こんにちは!
技術は実際に触って学ぶタイプです。零壱(ゼロイチ)テクトです。

先日、OpenWrtでSyslogサーバを立てたのですが
僕が使うWindowsではLinuxのようなLoggerコマンドがなく
スクリプトで好きな種類のSyslogを送信できないかと思った所
PowerShellで良さげなのが無かったので作成してみました。
尚、逆にSyslogの受信も考えたんですが、以下 ebi216様が
実用的なコードを書いてくださっていたので、送信だけのコードを作成しました。
@ebi216様 / PowershellでSyslogサーバを書く
https://qiita.com/ebi216/items/3e5d18bd33c5e47ae3b5
1.概要/仕様
・PowerShellのみでSyslogを送信
・Syslogで一般的な仕様 RFC 3164 形式準拠(仕事でも使いたいので
・Facility/Severityを選べるように
・後に弄れるように生成メッセージも部品化
2.コード
# 送信先SyslogサーバーのIPアドレス/ポート番号
$syslogServer = "192.168.100.1" # SyslogサーバーのIPアドレス
$syslogPort = 514 # Syslogのデフォルトポート (UDP)
# ===== Syslogメッセージの詳細設定 =====
# RFC 3164 形式に準拠
# PRI = (Facility * 8) + Severity
$facility = 1
# Facility (機能) コード: メッセージを生成したプログラムの種類
# 0: kernel messages (カーネルメッセージ)
# 1: user-level messages (ユーザーレベルメッセージ)
# 2: mail system (メールシステム)
# 3: system daemons (システムデーモン)
# 4: security/authorization messages (セキュリティ/認証メッセージ)
# 5: syslogd internal messages (syslogd内部メッセージ)
# 6: line printer subsystem (ラインプリンターサブシステム)
# 7: network news subsystem (ネットワークニュースサブシステム)
# 8: UUCP subsystem (UUCPサブシステム)
# 9: clock daemon (クロックデーモン)
# 10: security/authorization messages (認証/セキュリティメッセージ)
# 11: FTP daemon (FTPデーモン)
# 12: NTP subsystem (NTPサブシステム)
# 13: log audit (ログ監査)
# 14: log alert (ログアラート)
# 15: clock daemon (クロックデーモン)
# 16-23: local use (ローカル利用)
$severity = 1
# Severity (重要度) コード: メッセージの重要度
# 0: Emergency (緊急) - システムが使用不能
# 1: Alert (警告) - 直ちに行動が必要
# 2: Critical (致命的) - クリティカルな状態
# 3: Error (エラー) - エラー状態
# 4: Warning (注意) - 警告状態
# 5: Notice (通知) - 正常だが注目すべき状態
# 6: Informational (情報) - 情報メッセージ
# 7: Debug (デバッグ) - デバッグレベルメッセージ
# 現在時刻の取得(UTC) / RFC 3164形式のタイムスタンプを作成: "Jan 23 12:34:56"
$now = [DateTime]::UtcNow
$month = $now.ToString("MMM", [System.Globalization.CultureInfo]::InvariantCulture) # 月の略称
$day = $now.Day
$dayString = " $day" # 日付生成/RFC3164準拠(3桁)/日付1桁の場合はスペースで桁調整
$dayString = $dayString.Substring($dayString.Length - 2, 2)
$time = $now.ToString("HH:mm:ss") # 時刻 (HH:mm:ss)
$timestamp = "$month $dayString $time"
# ホスト名: メッセージを送信しているホストのコンピュータ名
$hostname = $env:COMPUTERNAME
# アプリケーション名 (Tag): メッセージを生成したアプリケーションの名前
$appName = "PowerShell"
# プロセスID (PID): メッセージを生成したプロセスのID
$processId = $PID
# 実際のメッセージ内容
$message = "Test Syslog Message from PowerShell(RFC 3164 FORMAT)"
# ===== Syslogメッセージ作成 =====
# PRIORITY (PRI) 値の計算
# PRI = (Facility * 8) + Severity
$priority = ($facility * 8) + $severity
$pri = "<$priority>"
# RFC3164 形式/Syslogメッセージ生成
# フォーマット: <PRI>TIMESTAMP HOSTNAME APP-NAME[PROCID]: MESSAGE
$syslogMessage = "$pri$timestamp $hostname $appName[$processId]: $message"
# ===== Syslogメッセージの送信 =====
# UDPクライアント定義
$udpClient = New-Object System.Net.Sockets.UdpClient
try {
# Syslogサーバー接続 (UDPはコネクションレスだが、Connectでデフォルトのリモートエンドポイントを設定)
$udpClient.Connect($syslogServer, $syslogPort)
# Syslogメッセージ/バイト配列に変換
# RFC3164 は ASCII が一般的/日本語不可
$bytes = [System.Text.Encoding]::ASCII.GetBytes($syslogMessage)
# メッセージ送信
$udpClient.Send($bytes, $bytes.Length)
# コンソールに送信完了メッセージ表示
Write-Host "[送信先] $($syslogServer):$($syslogPort) 宛にSyslogメッセージを送信しました。"
Write-Host "[メッセージ] $($syslogMessage)"
}
catch {
# エラー発生時処理
Write-Error "Syslogメッセージ送信中エラー: $($_.Exception.Message)"
Write-Host "エラーの種類: $($_.Exception.GetType().FullName)"
}
finally {
# UDPクライアントを必ずクローズ/リソース解放
if ($udpClient -ne $null) {
$udpClient.Close()
Write-Host "---> UDPクライアントをクローズ"
}
}
3.結果
⬇️PowerShell ISE側の送信結果です。これを3回送りました。
PS C:\Powershell\SyslogTestSned.ps1
99
[送信先] 192.168.100.1:514 宛にSyslogメッセージを送信しました。
[メッセージ] <9>May 24 14:33:49 01tecto PowerShell[20200]: Test Syslog Message from PowerShell(RFC 3164 FORMAT)
---> UDPクライアントをクローズ
⬇️OpenWrtのSyslogサーバ側のログです。
実際にSyslogサーバで受信を確認できました。
(見やすさや情報隠しにログの一部を若干弄ってます)
BusyBox v1.36.1 (2024-09-23 12:34:46 UTC) built-in shell (ash)
_______ ________ __
| |.-----.-----.-----.| | | |.----.| |_
| - || _ | -__| || | | || _|| _|
|_______|| __|_____|__|__||________||__| |____|
|__| W I R E L E S S F R E E D O M
-----------------------------------------------------
OpenWrt 23.05.5, r24106-10cc5fcd00
-----------------------------------------------------
root@OpenWrt_FG52E:~#
root@OpenWrt_FG52E:~#
root@OpenWrt_FG52E:~# cat /var/log/syslog.log
May 24 14:33:21 OpenWrt_FG52E dnsmasq-dhcp[1]: DHCPDISCOVER(br-lan) xx:xx:xx:xx:xx:xx:xx
May 24 14:33:21 OpenWrt_FG52E dnsmasq-dhcp[1]: DHCPOFFER(br-lan) 192.168.xx.xx xx:xx:xx:xx:xx:xx
May 24 14:33:41 01Tecto PowerShell[20200]: Test Syslog Message from PowerShell(RFC 3164 FORMAT)
May 24 14:33:46 01Tecto PowerShell[20200]: Test Syslog Message from PowerShell(RFC 3164 FORMAT)
May 24 14:33:50 01Tecto PowerShell[20200]: Test Syslog Message from PowerShell(RFC 3164 FORMAT)
May 24 14:33:58 OpenWrt_FG52E odhcpd[1894]: A default route is present -略- don't announce a default route by overriding ra_lifetime!
4.備考
・✅ 改良案1:1実行1送信なので、連発したい場合は回数指定してループさせる必要あり
・✅ 改良案2:同じメッセージ連発はイマイチなので
ランダムでFacility/Severityを変えた方がよさげ
・「Syslog Generator for Windows」や
「Kiwi SyslogGen」なるフリーのSyslog送信ツールを見つけたので
ちゃんとした業務で検証に使用するなら、そっちのツールの方が良いカーモ。
・そもそもLinuxのLoggerコマンドやその手のツールを使え、
と思ったが方いれば仰る通りです。
・最初はもっとシンプルでとりあえず送信できるコードを書いたんですが
せっかく投稿するなら「RFC3164
」に準拠しようと盛ったら
仕様の確認と理解の方にめっちゃ時間かかりました……。
それでは
どこかの誰かの何かの足しになれば幸いです。
01000010 01011001 01000101