3

Во-первых, я просто хочу убедиться, что пользователь 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 СЛУШАТЬ svchost
TCP 0.0.0.0: Система System5 0.0.0.0:0 СЛУШАТЬ систему
TCP 0.0.0.0:623 0.0.0.0:0 LISTENING LMS

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

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

3 ответа3

3

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

Примечание: вы просите netstat

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

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

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

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

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

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

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] order ]

Так что это даст вам вывод, как это ...

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

3

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

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 может занять много времени и завершится ошибкой, если у вас нет достаточных разрешений).
0

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

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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .