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

[玩转系统] PowerShell 网络监视器

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

PowerShell 网络监视器


我希望您一直在尝试解决 Iron Scripter 网站上发布的脚本挑战。这些挑战是为个人自行完成而设计的,以培养他们的 PowerShell 脚本技能。几周前,发布了一个使用 PowerShell 和 Write-Progress cmdlet 创建网络监控工具的挑战。我想分享一下我对挑战的笔记以及我想出的一些代码。

中级挑战

第一步是确定 Get-Counter 所需的性能计数器。

$counters = "\Network interface(*ethernet*)\Bytes sent/sec",
"\Network interface(*ethernet*)\Bytes received/sec",
"\Network interface(*ethernet*)\Bytes total/sec"

有了这些,我可以使用 Get-Counter 来检索数据。

Get-Counter -Counter $counters -MaxSamples 10 -SampleInterval 1 -ov d | 
Select-object -ExpandProperty CounterSamples | Select-Object -Property Timestamp,
@{Name="Computername";Expression = {[regex]::Match($_.path, "(?<="\)\w+").Value.toUpper() }},
@{Name = "Counter"; Expression = { ($_.path -split "\")[-1]}},
@{Name = "Network"; Expression = {$_.instancename}},
@{Name = "Count"; Expression = {$_.cookedValue}}

我正在从计数器示例属性中解析出值。

[玩转系统] PowerShell 网络监视器

如果我想更进一步,我可以将输出定义为自定义对象并创建一个格式 ps1xml 文件来清理显示。

先进的

高级挑战是使用 Write-Progress 创建一个可视化工具。该 cmdlet 允许您在同一窗口中拥有多个进度条。您可以通过 ID 号来引用它们。这意味着我必须划分柜台。

Get-Counter -Counter $counters -MaxSamples 30 -SampleInterval 1  |
ForEach-Object {
    $network = $_.countersamples[0].InstanceName
    $computername = [regex]::Match($_.CounterSamples[0].path, "(?<="\)\w+").Value.toUpper()
    $time = $_.timestamp
    $total = $_.countersamples.where( {$_.path -match "total"})
    $totalKbps = $total.cookedValue*0.008
    if ($totalKbps -gt 100) {
        $totalPct = 100
    }
    else {
        $totalPct = $totalKbps
    }
    $sent = $_.countersamples.where( {$_.path -match "sent"})
    $sentKbps = $sent.cookedValue*0.008
    if ($sentKbps -gt 100) {
        $sentPct = 100
    }
    else {
        $sentPct = $sentKbps
    }
    $rcvd = $_.countersamples.where( {$_.path -match "received"})
    $rcvdKbps = $rcvd.cookedValue*0.008
    if ($rcvdKbps -gt 100) {
        $rcvdPct = 100
    }
    else {
        $rcvdPct = $rcvdKbps
    }
    Write-Progress -Activity "[$time] $computername : $network" -status "Total Kbps $totalKbps" -id 1 -PercentComplete $totalpct
    Write-Progress -Activity " " -status "Send Kbps $sentKbps" -id 2 -PercentComplete $sentpct
    Write-Progress -Activity " " -status "Received Kbs $rcvdKbps" -id 3 -PercentComplete $rcvdpct

}

另一个好处是将数据格式化为 Kbps。据我所知,如果我将字节值乘以 0.008,我就会得到我想要的。我还必须考虑进度条的长度,因为它显然不能超过 100。因此显示是相对的,而不是真实的图表。

在测试过程中,我发现 Windows PowerShell 中的 Write-Progress 似乎存在显示错误,无法准确生成我想要的结果。但它在 PowerShell 7 中运行得很好。

[玩转系统] PowerShell 网络监视器

获取网络性能

我将所有这些整合到一个 PowerShell 函数中。

Function Get-NetworkPerformance {
    [cmdletbinding(DefaultParameterSetName = "sample")]
    [alias("gnp")]
    Param(
        [Parameter(HelpMessage = "Specify a computer to connect to.")]
        [string]$Computername = $env:computername,
        [Parameter(HelpMessage = "Use the network description from Get-NetAdapter")]
        [string]$NetworkInterface = "*ethernet*",
        [Parameter(ParameterSetName = "continuous")]
        [switch]$Continuous,
        [Parameter(Mandatory, ParameterSetName = "sample")]
        [int64]$MaxSamples,
        [Parameter(Mandatory, ParameterSetName = "sample")]
        [Int32]$SampleInterval,
        [switch]$Passthru
    )

    Write-Verbose "Starting $($MyInvocation.MyCommand)"
    Write-Verbose "Detected parameter set $($pscmdlet.ParameterSetName)"
    Write-Verbose "Validating network interface"
    #updated 12 Oct 2021 to make sure only a single network adapter is selected 
    $c = (Get-NetAdapter -InterfaceDescription $NetworkInterface -CimSession $Computername | Where-Object { $_.status -eq 'up' }).count
    if ($c -gt 1) {
        Throw "You must specify a single network interface."
    }
    Write-Verbose "Verified a single network interface"
    #save the current progressbar setting
    $bg = $host.PrivateData.progressBackgroundColor

    #the networking counters
    $counters = "\Network interface($NetworkInterface)\Bytes sent/sec",
    "\Network interface($NetworkInterface)\Bytes received/sec",
    "\Network interface($NetworkInterface)\Bytes total/sec"

    $PSBoundParameters.Add("counter", $counters)

    if ($PSBoundParameters.ContainsKey("Passthru")) {
        [void]( $PSBoundParameters.Remove("passthru"))
    }

    if ($PSBoundParameters.ContainsKey("NetworkInterface")) {
        [void]( $PSBoundParameters.Remove("NetworkInterface"))
    }
    Write-Verbose "Passing these parameters to Get-Counter:`n $($PSBoundParameters | Out-String)"

    Try {
        Get-Counter @PSBoundParameters -OutVariable pass -ErrorAction Stop |
        ForEach-Object {
            $network = $_.countersamples[0].InstanceName
            $computername = [regex]::Match($_.CounterSamples[0].path, "(?<="\)\w+").Value.toUpper()
            $time = $_.timestamp
            $total = $_.countersamples.where( { $_.path -match "total" })
            $totalKbps = $total.cookedValue * 0.008
            #adjust the progressbar color
            if ($totalKbps -ge 150) {
                $host.PrivateData.progressBackgroundColor = "Red"
            }
            else {
                $host.PrivateData.progressBackgroundColor = $bg
            }
            if ($totalKbps -gt 100) {
                $totalPct = 100
            }
            else {
                $totalPct = $totalKbps
            }
            $sent = $_.countersamples.where( { $_.path -match "sent" })
            $sentKbps = $sent.cookedValue * 0.008
            if ($sentKbps -gt 100) {
                $sentPct = 100
            }
            else {
                $sentPct = $sentKbps
            }
            $rcvd = $_.countersamples.where( { $_.path -match "received" })
            $rcvdKbps = $rcvd.cookedValue * 0.008
            if ($rcvdKbps -gt 100) {
                $rcvdPct = 100
            }
            else {
                $rcvdPct = $rcvdKbps
            }

            Write-Progress -Activity "[$time] $computername : $network" -Status "Total Kbps $totalKbps" -Id 1 -PercentComplete $totalpct
            Write-Progress -Activity " " -Status "Send Kbps $sentKbps" -Id 2 -PercentComplete $sentpct
            Write-Progress -Activity " " -Status "Received Kbs $rcvdKbps" -Id 3 -PercentComplete $rcvdpct
        }
    } #Try
    Catch {
        Write-Warning "Failed to get performance counters. $($_.Exception.message)"
    }

    if ($passthru -AND $pass) {
        Write-Verbose "Passing results to the pipeline"
        $pass
    }

    #restore the progressbar value
    $host.PrivateData.progressBackgroundColor = $bg
    Write-Verbose "Ending $($MyInvocation.MyCommand)"
}

该功能提供了灵活性和易用性。

[玩转系统] PowerShell 网络监视器

在解决这个挑战的过程中我什至学到了一些新东西,这才是重点。我希望你能尝试一下挑战。每个技能级别都有测试。祝你好运。

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

取消回复欢迎 发表评论:

关灯