Home > Windows にまつわる e.t.c.

PowerShell で死活監視


コンピューター等のノード死活監視はインフラ管理の基本中の基本です

死活監視をする方法はいろいろありますが、PowerShell だって死活監視が出来るのです

 

死活監視手法

では、死活監視はどの様にするかを整理してみましょう

 

L2 監視

ping を使って対象ノードが生きているか確認する一番基本的な手法です

ノードによっては icmp に反応しない設定になっているので、ping に反応しないノードの死活監視は別の手法を使います

 

L3 監視

TCP ポートが生きているかの監視です

icmp に反応しないようにしていても、サービス提供をしているノードであれば、サービスで使用する TCP ポートは開いているはずなので、ポートが開いているかで死活監視をします

 

L4 監視

ポートが開いていても、サービスが死んでいることもありますので、L4 動作で確認します

昨今は Web サービスが多いので、Web サービスが生きているかで死活監視をします

PowerShell 標準機能で Web サービスが生きているか簡単に確認できます

Web サービス以外の L4 監視は、自分でプロトコルを書く必要があるのでちょいとハードル高いのですが、腕に覚えがあればそんなに難しくないのでチャレンジしてください。

 

死活監視に使う PowerShell コマンドレット

L2/L3 死活監視に使う PowerShell コマンドレットは「Test-NetConnection」と「Test-Connection」の2つです

名前からして、よく似た機能を持ってそうですね

Test-NetConnection は、Windows PowerShell 時代のコマンドレットで、PowerShell Core では互換コマンドレットレットとして存在しているようで、Get-Help の -Online オプションでは使用法が確認できないようになっています

 

それでは、「Test-NetConnection」と「Test-Connection」の違いを見てみましょう

厄介な事に、動作環境によって機能が違うんですよね...

動作環境 コマンドレット ping port IPv4/IPv6 指定
Windows PowerShell 5.1 Test-NetConnection
-Count オプション無し
×
Test-Connection
-Count オプション有り
× ×
PowerShell Core 7.2.1 Test-NetConnection
-Count オプション無し
×
Test-Connection
-Count オプション有り

 

この表を見てもわかるように、Windows PowerShell では「Test-NetConnection」を使わないと L3 死活確認が出来ないですし、PowerShell Core では IPv4/IPv6 の指定が出来る「Test-Connection」を使う事が想定されいる事がわかります

反応速度も「Test-Connection」の方が早いので、どうしても Windows PowerShell で実装しなくちゃならない場合を除いて、PowerShell Core + Test-Connection の組み合わせをお勧めします

 

L2 死活監視の実装

それでは、PowerShell Core と Windows PowerShell 別に、それぞれの死活監視実装を見ていきましょう

L2 死活監視の ping は、ping.exe を叩く必要は無くコマンドレットレットだけで確認が出来ます

 

PowerShell Core

PowerShell Core では「Test-Connection -Ping ターゲットノード」で L2 死活確認が出来ます

 

ping.exe と同様に4回の疎通確認をしていますね

IPv4/IPv6 を明示的に指定する場合は、-IPv4 -IPv6 オプションを指定します

 

L2 死活確認は「Status」属性を見れば良さそうですが、default では4回確認をし、4つのオブジェクト配列して結果が返ってきます

4回待つのも面倒なので、1回の確認だけにするには、-Count オプションで 1 を指定します

 

戻り値の Status のタイプを確認すると、IPStatus なので、"[IPStatus" と入力して TAB 補完すると "[System.Net.NetworkInformation.IPStatus]" である事がわかります

つまり、Status が "[System.Net.NetworkInformation.IPStatus]::Success" であるかを確認すれば L2 死活確認が出来ます

 

関数にするとこんな感じです

#######################################################################
# ping(PowerShell Core)
#######################################################################
function TestPingPSC( $TergetNode ){
    if( (Test-Connection -Ping $TergetNode -Count 1 -ErrorAction SilentlyContinue).Status -ne [System.Net.NetworkInformation.IPStatus]::Success){
        return $false
    }
    return $true
}

 

Windows PowerShell

Windows PowerShell では「Test-Connection -ComputerName ターゲットノード」で L2 死活確認が出来ます

 

Test-Connection は -Count もなく、そのままオブジェクトが返ってくるで PingSucceeded の True / False を確認します

 

関数にするとこんな感じです

#######################################################################
# ping(Windows PowerShell)
#######################################################################
function TestPingWPS( $TergetNode ){
    if( (Test-NetConnection -ComputerName $TergetNode -WarningAction SilentlyContinue ).PingSucceeded ){
        return $true
    }
    return $false
}

 

L3 監視

L3 死活確認のノードのポート状態もコマンドレットレットで確認出来ます

 

PowerShell Core

PowerShell Core では「Test-Connection -ComputerName ターゲットノード -TcpPort ポート番号」で L3 死活確認が出来ます

 

戻り値はシンプルに True / False が返ってきますが、ポートが開いていない場合は少々待たされます

コマンドレットが戻ってくるまで待っても良いのですが、確認対象が多い場合は悠長に待っていられないので、Start-Job でジョブとして非同期に処理をさせます

 

Start-Job -ScriptBlock {投入スクリプトブロック} -ArgumentList 引数リスト

 

$JobStatus = Start-Job -ScriptBlock {Test-Connection $args[0] -TcpPort $args[1] } -ArgumentList "www.vwnet.jp", 80

 

ジョブの状態は Get-Job で確認出来るのですが、今回は 1 秒待ったら状態を確認して、処理完了していなかったらポートが開いていないことにして次の確認に移りましょう

1秒のタイムアウトを仕掛けるには、Wait-Job -Timeout を使います

 

Wait-Job $JobStatus -Timeout 1

 

タイムアウトした時は、処理途中なので State が Completed 以外になっています

ジョブの結果を受け取るには、 Receive-Job を使います

Receive-Job $JobStatus

 

関数にするとこんな感じです

#######################################################################
# port(PowerShell Core)
#######################################################################
function TestPortPSC( [string]$TergetNode, [int]$TertgetPort ){
    # 1 秒待つ
    $TimeOut = 1

    $JobStatus = Start-Job -ScriptBlock {Test-Connection -ComputerName $args[0] -TcpPort $args[1] } -ArgumentList $TergetNode, $TertgetPort

    $Dummy = Wait-Job $JobStatus -Timeout $TimeOut
    # 処理完了
    if( $JobStatus.State -eq "Completed"){
        # Job 実行結果受け取り
        $JobReturn = Receive-Job $JobStatus
        if( $JobReturn ){
            return $true
        }
        else{
            return $false
        }
    }
    # タイムアウト
    return $false
}

 

Windows PowerShell

Windows PowerShell では「Test-NetConnection -ComputerName ターゲットノード -Port ポート番号」で L3 死活確認が出来ます

ポート状態は TcpTestSucceeded に True / False がセットされます

 

Test-NetConnection もポートが開いていない場合は少々待たされます

 

関数にするとこんな感じですが、処理自体も Test-Connection より時間かかるので、5秒待つようにします

#######################################################################
# port(Windows PowerShell)
#######################################################################
function TestPortWPS( [string]$TergetNode, [int]$TertgetPort ){
    # 5 秒待つ
    $TimeOut = 5

    $JobStatus = Start-Job -ScriptBlock {(Test-NetConnection -ComputerName $args[0] -Port $args[1]).TcpTestSucceeded} -ArgumentList $TergetNode, $TertgetPort

    $Dummy = Wait-Job $JobStatus -Timeout $TimeOut
    # 処理完了
    if( $JobStatus.State -eq "Completed"){
        # Job 実行結果受け取り
        $JobReturn = Receive-Job $JobStatus
        if( $JobReturn ){
            return $true
        }
        else{
            return $false
        }
    }
    # タイムアウト
    return $false
}

 

Windows PowerShell、PowerShell Core とも、Remove-Job していないジョブはそのまま残骸が残るので、最後にまとめて後始末しておきます

Get-Job | % { Remove-Job -Id $_.Id }

 

L4 監視

Web サービスの L4 死活監視は、URI を開いてステータスに 200 が返ってくるかを確認します

Web ページのステータスを確認するには Invoke-WebRequest -Uri を使います

 

StatusCode に 200 が返ってくれば Web サービスは正常です

幸い、Invoke-WebRequest は互換性があるので機能差を気にしなくて大丈夫です

コードにするとこんな感じです

#######################################################################
# Web
#######################################################################
function TestWeb( $TergetURI ){

    try{
        $WebStatus = Invoke-WebRequest -Uri $TergetURI
    }
    catch{
        return $false
    }
    if( $WebStatus.StatusCode -ne 200 ){
        return $false
    }

    return $true
}

 

 

Hyper-V ホストであれば、VM の死活確認も同様に書くことが出来ますので、必要に応じて実装してみてください

 

参考情報

Test-NetConnection (NetTCPIP) | Microsoft Docs
https://docs.microsoft.com/en-us/powershell/module/nettcpip/test-netconnection?WT.mc_id=WD-MVP-36880&view=windowsserver2022-ps

Test-Connection (Microsoft.PowerShell.Management) - PowerShell | Microsoft Docs
https://docs.microsoft.com/ja-jp/powershell/module/Microsoft.PowerShell.Management/Test-Connection?WT.mc_id=WD-MVP-36880

 

back.gif (1980 バイト)

home.gif (1907 バイト)

Copyright © MURA All rights reserved.