Powershell - Start-ThreadJob ID增加非常快,为什么?

7gyucuyw  于 2023-03-12  发布在  Shell
关注(0)|答案(1)|浏览(99)

Powershell和Stackoverflow新手。这是我的第一个Powershell脚本,我正试图尽我所能优化它。我的目标是让代码尽可能高效地运行。在这方面的任何帮助/建议都将不胜感激!
此脚本显示新的“Established”TCP连接(Get-NetTCPConnection)及其关联的DNS主机名(Resolve-DnsName)。将每个新连接与以前连接的数组进行比较。如果它们具有相同的“*RemoteAddress *”,则DNS主机名将复制到新连接并显示;否则,它将创建一个新的(Resolve-DnsName)(Start-ThreadedJob),并继续移动到下一个新连接。一旦作业为“Completed”,它将复制“NameHost”并显示该连接。
我的理解遇到了一个障碍。当代码运行时,作业“Ids”似乎增加得非常快,即使在上一个作业和新作业之间没有创建新作业。
要测试该脚本,请运行该脚本并访问任意站点。请观察“Id”是否快速增加。请注意,它将在“C:\Temp\Active_Connections.csv”中创建日志文件

$logFile = 'C:\Temp\Active_Connections.csv'
if (-not(Test-Path $logFile -PathType Leaf)){
    New-Item -ItemType File -Force -Path $logFile | Out-Null
    } else {
    Clear-Content $logFile
}
$headersAdded = $true
$newConnections = @()
While ($true){
    $connections = @(Get-NetTCPConnection)
    foreach ($connection in $connections){
        if ($connection.State -eq "Established"){
            if ($newConnections.InstanceID -notcontains $connection.InstanceID){
                if ($newConnections.RemoteAddress -notcontains $connection.RemoteAddress){
                    if ((Get-Job).Name -notcontains $connection.RemoteAddress){
                        Start-ThreadJob -Name $connection.RemoteAddress -ScriptBlock {param($remoteAddress) Resolve-DNSName -Name $remoteAddress} -ArgumentList $connection.RemoteAddress >$null
                    }else{
                        $job = Get-Job | Where-Object {$_.Name -eq $connection.RemoteAddress}
                        if ($job.State -eq "Completed"){
                            Add-Member -InputObject $connection -MemberType NoteProperty -Name "Id" -Value $job.Id -Force
                            Try {
                                $receivedJob = $job | Receive-Job -ErrorAction Stop
                                Add-Member -InputObject $connection -MemberType NoteProperty -Name "NameHost" -Value $receivedJob.NameHost -Force
                            }catch{
                                $na = "N/A"
                                Add-Member -InputObject $connection -MemberType NoteProperty -Name "NameHost" -Value $na -Force
                            }
                            #Remove-Job -Id $job.Id
                        }
                    }
                }else{
                    foreach ($newConnection in $newConnections){
                        if ($newConnection.RemoteAddress -eq $connection.RemoteAddress){
                            Add-Member -InputObject $connection -MemberType NoteProperty -Name "NameHost" -Value $newConnection.NameHost -Force
                        }
                    }
                }
            }
            if ($null -ne $connection.NameHost){
                if ($headersAdded) {
                    $formatting = @{n='CreationTime';e={$_.CreationTime.ToString("h:mm:ss tt")}},'Id','LocalAddress','LocalPort','RemoteAddress','RemotePort','NameHost'
                    $properties = @{Expression="CreationTime";Width=13},@{Expression="Id";Width=4},@{Expression="LocalAddress";Width=15},@{Expression="LocalPort";Width=10;Alignment="Left"},@{Expression="RemoteAddress";Width=15},@{Expression="RemotePort";Width=10;Alignment="Left"},@{Expression="NameHost";Width=100}
                    ($connection | Select-Object $formatting | Format-Table -Property $properties | Out-String).Trim() | Tee-Object -FilePath $logFile -Append
                    $headersAdded = $false
                } else {
                    ($connection | Select-Object $formatting | Format-Table -HideTableHeaders -Property $properties | Out-String).Trim() | Tee-Object -FilePath $logFile -Append
                }
                $newConnections += $connection
            }
        }
    }
}

请,让我知道我可以做得更好,如果你有任何想法,为什么工作ID的增加这么快之间的新连接。
谢谢你的帮助克里斯

djmepvbi

djmepvbi1#

  • 我对作业ID值的跳跃没有任何解释,虽然知道原因是很好的,但实际上这并不一定是个问题。
  • 您的代码会创建tight loop,这是最好避免的。
  • 下面是代码的一个PowerShell惯用的重新表述,它尝试尽可能早地获得结果,同时在两次尝试之间休眠一段固定的时间(显然可以调整)。
  • 结果是输出对象不一定要按“时间顺序”排序。
  • 输出对象的Id属性(列)反映Get-NetTCPConnection返回的原始输出顺序
# NOTE: What is created is NOT a CSV file.
#       It is a plain-text file in tabular format FOR THE HUMAN OBSERVER.
$logFile = 'C:\Temp\Active_Connections.csv'
& {
  $newConnections = [ordered] @{} # (Ordered) hashtable that stores all new connections.
  while ($true) {
    # Look for new connections, and start a thread job for each 
    # in order to resolve the remote adddress to a domain name, if possible.
    Get-NetTCPConnection | 
      Where-Object { $_.State -eq 'Established' -and -not $newConnections.Contains($_.InstanceID) } |
      ForEach-Object {
        $jb = Start-ThreadJob { Resolve-DNSName -Name ($using:_).RemoteAddress }
        $newConnections[$_.InstanceID] = 
          $_ |
            Select-Object CreationTime,
              @{
                n = 'Id'
                e = { $jb.Id }
              },
              LocalAddress, LocalPort, RemoteAddress, RemotePort, 
              @{
                n = 'NameHost'
                e = { $jb }
              }
      }
    # Sleep a little, to avoid a tight loop.
    Start-Sleep -Milliseconds 300
    # Look for thread jobs that have completed, and output
    # the connection-info objects with the job result.
    $newConnections.Keys |
      ForEach-Object {
        if (($obj = $newConnections[$_]) -and ($jb = $obj.NameHost).State -notin 'NotStarted', 'Running') { 
          # A completed job: get its result.
          $result = try { $jb | Receive-Job -ErrorAction Stop } catch { @{ NameHost = 'n/a' } }
          $jb | Remove-Job -Force # Remove the completed job.
          $obj.NameHost = $result.NameHost # Update the object with the job result.
          $obj # Output the updated object.
          $newConnections[$_] = $null # No need to hang on to the object in the hasthable.
        }
      }
  }
} |
  Format-Table  @{ Name = 'CreationTime'; Expression = { $_.CreationTime.ToString('h:mm:ss tt') }; Width = 13 }, 
                @{Expression = "Id"; Width = 4 }, 
                @{Expression = "LocalAddress"; Width = 15 }, 
                @{Expression = "LocalPort"; Width = 10; Alignment = "Left" },
                @{Expression = "RemoteAddress"; Width = 15 }, @{Expression = "RemotePort"; Width = 10; Alignment = "Left" }, 
                @{Expression = "NameHost"; Width = 100 } |
  Tee-Object -FilePath $logFile

相关问题