Powershell one-liner для отображения процесса на той же строке, что и порт, используя проблему netstat

3259
Ric

Сначала я просто хочу убедиться, что пользователь Erik Bitemo получает кредит на оригинальный код, который я здесь использую. Вывод - это то, что я ищу за одним исключением: один из портов исчезает, и на его месте появляется «System System5», и я не могу понять, почему это происходит.

Цель: показать все порты TCP (прослушивание) и UDP и процесс, связанный с каждым на одной линии.

Один используемый вкладыш:

$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 LISTENING 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 LISTENING LMS

Порт, который он меняет, - 445, но я понятия не имею, почему он меняет только тот, когда остальные порты работают как положено. Почему скрипт меняет 445 на "System System5"?

Использование других инструментов, к сожалению, невозможно, поэтому я ограничен использованием встроенных инструментов Windows.

3
Пожалуйста [отредактируйте] вопрос и предоставьте необработанный вывод из `netstat -bano | select-string 'LISTENING | UDP'` DavidPostill 6 лет назад 0

3 ответа на вопрос

3
JosefZ

$pможет быть что - то вроде TCP 0.0.0.0:445 0.0.0.0:0 LISTENING 4и $nar[-1]есть строка 4поэтому -replaceоператор принимает все 4 S:

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

Принудительно заменить только последнее вхождение при $nar[-1]использовании привязки конца строки (экранированный $):

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

Прочтите также ответ Мэтта на « Замена последнего появления подстроки в строке при стеке потока».

КСТАТИ:

  • $ppath не определено…
  • … И netstat -anoдолжно быть достаточно (обратите внимание, что эта -bопция может занимать много времени и потерпит неудачу, если у вас нет достаточных разрешений).
Вы нашли проблему наверняка. Я также предложил предложения по этому вопросу, если вам интересно. Matt 6 лет назад 0
3
Matt

Ответ JosefZ прекрасно объясняет вашу проблему. Вы используете регулярное выражение, и оно делает именно то, о чем вы его просили, возможно, заменяя больше, чем вы ожидали.

Примечание стороны является то, что вы просите, netstatчтобы

отображает исполняемый файл, участвующий в создании каждого соединения или порта прослушивания

с переключателем b. Однако вы отбрасываете это с, select-stringтак как этот процесс появляется в отдельной строке после других данных. Это не конец света, а потому, что вы можете использовать такие вещи, как -Contextиз, Select-Stringчтобы получить это, но это будет смотреться на более близко другое время.

Я хотел бы предложить другие предложения относительно того, что вы можете сделать в этой ситуации.

Использование других инструментов, к сожалению, невозможно, поэтому я ограничен использованием встроенных инструментов Windows.

Забавно, у вас есть хотя бы Windows 8? Если вы это сделаете, вы можете просто использовать Get-NetTCPConnectionкомандлет, который по существу netstatв форме объекта.

Таким образом, вы можете сделать это, чтобы получить ту же информацию без хлопот

get-nettcpconnection | select local*,remote*,state,@} 

У вас нет 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однострочные строки и преобразовывать их в объекты. Что-то еще, чтобы искать.

Это было очень полезно. Спасибо за помощь. Ric 6 лет назад 0
Ваше решение было бы идеальным, но, похоже, оно требует как минимум Powershell 3 или 4. При запуске на компьютере с Windows 7 оно сразу выдает ошибку. Можно ли внести какие-либо изменения, чтобы избежать этого? Ошибка «Невозможно найти тип [упорядоченный]: убедитесь, что сборка, содержащая этот тип, загружена». Ric 6 лет назад 0
Эти броски вызовут проблему да. Легко обратиться хотя. Я добавлю быстрое обновление для вас. Matt 6 лет назад 1
Информация о процессе недоступна в Windows 2012 (не R2). Скорее всего, он также не доступен в Windows 8.0. Thorarin 5 лет назад 0
0
Jhon Willmaure

Более простой...

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

Похожие вопросы