ブログの記事から検索

2019年3月9日土曜日

Windows 10 の Powershell で Syslog 受信するスクリプト

ネットワーク機器の吐き出すSyslogをファイルに保存したくは無いけど、リアルタイムに流れてくるものを拾って眺めておきたい。というシチュエーションが私にはあるので、適当なプログラムが無いかと探していたら、Powershell で実現する方法が載っていたので紹介します。

<この記事は、旧ブログからの移転記事です。スクリプトも若干変更>

見つけたのはこちらのWebページです。こちらに掲載されているスクリプトをベースにアレンジしました。

WindowsでPowershellだけでSyslogを受信してみる。 | 技術的な何か。

また、Syslog のセレクターの計算処理についてはこちらが詳しい。


実行してSyslogを受信するとこのように表示されます。




以下、スクリプト

SyslogMon.ps1

$Udp = New-Object System.Net.Sockets.UdpClient(514)
$Sender = $null

Add-Type -TypeDefinition @"
       public enum Syslog_Facility
       {
               kern,
               user,
               mail,
               system,
               security,
               syslog,
               lpr,
               news,
               uucp,
               clock,
               authpriv,
               ftp,
               ntp,
               logaudit,
               logalert,
               cron,
               local0,
               local1,
               local2,
               local3,
               local4,
               local5,
               local6,
               local7,
       }
"@

Add-Type -TypeDefinition @"
       public enum Syslog_Severity
       {
               Emergency,
               Alert,
               Critical,
               Error,
               Warning,
               Notice,
               Info,
               Debug
       }
"@

Write-Host "Starting Syslog Monitor"

while($true) `
{
  if($Udp.Available) `
  {
    $Buffer = $Udp.Receive([ref]$Sender)
    $RemoteHostIpAddress = $Sender.Address.ToString()
    $MessageString = [Text.Encoding]::UTF8.GetString($Buffer)

## Syslog セレクター情報の抽出
    $Priority = [Int]($MessageString -Replace "<|>.*") 
    [int]$FacilityInt = [Math]::truncate([decimal]($Priority / 8))
    $Facility = [Enum]::ToObject([Syslog_Facility], $FacilityInt)
    [int]$SeverityInt = $Priority - ($FacilityInt * 8 )
    $Severity = [Enum]::ToObject([Syslog_Severity], $SeverityInt)

## Syslog セレクターを除去
    $MessageString = $MessageString -Replace "^<[0-9]+>",""

## Syslog の DateTime と 内容を分割
    $MessageStringArray = $MessageString -Split " "
    $MessageStringDate = $MessageStringArray[0] + " " + $MessageStringArray[1] + " " + $MessageStringArray[2]
    $MessageStringBody = $MessageString -Replace $MessageStringDate,""

## 出力フォーマット
#    $MessageOut = "$MessageStringDate $RemoteHostIpAddress <$Facility.$Severity> $MessageStringBody"
    $MessageOut = "$RemoteHostIpAddress <$Facility.$Severity> $MessageString"

## ディスプレイに表示させるだけにするか、ファイルに保存するか。両方でも良い。
    Write-Host $MessageOut
    $MessageOut >> %USERPROFILE%\Documents\syslog\syslog.log
  }
  [Threading.Thread]::Sleep(500)

1 件のコメント:

  1. ChatGPTに書かせるとこうなるらしい

    # UDPListenerモジュールをインポート
    Import-Module UDPListener

    # サーバーポート番号を定義
    $port = 514

    # Syslogサーバを作成
    $listener = New-UDPServer -Port $port

    # メッセージを受信し、facilityとseverityをデコードして記録する
    while ($true) {
    $message = $listener.ReceiveString()

    # facilityとseverityを取得
    $facility = [int]($message -replace '^\<(\d+)\>\d+', '$1') / 8
    $severity = [int]($message -replace '^\<\d+\>(\d+)', '$1')

    # facilityとseverityをデコード
    $facility_names = @('kernel messages', 'user-level messages', 'mail system', 'system daemons', 'security/authorization messages', 'messages generated internally by syslogd', 'line printer subsystem', 'network news subsystem', 'UUCP subsystem', 'clock daemon', 'security/authorization messages (private)', 'FTP daemon', 'NTP subsystem', 'log audit', 'log alert')
    $severity_names = @('Emergency', 'Alert', 'Critical', 'Error', 'Warning', 'Notice', 'Informational', 'Debug')

    $facility_name = $facility_names[$facility]
    $severity_name = $severity_names[$severity]

    # デコードしたfacilityとseverityを記録
    $log_message = "$facility_name, $severity_name: $message"
    Write-Host $log_message

    # ここにログを保存するコードを追加することができます
    }

    返信削除