当前位置:网站首页 > 更多 > 玩电脑 > 正文

[玩转系统] 终极 PowerShell 遥测提示

作者:精品下载站 日期:2024-12-14 07:53:54 浏览:15 分类:玩电脑

终极 PowerShell 遥测提示


好吧,我知道我不会满足。前几天我分享了一个 PowerShell 提示功能,可以显示一些远程服务器的遥测信息。缺点之一是我可以显示的信息量有限。我修改了该函数,并有了一个新版本,可以通过一些性能计数器显示附加信息。我还重新组织了该函数,使其更加高效。想看吗?

此版本仍然读取计算机名称列表。我仍然建议保持这个列表简短。虽然我已经修改了提示显示,以便每个服务器都有自己的线路。

[玩转系统] 终极 PowerShell 遥测提示

此版本的函数调用 Get-Counter 来检索附加信息。

#define a list of performance counters    
$c = "\processor(_total)\% processor time",
"\physicaldisk(_total)\% disk time",
"\server\bytes total/sec",
"\system\file control operations/sec" 


#create a hashtable of counters and values
get-counter -Counter $c | select-object -ExpandProperty countersamples |
    foreach-object -Begin {$counterhash = @{}} -process {
    $counterHash.add($_.Path.split("\")[-1], [math]::round($_.CookedValue, 2))
}

计数器数据被添加到每个服务器的输出中。

[玩转系统] 终极 PowerShell 遥测提示

为了视觉兴趣,我使用字符值的哈希表。棘手的部分是填充值以使所有内容都对齐。即便如此,也可能存在数据不完全对齐的情况。这通常会在您下次刷新时自行解决。

我也在尝试用这个提示做一些新的事情。当您运行命令时,PowerShell 希望自动调用提示功能。我插入了一个暂停命令(仅适用于 Windows)。当您按 Enter 时,屏幕将被清除,并且您将在 PowerShell 控制台顶部看到监控显示。

[玩转系统] 终极 PowerShell 遥测提示

如果您仅使用 PowerShell 控制台偶尔运行命令或只想定期刷新数据,这可能很有用。但是,您可以切换此功能。当您加载提示时,PowerShell 将定义一个名为 PromptClear 的全局变量,其值为 $True。运行 $PromptClear=$False 以关闭暂停和清除。将其设置回 $True 以将其重新打开。

现在你们中的一些人已经迫不及待地想尝试一下了。该文件托管在 GitHub 上。

TelemetryPrompt2.ps1:

#requires -version 5.1
#this requires a windows platform


$global:PromptClear = $true

Function prompt {
  
    if ($global:PromptClear) {
        Pause
        Clear-Host
    }

    $charHash = @{
        Up          = [char]0x25b2
        Down        = [char]0x25bc 
        Delta       = [char]0x2206 
        Pointer     = [char]0x25BA
        TopLeft     = [char]0x250c
        TopRight    = [char]0x2510
        Border      = [char]0x2500
        BottomLeft  = [char]0x2514
        BottomRight = [char]0x2518
        Ohm         = [char]0x2126
        Mu          = [char]0x3bc
        disk        = [char]0x058d
        bps         = [char]0x20bf
    }

    Try {
        #verify there is a global hashtable variable
        Get-Variable -Name rsHash -Scope global -ErrorAction Stop | Out-Null
    }
    Catch {
        #create the runspace and synchronized hashtable
        $global:rsHash = [hashtable]::Synchronized(@{Computername = $env:computername; results = ""; date = (Get-Date); computers = @()})
        $newRunspace = [runspacefactory]::CreateRunspace()
        #set apartment state if available
        if ($newRunspace.ApartmentState) {
            $newRunspace.ApartmentState = "STA"
        }
        $newRunspace.ThreadOptions = "ReuseThread"         
        $newRunspace.Open()
        $newRunspace.SessionStateProxy.SetVariable("rsHash", $rsHash)  

        $pscmd = [PowerShell]::Create().AddScript( {                      
            
                #define the path to the list of computers
                $script:listPath = "C:\scripts\watch.txt"
            
                #define scriptblock to run remotely
                $sb = {
                
                    #define a list of performance counters    
                    $c = "\processor(_total)\% processor time",
                    "\physicaldisk(_total)\% disk time",
                    "\server\bytes total/sec",
                    "\system\file control operations/sec" 

                    Try {        
                        $mem = Get-CimInstance -ClassName win32_operatingsystem -Property TotalVisibleMemorySize, FreePhysicalMemory -ErrorAction Stop -OperationTimeoutSec 2
                        $memUsage = ($mem.FreePhysicalMemory / $mem.TotalVisibleMemorySize) * 100 -as [int]
                        $disk = Get-CimInstance -Classname win32_logicaldisk -filter "deviceID = 'c:'" -Property DeviceID, Size, FreeSpace -ErrorAction Stop -OperationTimeoutSec 2
                        $diskFree = ($disk.FreeSpace / $disk.Size) * 100 -as [int]
                        #get a count of all processes except idle and system and subtract 1 for the remote connection
                        $proc = (Get-Process).Where( {$_.name -notmatch 'Idle|system'}).count - 1
                        $os = Get-CimInstance -ClassName win32_operatingsystem -Property lastbootupTime
                        $isUp = $True

                        #create a hashtable of counters and values
                        get-counter -Counter $c | select-object -ExpandProperty countersamples |
                            foreach-object -Begin {$counterhash = @{}} -process {
                            $counterHash.add($_.Path.split("\")[-1], [math]::round($_.CookedValue, 2))
                        }
                    }
                    catch {
                        #this will probably never be used
                        $memUsage = 0
                        $diskFree = 0
                        $isUp = $False
                        Processes = 0
                        OS = "" 
                        Counters - @{}
                    }
                    [pscustomobject]@{
                        Computername = $env:computername
                        MemoryUsage  = $memUsage
                        DiskFree     = $diskFree
                        Processes    = $proc
                        IsUp         = $IsUp
                        Uptime       = ((Get-Date) - $os.LastBootUpTime).toString("d\.hh\:mm\:ss")
                        Counters     = $counterhash
                    }
                } #end scriptblock
                
                #define a pssession option to speed up connections
                $opt = New-PSSessionOption -OpenTimeout 1000 -MaxConnectionRetryCount 1

                do {
                    #define the list of computers to test
                    #filter out blank lines and trim any spaces to clean up names.
                    #This should be a short list unless you increase the width of your console sessions
                    if (Test-Path -path $script:listPath ) {
                           $computers = Get-Content -Path $script:listpath |
                            Where-Object {$_ -match '\w+' -AND $_ -notmatch "#"} | Foreach-Object {$_.trim()} | Sort-Object
                    }
                    else {
                        #if path not found default to local computer
                        $computers = $env:computername
                    }

                    #make sure there are sessions for all computers in the list
                    $computers | Where-Object {(get-pssession).where( {$_.state -eq 'opened'}).computername -notcontains $_} |
                        ForEach-Object {
                        New-PSSession -ComputerName $_ -SessionOption $opt
                    }
                    #remove broken sessions
                    Get-PSSession | Where-Object {$_.state -eq 'broken'} | Remove-PSSession
                    $results = Invoke-Command -ScriptBlock $sb -HideComputerName  -Session (Get-PSSession) 

                    $global:rsHash.results = $results
                    $global:rsHash.date = Get-Date
                    $global:rshash.computers = $computers
                    #set a sleep interval between tests
                    Start-Sleep -Seconds 10
                } While ($True)
            }) # script
        $pscmd.runspace = $newrunspace
        [void]$psCmd.BeginInvoke()
    } #catch

    #guess at a line length

    # get longest name so shorter names can be padded
    $longest = ($global:rshash.computers |  sort-object length -Descending | select-object -first 1).length
    
    #account for a : after each name + character + value
    #you may have to tweak this value to get everything to line up
    #and it might depend on whether you are using the console or ISE
    $len = $longest + 75

    #display local computername and datetime
    $dt = "`n {2} {0} {1} " -f (get-date).toshortdatestring(), (get-date).TolongTimeString(), $env:computername
    Write-host $dt -ForegroundColor black -BackgroundColor gray
    
    Write-Host "$($charhash.topleft)" -NoNewline
    Write-Host ($($charHash.Border.ToString()) * $len ) -NoNewline
    Write-Host $charHash.topRight

    if ($global:rsHash.results) {
    
        #create a hashtable from the results
        $h = $global:rshash.results | Group-Object -Property Computername -AsHashTable -AsString

        #sort the results by computername
        foreach ($item in $global:rshash.computers) {

            if ($h[$item]) {
                $obj = $h[$item]
            }
            else {
                #create a temporary object for computer that is not running but in the list
                $obj = [pscustomobject]@{
                    Computername = $item.ToUpper()
                    Uptime       = (New-TimeSpan).toString()
                    DiskFree     = "00"
                    MemoryUsage  = "00"
                    Processes    = "00"
                    IsUp         = $false
                }
            }

            Write-Host " $($charhash.pointer) $(($obj.computername).padright($longest,' '))" -NoNewline            

            #only display results if computer is up
            
            if ($obj.IsUp) {
                Write-Host " $($charHash.Up)" -ForegroundColor green -NoNewline
                $upfg = "green"
            }
            else {
                Write-Host " $($charHash.down)" -ForegroundColor red -NoNewline
                $upfg = "red"
            }               
            
            if ($obj.IsUp) {
                if ($obj.DiskFree -le 20) {
                    $diskfg = "red"
                }
                elseif ($obj.DiskFree -le 75) {
                    $diskfg = "yellow"
                }
                else {
                    $diskfg = "green"
                }
                if ($obj.MemoryUsage -le 30) {
                    $memfg = "red"
                }
                elseif ($obj.MemoryUsage -le 60) {
                    $memfg = "yellow"
                }
                else {
                    $memfg = "green"
                }
                #format counter data
                $pctDiskTime = ("{0:N2}" -f $obj.counters.'% disk time').PadLeft(6, " ")
                $fileControl = ($obj.counters.'file control operations/sec').ToString().Padleft(9, " ")
                $pctProcTime = ("{0:N2}" -f $obj.counters.'% processor time').Padleft(6, " ")

                Write-Host $obj.Uptime.padleft(12,' ') -ForegroundColor $upfg -NoNewline
                Write-Host " $($charhash.disk)$(($obj.diskfree).toString().padleft(3,' '))%" -NoNewline -ForegroundColor $diskfg
                write-host " $($charHash.delta) $pctDiskTime" -NoNewline
                write-host " fc$filecontrol" -NoNewline
                write-host " $($charhash.ohm)$pctProcTime" -NoNewline
                Write-Host " $($charhash.mu)$($obj.MemoryUsage)%"-NoNewline -ForegroundColor $memfg 
                Write-Host " p$(($obj.Processes).tostring().padright(4,' '))"  -NoNewline
                write-host " $($charhash.bps) $($obj.counters.'bytes total/sec')"
            }
            else {
                write-host " "
            }
        } #foreach
    }
    else {
        Write-Host "Working..." -ForegroundColor yellow 
    }

    Write-Host $charHash.BottomLeft -NoNewline
    Write-Host ($($charHash.Border.ToString()) * $len ) -NoNewline
    Write-Host $charHash.BottomRight

    "PS $($executionContext.SessionState.Path.CurrentLocation)$('>' * ($nestedPromptLevel + 1)) "

}

你怎么认为?我对这个概念的理解是否足够深入?这对你们中的任何人来说实用吗?为了让这项工作对你有用,你做了什么?我希望您发现这很有用,或者至少从代码中获得一两个提示。享受。

您需要 登录账户 后才能发表评论

取消回复欢迎 发表评论:

关灯