PowerShellでSyslogを読もう

リアルタイムでSyslog眺めたいときって、ありますよね
それが普段使ってるPowerShellで見れたら素敵ですよね

モジュール書こうか!な!

$Script:ReceivedSyslog = @()

class Syslog
{
    [datetime] $ReceivedTime
    [System.Net.IPAddress] $IPAddress
    [int] $Port
    [string] $Log
}

enum Severity
{
    emerg
    alert
    crit
    err
    warning
    notice
    info
    debug
}

function Receive-Syslog
{
    [CmdletBinding()]
    param
    (
        [Parameter(Mandatory=$false)]
        [ValidateSet('utf-8','shift_jis','euc-jp')]
        [string] $Encoding = 'euc-jp',
        [Parameter(Mandatory=$false)]
        [uint16] $Port = 514,
        [Parameter(Mandatory=$false)]
        [int] $ReceiveSpan = 1000,
        [Parameter(Mandatory=$false)]
        [scriptblock] $Parser
    )
    try
    {
        $Enc = [System.Text.Encoding]::GetEncoding($Encoding)
        $udpClient = New-Object System.Net.Sockets.UdpClient $([int] $Port)
        $RemoteEndpoint = New-Object System.Net.IPEndPoint @([ipaddress]::Any,0)
        $udpClient.Client.ReceiveTimeout = $ReceiveSpan
        do 
        {
            try
            {
                $ReceivedBytes = $udpClient.Receive([ref] $RemoteEndpoint)
                $Syslog = [Syslog] @{
                    ReceivedTime = Get-Date
                    IPAddress    = $RemoteEndpoint.Address
                    Port         = $RemoteEndpoint.Port
                    Log          = $Enc.GetString($ReceivedBytes).Trim()
                }
                $Output = if ($Parser) {
                    &$Parser $Syslog
                } else {
                    $Syslog
                }
                $Script:ReceivedSyslog += $Output
                $Output | Write-Output
            }
            catch
            {
                Write-Verbose 'timed out'
            }

        }
        while ($true)
    }
    finally
    {
        $udpClient.Close()
        Write-Verbose 'closed socket'
    }
}

function Get-SyslogReceived
{
    return $Script:ReceivedSyslog
}

function Clear-SyslogReceived
{
    $Script:ReceivedSyslog = @()
}

function Get-SyslogPriority
{
    param
    (
        [Parameter(Mandatory)]
        [int] $Int
    )
    return [Severity] ($Int % 8)
}

Receive-Syslog 叩けば受信するぞ

SyslogなんてUDPClientで受け取るだけなのでなんてこたーねぇ…
んだけど非同期の壁を乗り越えるのがアレだったので関数を実行するとブロックされます
Ctrl+C で停止させたかったので適度に Receive() をタイムアウトさせてますよ
雑だね!

Ctrl+C したときにソケットを閉じたいんだけどどうしたらいいんだ…
と暫く悩んでたんですが try-finally で良かったんですね
とても楽ちん、ありがとうPowerShell

そのまま実行すると [Syslog] 型にして返します
-Parser[scriptblock] を渡すと出力を好きに変更出来ます
$args[0][Syslog] 型の値が入ってるのでいい感じにしてから返しましょう
とりあえず元の値に NotePropertyAdd-Member する感じにしたら素敵でした

ほかのパラメータは

  • -Encoding
    へいしゃの製品はsyslogににほんごが混ざってる可能性があるのでそれらに対応する為に必要なんだ
    しょうじきやめてほしい
  • -ReceiveSpan
    UDPClientが受信でタイムアウトするまでの時間
    あんまり長くすると Ctrl+C してから止まるまでにイラッとするかもしれない
  • -Port
    待ち受けポートな

な感じです

関数を Ctrl+C で抜けても $Script:ReceivedSyslog 受信したログが全部入ってるので Get-SyslogReceived で後から見返すことも出来るぞ
パーサー書くときこれ使って練習したので実装しといてよかった

あとはなんだ、よく使うパーサーを吐く関数とか書いといたらゴキゲンです
そんじゃこれでsyslog見ながら仕事するぞう

広告

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中