読者です 読者をやめる 読者になる 読者になる

tech.guitarrapc.cóm

C#, PowerShell, Unity, Cloud, Serverless Technical Update and Features

PowerShell で TCP/IP 接続監視をしたい

前回、 netstat が PowerShell では オブジェクトとして取得できることを紹介しました。

PowerShell で netstat をするにはどうするの

この記事では単純に Group-Object した結果として、状態に応じてグルーピングしましたが、今回はログ監視として横に並べたい時の出力を考えてみましょう。 ====

欲しい形式はどういう感じ?

前回の記事では、 Group-Object で縦に並べました。

Get-NetTCPConnection | group state -NoElement

# 結果
Count Name                     
----- ----                     
   83 Established              
   29 Listen                   
    8 TimeWait                 
    6 CloseWait 

これは、ちょろっととって確認するにはいいのです。 でも、ログで後から見直すには不便ですよねー、取り込め直せないし。 欲しいのはこのような形式です。

date                   Established Listen TimeWait CloseWait
----                   ----------- ------ -------- ---------
2013/09/03 08:56:03:40          57     31       26         6

サンプル1

Object[] を PSCustomObject に作り変える必要があります。 まず、一つ目のサンプルがこういった感じ?

function Get-NetTCPConnectionCheck{

    [CmdletBinding()]
    param(

    )
    
    begin
    {
        $result = [ordered]@{}
    }

    process
    {
        $result.date = (Get-Date).ToString("yyyy/MM/dd HH:mm:dd:ss")

        $connection = Get-NetTCPConnection
        $status = ($connection | group state -NoElement).Name

        foreach ($c in $($connection | group State -NoElement))
        {
            $status | %{
                $s = $_
                if *1
        {
            $status | %{
                $s = $_
                if (($c | where Name -eq $s).Name -ne $null)
                {
                    $result.Add("$(($c | where Name -eq $s).Name)", ($c | where Name -eq $s).count)
                }
            }
        }
    }

    end
    {
        return [PSCustomObject]$result
    }

}

大分やぼったいです。 まぁ、実行してみます。

"Date, Listen, Established, TimeWait, CloseWait, LastAck" | Out-File -Encoding utf8 -FilePath c:\logs\tcpconnection.log
while (1)
{
    $result = Get-NetTCPConnectionCheck
    "$($result.date), $($result.Established), $($result.CloseWait), $($result.Listen)" | Out-File -Encoding utf8 -FilePath c:\logs\tcpconnection.log -Append
    sleep 1
}

結果は、当然ずれずに取得できます。

date                                                     Established                            Listen                         CloseWait
----                                                     -----------                            ------                         ---------
2013/09/03 08:59:03:07                                            44                                31                                42
2013/09/03 08:59:03:08                                            44                                31                                42
2013/09/03 08:59:03:09                                            44                                31                                42
2013/09/03 08:59:03:10                                            44                                31                                42
2013/09/03 08:59:03:11                                            44                                31                                42
2013/09/03 08:59:03:12                                            44                                31                                42

実際、裏では知らせてログ取得するならこれで十分です。 取り込んだログは、 " " 半角スペースを delimiter として Import-CSV で取り込みも可能なので分析も容易でしょう。 あとはテキトーにちょちょいと触れば自在ですね。 netstat より簡単で気楽に作れていいものです。

GitHub

置いておきます。

https://github.com/guitarrapc/PowerShellUtil/tree/master/Get-NetTCPConnectionCheck

追記

Sep/4/2013 牟田口せんせーが解決エントリを下さいました。

PowerShell Scripting Weblog TCP/IP接続監視

.contains と } | ft がなるほどでした。 で、私ならどうするか。最終的にはこうかなーとか。

function Get-NetTCPConnectionCheck{

    [CmdletBinding()]
    param(

    )
    
    begin
    {
        $result = [ordered]@{}
    }

    process
    {
        $result.date = (Get-Date).ToString("yyyy/MM/dd HH:mm:dd:ss")
        @("Listen","Established","TimeWait","CloseWait","LastAck","FinWait2") | %{$result.$_ = 0}

        Get-NetTCPConnection | group state -NoElement | where name -in $result.Keys | %{$result.$($_.name) = $_.count}
    }

    end
    {
        return [PSCustomObject]$result
    }

}

# 例のごとく $_ と Export を分岐
&{
    while($true)
    {
        Get-NetTCPConnectionCheck | %{
            $_ | Export-Csv -Path D:\hoge.csv -NoClobber -NoTypeInformation -Append -Encoding UTF8
            $_}
        sleep -Seconds 1
    }
} | Format-Table

Format-Table に -Autosize は使えません。理由?分かりますよね。Autosizeするには結果を全部得ておく必要がありますが、これでは結果が得られないからです。 で、出力すると....やったね。

date                     Listen   Established   TimeWait   CloseWait    LastAck   FinWait2
----                     ------   -----------   --------   ---------    -------   --------
2013/09/04 07:01:04:37       31            49          3           4          0          1
2013/09/04 07:01:04:38       31            49          3           4          0          1
2013/09/04 07:01:04:39       31            50          3           4          0          1
2013/09/04 07:01:04:41       31            49          3           4          0          1
2013/09/04 07:01:04:42       31            49          3           4          0          1
2013/09/04 07:01:04:43       31            49          3           4          0          1
2013/09/04 07:01:04:44       31            49          3           4          0          1
2013/09/04 07:01:04:45       31            49          3           4          0          1
2013/09/04 07:01:04:46       31            49          3           4          0          1
2013/09/04 07:01:04:47       31            50          3           3          0          1
2013/09/04 07:01:04:48       31            50          3           3          0          1
2013/09/04 07:01:04:49       31            50          3           3          0          1
2013/09/04 07:01:04:50       31            50          3           3          0          1

# ちなみにこれはダメです。

&{
    while($true)
    {
        Get-NetTCPConnectionCheck
        sleep -Seconds 1
    }
} | ConvertTo-Csv -NoTypeInformation | Tee-Object d:\hoge.csv -Append | Format-Table

画面出力も こうなっちゃうので

"date","Listen","Established","TimeWait","CloseWait","LastAck","FinWait2"
"2013/09/04 07:06:04:47","31","62","20","3","0","1"
"2013/09/04 07:06:04:49","31","62","20","3","0","1"

大枠は出来たので、ポート指定とかは parameter / switch 指定で自在に出来るでしょう。 脱netstat ここになりました。 ちなみに SumoLogic で取り込むとかするなら ConvertTo-Json にして Out-File でいいでしょう。

*1:$c | where Name -eq $s).Name -ne $null) { $result.Add("$(($c | where Name -eq $s).Name)", ($c | where Name -eq $s).count) } } } } end { return [PSCustomObject]$result } }

実行してみます。

while (1)
{
    Get-NetTCPConnectionCheck
    sleep 1
}

出力結果です。

date        : 2013/09/04 03:46:04:27
Established : 54
Listen      : 31
CloseWait   : 4
TimeWait    : 1
FinWait2    : 1

date        : 2013/09/04 03:46:04:28
Established : 54
Listen      : 31
TimeWait    : 1
CloseWait   : 2
FinWait2    : 1

date        : 2013/09/04 03:46:04:30
Established : 54
Listen      : 31
TimeWait    : 1
CloseWait   : 2
FinWait2    : 1

んー、 Format-List 表示になってしまいました... Format-Table を付けても -HideTableHeaders を付けても..... ぬぐぅ

date                              Established                 Listen               TimeWait              CloseWait              FinWait2
----                              -----------                 ------               --------              ---------              --------
2013/09/04 03:44:04:51                     60                     31                      5                      2                     1



date                              Established                 Listen               TimeWait              CloseWait              FinWait2
----                              -----------                 ------               --------              ---------              --------
2013/09/04 03:44:04:52                     60                     31                      2                      2                     1



date                              Established                 Listen               TimeWait              CloseWait              FinWait2
----                              -----------                 ------               --------              ---------              --------
2013/09/04 03:44:04:53                     60                     31                      2                      2                     1

しかも、取得結果の Propertyを動的に取得しているが故に、ログ出力した時に状況によってはプロパティの順序が変わったりします。 ホスト画面で使っている分にはまぁ、はぁ。

サンプル2

ログでずれるのは困ります。しょうがないので、欲しいステータスだけ指定してみしましょう。 TCP State を全て指定してもいいですが、とりあえず良くあるので。

function Get-NetTCPConnectionCheck{

    [CmdletBinding()]
    param(

    )
    
    begin
    {
        $result = @{}
    }

    process
    {
        $result.date = (Get-Date).ToString("yyyy/MM/dd HH:mm:dd:ss")

        $connection = Get-NetTCPConnection
        $statuslist = @("Listen","Established","TimeWait","CloseWait","LastAck")
        $status = ($connection | group state -NoElement | where Name -in $statuslist).Name

        foreach ($c in $($connection | group State -NoElement