Web アプリの動作確認中、エビデンスとしてログファイルを残さなければならない場面とそこそこ出くわすかと思います。Windows でも ssh コマンドを使えるようになったので、それで Linux サーバーに接続しファイルに残すのはいいですが、一緒に画面にも流したいですよね。Linux の tee コマンドにあたる Tee-Object
というコマンドがあるのでそれを使用します。
そのまま ssh コマンドをログに出すと日本語が化けるので、前処理として PowerShell のコードページを切り替えます。Windows PowerShell でも PowerShell (Core 版。新しい方) でも、日本語版 Windows で使っている場合はデフォルトの文字コードが Shift-JIS になっているようなので、 UTF-8 に変更します。
スクリプト本体と読み込み方
上記を考慮したコードは次のようになります。
function Start-FollowRemoteLog {
Param (
[Parameter(Mandatory=$true)][string]$HostName,
[Parameter(Mandatory=$true)][string]$RemotePath,
[string]$LocalPath = "default.log"
)
$command = "tail -n 0 -f ${RemotePath}"
# root 権限がいる場合
# $command = "sudo tail -n 0 -f ${RemotePath}"
# 作業ディレクトリ指定したい場合
# $command = "cd /var/log/ && tail -n 0 -f ${RemotePath}"
# 日本語が文字化けするので、 UTF-8 に設定
$defaultOutputEncoding = $OutputEncoding;
$defaultConsoleInputEncoding = [Console]::InputEncoding;
$defaultConsoleOutputEncoding = [Console]::OutputEncoding;
$OutputEncoding = [Console]::InputEncoding = [Console]::OutputEncoding = New-Object System.Text.UTF8Encoding
try {
ssh $HostName $command | Tee-Object -FilePath $LocalPath
} finally {
# 後片付け。元の文字コードに戻す
$OutputEncoding = $defaultOutputEncoding;
[Console]::InputEncoding = $defaultConsoleInputEncoding;
[Console]::OutputEncoding = $defaultConsoleOutputEncoding;
}
}
このコードを log.ps1
など名前を付けて保存し、使用する場合は以下のように ps1 ファイルを PowerShell 上で指定します。ファイル名の前に . を入れるのがポイントです(dot source と呼ぶようです)。
. .\log.ps1
function global:Start-FollowRemoteLog
にしてパスを通す方法もありますが、恐らく接続先のサーバーによって tail コマンドの前処理が変わるので、サーバー毎にスクリプト書いて都度読み込みが適切な気がしています。
使い方
関数を呼ぶ場合は以下の通りです。
Start-FollowRemoteLog -HostName yourHostName -RemotePath "access_log" -LocalPath local.log
ssh の接続先設定 yourHostName
は ~/.ssh/config
に設定されている前提です。この config ファイルの設定方法は割愛します。
画面が文字化けする場合は、Powershell のタイトルバーを右クリックし、プロパティからフォントを MS ゴシック に設定してください。コードページを切り替えるとフォントも切り替わるためです(コードページごとに設定が保存される?)。
ローカルに保存されるログは UTF-16 LE というエンコーディングになります。Tee-Object に Encoding オプションはないので、Unicode で保存されます。Out-File に渡すなど、探せばエンコーディング指定する方法がありそうですが、今回はそこにはこだわらないことにしました。
複数ログを1つのログにまとめたい場合は、スペース区切りでログファイル名を指定すると可能です。これは tail の機能です。
Start-FollowRemoteLog -HostName yourHostName -RemotePath "access_log error_log" -LocalPath local.log
Windows 10 で ssh コマンドが普通に使えるようになり、 Unix 系サーバーへの接続が容易になってうれしい限りです。PowerShell と組み合わせればいろいろな事ができそうです。