Windows Server 2019 に OpenSSH サーバーを導入すると、sshd の接続ログはイベント ビューアーの「OpenSSH/Operational」に記録されます。ただし、このログは従来の System / Application ログとは形式が異なるため、Get-EventLog では取得できません。この記事では、PowerShell で OpenSSH/Operational ログを正しく扱い、過去 24 時間分だけをレポートとして自動生成する具体的な手順とスクリプト例を詳しく解説します。
OpenSSH ログが Get-EventLog で取得できない理由
まず、よくあるつまずきポイントとして「Get-EventLog -List に OpenSSH/Operational が表示されない」「Get-EventLog -LogName OpenSSH/Operational でエラーになる」という現象があります。これは環境の問題ではなく、コマンド側の仕様によるものです。
Windows のイベント ログには、大まかに次の 2 種類があります。
- 従来型イベント ログ(System / Application / Security など)
- アプリケーションとサービス ログ(ETW チャネル含む)
OpenSSH のログ「OpenSSH/Operational」は後者に属しており、旧式の Get-EventLog コマンドレットでは扱えません。代わりに、より新しい Get-WinEvent を利用する必要があります。
| コマンドレット | 対応しているログ | OpenSSH/Operational | 備考 |
|---|---|---|---|
Get-EventLog | System / Application など従来型ログのみ | 非対応 | レガシー互換用。新規スクリプトでは非推奨。 |
Get-WinEvent | 従来型ログ + アプリケーションとサービス ログ + ETW | 対応 | OpenSSH/Operational を含む最新ログの取得に使用 |
そのため、OpenSSH のログを PowerShell で扱う際は「まず Get-EventLog という選択肢を捨てる」ことが重要な第一歩になります。
OpenSSH/Operational ログが存在するか確認する
次に、本当に OpenSSH/Operational ログが作成されているかを確認します。OpenSSH サーバーの機能を追加しただけでは、まだログ チャネルが有効になっていないケースもあるため、接続動作(SSH ログイン)を一度発生させてから確認するのがおすすめです。
# OpenSSH 関連のログ チャネルを一覧表示
Get-WinEvent -ListLog *OpenSSH* |
Select-Object LogName, LogType, IsEnabled, MaximumSizeInBytes
ここで LogName に OpenSSH/Operational が表示され、IsEnabled が True になっていれば準備完了です。表示されない場合は、OpenSSH サーバーが正しくインストールされているか、サービス sshd が起動しているかを先に確認します。
# OpenSSH サービスの状態確認
Get-Service sshd,ssh-agent
少なくとも sshd が Running であることが望ましい状態です。
基本の取得コマンド:Get-WinEvent で直近のログを確認する
OpenSSH/Operational ログにアクセスできることが確認できたら、まずは直近の数件だけを取得して、どのようなログが出力されているのかを目視で確認しておきます。
# OpenSSH/Operational の直近 5 件を表示
Get-WinEvent -LogName "OpenSSH/Operational" -MaxEvents 5
この時点で、以下のような項目が表示されます。
- TimeCreated(発生日時)
- Id(イベント ID)
- LevelDisplayName(情報 / 警告 / エラーなど)
- Message(接続元 IP やユーザー名などの詳細メッセージ)
この情報をもとにレポートを作成していくので、「どの項目を CSV レポートに含めるか」をここでイメージしておくと、後の設計がスムーズになります。
過去 24 時間分だけの OpenSSH ログを抽出する
本題の「過去 24 時間分のログだけを抽出する」方法を解説します。ポイントは次の 2 つです。
- 基準時刻(24 時間前)を変数に保持する
- できるだけ早い段階でフィルターする(パフォーマンスのため)
まず、基準となる開始時刻を変数に入れます。
$start = (Get-Date).AddHours(-24)
Where-Object で後からフィルターする方法
一番分かりやすい形は、いったんログを取得してから Where-Object で絞り込む方法です。
$start = (Get-Date).AddHours(-24)
Get-WinEvent -LogName "OpenSSH/Operational" |
Where-Object { $_.TimeCreated -ge $start } |
Select-Object TimeCreated, Id, LevelDisplayName, Message
動きとしてはシンプルで、PowerShell 初心者にも読みやすい書き方です。ただし、大量のログがあるサーバーでは「まず全部取得してから捨てる」動作になるため、時間がかかる場合があります。
FilterHashtable を使って取得前に絞り込む方法(推奨)
実運用では、パフォーマンス面を考えて -FilterHashtable パラメーターを使用する方法がおすすめです。これは「イベント ログ側で 絞り込みを行ってから結果を返す」ため、高速に動作します。
$start = (Get-Date).AddHours(-24)
Get-WinEvent -FilterHashtable @{
LogName = 'OpenSSH/Operational'
StartTime = $start
} |
Select-Object TimeCreated, Id, LevelDisplayName, Message
| 方式 | 特徴 | メリット | デメリット |
|---|---|---|---|
| Where-Object で後フィルター | PowerShell 側で絞り込み | 読みやすく、直感的 | 大量ログで遅くなりやすい |
| FilterHashtable で前フィルター | イベント ログ側で絞り込み | 高速・省メモリで実運用向き | Hashtable 記法に慣れが必要 |
24 時間レポートのように毎日自動で回す処理では、基本的に FilterHashtable 方式を選ぶのが定石です。
24 時間分の OpenSSH ログを CSV レポートに保存する
抽出したログを CSV に書き出すことで、Excel での分析や、別システムへの取り込みが容易になります。以下は、過去 24 時間分の OpenSSH ログを CSV ファイルとして保存するサンプルです。
$start = (Get-Date).AddHours(-24)
Get-WinEvent -FilterHashtable @{
LogName = 'OpenSSH/Operational'
StartTime = $start
} |
Select-Object TimeCreated, Id, LevelDisplayName, Message |
Export-Csv -Path "C:\Report\OpenSSH_24h.csv" -NoTypeInformation -Encoding UTF8
上記のスクリプトのポイントを整理します。
| 処理ステップ | 内容 | 補足 |
|---|---|---|
$start の設定 | 現在時刻から 24 時間前を算出 | 必要に応じて -48 などに変更すれば 2 日分も簡単に取得可能 |
-FilterHashtable | ログ名と開始時刻でサーバー側フィルタリング | 大量ログでも高速に処理できる |
Select-Object | 必要な項目だけに絞り込む | 列数を絞ることで CSV の可読性が向上 |
Export-Csv | UTF-8 の CSV ファイルとして出力 | 日本語環境でも文字化けしにくい |
出力先フォルダー C:\Report が存在しない場合は、事前に作成しておくか、スクリプト内で自動作成するようにしておくと運用が楽になります。
$reportDir = "C:\Report"
if (-not (Test-Path $reportDir)) {
New-Item -Path $reportDir -ItemType Directory -Force | Out-Null
}
日付付きファイル名でレポートを蓄積する
運用現場では、「毎日上書きする」よりも「日付ごとにファイルを残す」方がトラブル調査に役立つことが多くあります。日付時刻をファイル名に含めることで、過去のレポートを簡単に遡れるようにします。
$hours = 24
$start = (Get-Date).AddHours(-$hours)
$reportDir = "C:\Report"
if (-not (Test-Path $reportDir)) {
New-Item -Path $reportDir -ItemType Directory -Force | Out-Null
}
$stamp = Get-Date -Format "yyyyMMdd_HHmmss"
$file = "OpenSSH_{0}h_{1}.csv" -f $hours, $stamp
$path = Join-Path $reportDir $file
Get-WinEvent -FilterHashtable @{
LogName = 'OpenSSH/Operational'
StartTime = $start
} |
Select-Object TimeCreated, Id, LevelDisplayName, Message |
Export-Csv -Path $path -NoTypeInformation -Encoding UTF8
このようにしておけば、C:\Report 配下に以下のようなファイルが蓄積されていきます。
- OpenSSH_24h_20250101_010000.csv
- OpenSSH_24h_20250102_010000.csv
- OpenSSH_24h_20250103_010000.csv
障害発生日時が分かっている場合、その日付周辺の CSV だけを開けばよいため、調査効率が大きく向上します。
レポート項目をカスタマイズして見やすくする
そのまま Message を CSV に出すと、1 行に複数行分のメッセージが入ってしまい、Excel 上で読みづらくなることがあります。用途に合わせて、必要な項目だけに絞り込むとレポートの使い勝手が向上します。
例えば、シンプルに「いつ」「何が起きたか」だけを見たい場合は次のようにします。
Get-WinEvent -FilterHashtable @{
LogName = 'OpenSSH/Operational'
StartTime = (Get-Date).AddHours(-24)
} |
Select-Object @{
Name = '日時'
Expression = { $_.TimeCreated }
}, @{
Name = 'イベントID'
Expression = { $_.Id }
}, @{
Name = 'レベル'
Expression = { $_.LevelDisplayName }
}, @{
Name = '概要'
Expression = { $_.Message.Split("`n")[0] } # 1 行目だけ抽出
} |
Export-Csv -Path "C:\Report\OpenSSH_24h_simple.csv" -NoTypeInformation -Encoding UTF8
Message.Split("`n")[0] のように 1 行目だけを抜き出すことで、「ログイン成功」「ログイン失敗」といった概要を一覧しやすくなります。より細かく IP アドレスやユーザー名を切り出したい場合は、正規表現を使って Message の文字列を解析することも可能です。
HTML レポートやメール通知への応用
CSV だけでなく、HTML 形式のレポートを共有フォルダーに置いたり、メール本文に貼り付けたりしたい場面もあります。PowerShell では ConvertTo-Html を使うことで、簡単に HTML テーブル形式のレポートを作成できます。
$start = (Get-Date).AddHours(-24)
$reportDir = "C:\Report"
$stamp = Get-Date -Format "yyyyMMdd_HHmmss"
$htmlPath = Join-Path $reportDir "OpenSSH_24h_$stamp.html"
if (-not (Test-Path $reportDir)) {
New-Item -Path $reportDir -ItemType Directory -Force | Out-Null
}
$events = Get-WinEvent -FilterHashtable @{
LogName = 'OpenSSH/Operational'
StartTime = $start
} |
Select-Object TimeCreated, Id, LevelDisplayName, Message
$events |
ConvertTo-Html -Title "OpenSSH 24時間レポート" -PreContent "<h1>OpenSSH 24時間レポート</h1>" |
Out-File -FilePath $htmlPath -Encoding UTF8
この HTML ファイルをブラウザーで開けば、そのままテーブル形式のレポートとして閲覧できます。必要に応じて、社内ポータルや SharePoint に配置して共有することもできます。
タスク スケジューラで 24 時間レポートを自動化する
ここまでのスクリプトを毎朝手動で実行するのも良いですが、運用を楽にするにはタスク スケジューラでの自動実行が必須です。基本的な流れは次の通りです。
- スクリプトを
C:\Scripts\OpenSSH_24h_Report.ps1として保存する - タスク スケジューラで新しいタスクを作成する
- トリガーを「毎日 ○:○○」に設定する
- 操作で PowerShell を指定し、引数でスクリプトを実行する
タスクの「操作」に指定するコマンド例は次の通りです。
| 項目 | 設定例 |
|---|---|
| プログラム/スクリプト | powershell.exe |
| 引数の追加 | -NoProfile -ExecutionPolicy Bypass -File "C:\Scripts\OpenSSH_24h_Report.ps1" |
| 開始 (“開始 (オプション)”) | C:\Scripts |
レポート出力先を NAS や共有フォルダーにしておけば、運用チーム全体でいつでも確認できる環境が整います。
OpenSSH/Operational ログ運用のベストプラクティス
長期運用を見据えた場合、単にログを出すだけでなく「ログ サイズ」「権限」「保管期間」なども合わせて検討しておくと安心です。代表的なポイントを表にまとめます。
| 項目 | 推奨設定・考慮点 |
|---|---|
| ログサイズ管理 | wevtutil sl "OpenSSH/Operational" /ms:104857600 などで上限サイズ(ここでは 100 MB)を設定し、ディスク圧迫を防ぐ |
| 権限 | 原則として管理者権限の PowerShell セッションで取得。閲覧権限を持たないアカウントではアクセスできない場合がある |
| パフォーマンス | 大量ログ環境では必ず -FilterHashtable や -MaxEvents を併用し、むやみに全件読み込まない |
| 自動化 | タスク スケジューラで 1 日 1 回実行し、NAS や SharePoint に自動保管すると日々の運用コストを大幅に削減できる |
| 保管期間 | セキュリティポリシーに合わせて「何日分の CSV を残すか」を決め、古いファイルを自動削除するバッチを用意するとなお良い |
ログ サイズ上限の変更は、次のようなコマンドで行います。
# OpenSSH/Operational の最大サイズを 100 MB に変更する例(管理者権限で実行)
wevtutil sl "OpenSSH/Operational" /ms:104857600
変更後はサーバー再起動の必要はありませんが、設定値が反映されているか Get-WinEvent -ListLog "OpenSSH/Operational" で確認しておくと安心です。
よくあるトラブルとチェックポイント
実際に運用していると、以下のようなトラブルや疑問がよく発生します。それぞれ簡単な確認ポイントをまとめます。
OpenSSH/Operational が見つからない
- OpenSSH サーバー機能がインストールされているか
Get-Service sshdでサービスが存在し、起動しているか- 少なくとも一度は SSH 接続を行ってログが出力されているか
特に、新規構築直後などで一度も接続していない場合、イベントが 1 件も出ておらず、チャンネルが有効化されていないケースがあります。その場合は、クライアントから一度ログインを試し、その後に Get-WinEvent -ListLog *OpenSSH* を実行してみてください。
権限エラーでログが取得できない
標準ユーザーで PowerShell を起動していると、セキュリティの制約によりイベント ログにアクセスできない場合があります。その際は、次のいずれかを試します。
- 「管理者として実行」で PowerShell を起動しなおす
- タスク スケジューラの実行アカウントをローカル管理者(あるいはそれに準ずる権限)に設定する
特に自動化タスクとして運用する場合は、実行アカウントの権限とパスワード更新ポリシー(定期変更の有無)も含めて設計しておくことが重要です。
時刻のズレで 24 時間の範囲が合わない
サーバーのタイムゾーンや時刻同期(NTP)がずれていると、「24 時間前」と言いつつ実際には異なる時間帯のログが取得されることがあります。特に以下の点に注意します。
- サーバーのタイムゾーン設定が正しいか
- ドメイン環境の場合はドメイン コントローラーと時刻同期されているか
- レポートを閲覧する側(クライアント PC)のタイムゾーンとの違いを考慮しているか
必要に応じて、レポートに「レポート生成日時」「対象期間(○○〜○○)」を明記する列を追加しておくと、後から確認しやすくなります。
24 時間 OpenSSH レポートの完成版スクリプト
最後に、ここまでの内容を踏まえた「24 時間 OpenSSH ログ レポート生成スクリプト」の一例を掲載します。時間数や出力フォルダをパラメーターで指定できるようにしておくと、再利用性が高まります。
param(
[int]$Hours = 24,
[string]$OutputDir = "C:\Report"
)
# 開始時刻(指定時間前)
$start = (Get-Date).AddHours(-$Hours)
# 出力フォルダーを確認・作成
if (-not (Test-Path $OutputDir)) {
New-Item -Path $OutputDir -ItemType Directory -Force | Out-Null
}
# ファイル名に時間数とタイムスタンプを付与
$stamp = Get-Date -Format "yyyyMMdd_HHmmss"
$file = "OpenSSH_{0}h_{1}.csv" -f $Hours, $stamp
$csvPath = Join-Path $OutputDir $file
# イベントを取得して CSV に出力
Get-WinEvent -FilterHashtable @{
LogName = 'OpenSSH/Operational'
StartTime = $start
} |
Select-Object TimeCreated, Id, LevelDisplayName, Message |
Export-Csv -Path $csvPath -NoTypeInformation -Encoding UTF8
Write-Host "レポートを出力しました: $csvPath"
このスクリプトを C:\Scripts\OpenSSH_24h_Report.ps1 などのファイル名で保存しておき、タスク スケジューラから次のように呼び出すと、汎用的な 24 時間レポート基盤として利用できます。
powershell.exe -NoProfile -ExecutionPolicy Bypass `
-File "C:\Scripts\OpenSSH_24h_Report.ps1" `
-Hours 24 `
-OutputDir "C:\Report\OpenSSH"
パラメーターを変えることで、「直近 1 時間のログだけを監視用に出力する」「直近 72 時間分をまとめて調査用に出力する」といった応用も容易です。
まとめ
Windows Server 2019 上の OpenSSH ログ「OpenSSH/Operational」は、従来型のイベント ログとは形式が異なるため、Get-EventLog ではなく Get-WinEvent で取得する必要があります。特に、-FilterHashtable と StartTime を組み合わせることで、過去 24 時間分だけを効率よく抽出できる点が重要です。
抽出したログは CSV・HTML などに変換して保存し、タスク スケジューラで定期実行することで、毎日自動で「OpenSSH 24 時間レポート」を生成できます。ログ サイズや権限、保管期間といった運用面のポイントもあわせて押さえることで、GUI に頼らず PowerShell だけで安定した SSH ログ監査の仕組みを構築できます。
これらを実装すれば、障害解析やセキュリティ インシデント対応の際に「いつ」「誰が」「どこから」「どのような結果で」接続してきたのかを、素早く把握できるようになります。日常の定常運用から、いざというときのトラブルシュートまで、OpenSSH ログを最大限に活用する基盤としてぜひ役立ててください。

コメント