Tìm kiếm trang web

Trình giám sát mạng PowerShell


Tôi hy vọng bạn đã thử sức mình với các thử thách viết kịch bản được đăng trên trang web Iron Scripter. Các thử thách được thiết kế để các cá nhân tự thực hiện nhằm xây dựng kỹ năng viết kịch bản PowerShell của mình. Một vài tuần trước, một thử thách đã được đăng tải nhằm tạo ra một công cụ giám sát mạng bằng cách sử dụng PowerShell và lệnh ghép ngắn Write-Progress. Tôi nghĩ tôi nên chia sẻ những ghi chú của mình về thử thách và một số đoạn mã mà tôi nghĩ ra.

Thử thách trung cấp

Bước đầu tiên là xác định các bộ đếm hiệu suất cần thiết cho Get-Counter.

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

Với những thứ này, tôi có thể sử dụng Get-Counter để lấy dữ liệu.

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}}

Tôi đang phân tích các giá trị từ thuộc tính mẫu truy cập.

Nếu tôi muốn tiến thêm một bước nữa, tôi có thể xác định đầu ra là một đối tượng tùy chỉnh và tạo tệp ps1xml định dạng để dọn dẹp màn hình.

Trình độ cao

Thử thách nâng cao là tạo ra một công cụ trực quan bằng cách sử dụng Write-Progress. Lệnh ghép ngắn cho phép bạn có nhiều thanh tiến trình trong cùng một cửa sổ. Bạn có thể tham khảo chúng bằng số ID. Điều này có nghĩa là tôi phải chia các quầy ra.

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

}

Một yếu tố bổ sung khác là định dạng dữ liệu dưới dạng Kbps. Theo như tôi biết, nếu tôi nhân giá trị byte với 0,008 thì tôi sẽ nhận được thứ mình muốn. Tôi cũng phải tính đến độ dài của thanh tiến trình vì rõ ràng nó không thể vượt quá 100. Do đó, màn hình chỉ mang tính tương đối và không phải là biểu đồ thực.

Khi kiểm tra điều này, tôi nhận thấy rằng Write-Progress trong Windows PowerShell dường như có một lỗi hiển thị không tạo ra chính xác những gì tôi nghĩ. Nhưng nó hoạt động tốt trong PowerShell 7.

Nhận-Hiệu suất mạng

Tôi kết hợp tất cả những thứ này lại thành một hàm 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)"
}

Chức năng này mang lại sự linh hoạt và dễ sử dụng.

Tôi thậm chí còn học được một số điều mới khi giải quyết thử thách này, đó thực sự là mấu chốt. Tôi hy vọng bạn sẽ thử sức mình với các thử thách. Có các bài kiểm tra cho mọi cấp độ kỹ năng. Chúc may mắn.

Bài viết liên quan