web-dev-qa-db-ja.com

netstatの問題を使用してポートと同じ行にプロセスを表示するPowershellワンライナー

まず、ユーザーErik Bitemoがここで使用している元のコードのクレジットを確実に取得できるようにしたいと思います。出力は、私が探しているものですが、1つの例外があります。ポートの1つが消え、代わりに「System System5」が表示され、なぜそれが起こっているのか理解できません。

目標:すべてのTCP(リッスン)ポートとUDPポート、およびそれぞれに関連付けられているプロセスを同じ行に表示します。

使用されている1つのライナー:

$nets = netstat -bano|select-string 'LISTENING|UDP'; foreach ($n in $nets)    {    $p = $n -replace ' +',' ';    $nar = $p.Split(' ');    $pname = $(Get-Process -id $nar[-1]).ProcessName;    $n -replace "$($nar[-1])","$($ppath) $($pname)";     }

出力例:

TCP 0.0.0.0:135 0.0.0.0:0リスニングsvchost
TCP 0.0.0.0:System System5 0.0.0.0:0 LISTENING System
TCP 0.0.0.0:623 0.0.0.0:0リスニングLMS

変更されるポートは445ですが、残りのポートが意図したとおりに機能しているのに、なぜそれだけが変更されるのかわかりません。スクリプトが445を「System System5」に変更するのはなぜですか?

残念ながら、他のツールを使用することは不可能なので、組み込みのWindowsツールの使用に限定されています。

4
Ric

$pTCP 0.0.0.0:445 0.0.0.0:0 LISTENING 4のようなもので、$nar[-1]は文字列4なので、-replace演算子はall4s:

TCP 0.0.0.0:445 0.0.0.0:0 LISTENING 4
            ↑↑                      ↑

行末アンカー(エスケープされた$nar[-1])を使用して、$の最後の出現のみを強制的に置換します。

$p -replace "$($nar[-1])`$","$ppath $pname"

Stackoverflowでのマットの回答 文字列内のサブストリングの最後のオカレンスの置換 も読んでください。

ところで:

  • $ppathが定義されていません…
  • …そしてnetstat -anoで十分です(-bオプションは時間がかかる可能性があり、十分な権限がないと失敗します)。
4
JosefZ

JosefZの答え は問題を完全に説明しています。あなたは正規表現を使用していて、おそらくあなたが期待以上のものを置き換えるだけでいいようにあなたが求めていることを正確に実行しています。

補足として、netstat

各接続またはリスニングポートの作成に関連する実行可能ファイルを表示します

bスイッチ付き。ただし、そのプロセスは他のデータの後に独自の行に表示されるため、select-stringでそれを削除しています。それは世界の終わりではありませんが、-ContextSelect-Stringのようなものを使用してそれを取得することができますが、別の機会にもっと詳しく調べる必要があるためです。

この状況で何ができるかについて他の提案をしたいと思います。

残念ながら、他のツールを使用することは不可能なので、組み込みのWindowsツールの使用に限定されています。

面白いことに、Windows 8以降はありますか?その場合は、基本的にオブジェクト形式でnetstatである Get-NetTCPConnection コマンドレットを使用するだけで済みます。

だからあなたはこれを行うことができ、手間をかけずに同じ情報を得ることができます

get-nettcpconnection | select local*,remote*,state,@{Name="Process";Expression={(Get-Process -Id $_.OwningProcess).ProcessName}}

Windows 8以降をお持ちではありませんか?それでは、解析スクリプトを改善することができます。さらに一歩進んでオブジェクトを作成すると、正規表現マッチングの問題が回避されます。

netstat -ano | Where-Object{$_ -match 'LISTENING|UDP'} | ForEach-Object{
    $split = $_.Trim() -split "\s+"
    [pscustomobject][ordered]@{
        "Proto" = $split[0]
        "Local Address" = $split[1]
        "Foreign Address" = $split[2]
        # Some might not have a state. Check to see if the last element is a number. If it is ignore it
        "State" = if($split[3] -notmatch "\d+"){$split[3]}else{""}
        # The last element in every case will be a PID
        "Process Name" = $(Get-Process -Id $split[-1]).ProcessName
    }
}

PowerShell v2に限定されている場合は、psobjectと順序付けされたキャストを変更する必要があります

netstat -ano | Where-Object{$_ -match 'LISTENING|UDP'} | ForEach-Object{
    $split = $_.Trim() -split "\s+"
    New-Object -Type pscustomobject -Property @{
        "Proto" = $split[0]
        "Local Address" = $split[1]
        "Foreign Address" = $split[2]
        # Some might not have a state. Check to see if the last element is a number. If it is ignore it
        "State" = if($split[3] -notmatch "\d+"){$split[3]}else{""}
        # The last element in every case will be a PID
        "Process Name" = $(Get-Process -Id $split[-1]).ProcessName
    }
} | Select "Proto", "Local Address", "Foreign Address", "State", "Process Name" 

最後のselectステートメントは、プロパティの順序を保証します。そうでない場合はシャッフルされ、[ordered]と機能的に同等です。

だからあなたはこのように出力するでしょう...

Proto Local Address Foreign Address State     Process Name  
----- ------------- --------------- -----     ------------  
TCP   0.0.0.0:135   0.0.0.0:0       LISTENING svchost       
TCP   0.0.0.0:445   0.0.0.0:0       LISTENING System        
TCP   0.0.0.0:1279  0.0.0.0:0       LISTENING PlexDlnaServer
TCP   0.0.0.0:2869  0.0.0.0:0       LISTENING System  

これは、PowerShellオブジェクトやフィルターと同じように扱うことができ、CSVへの適合や出力など必要な処理を行うことができます。それは今構造化されています。

PowerShellのバージョンに応じて、 Convert-FromString を使用することもできます。これは、1行の文字列を受け取り、それらもオブジェクトに変換します。何か別のものを調べます。

6
Matt

よりシンプル...

filter timestamp {"$(Get-Date -Format G): $_"};netstat -abno 1 | Select-String -Context 0,1 -Pattern LISTENING|timestamp
0
Jhon Willmaure