MiracleJobLogo
エンジニアのエンジニアによるエンジニアのためのサイト
News 07/25 おすすめ情報に 『 【案件】Azure AD関連の認証設計/azureの基本設計 』 を追加しました。
会員登録するとキャリア診断やサイトに参加することができます。
あなたにおすすめな技術情報、資格、仕事などをお知らせします。

無料会員登録


パスワードを忘れた場合
LINEで送る
MiracleJobBanaLeft1
MiracleJobBanaLeft2


PowerShell スクリプトのLoggingいろいろ
profile-img
投稿者: muto-sanさん
投稿日:2018/10/10 00:56
更新日:2018/10/10 16:18
like-img
分類
技術
テクノロジー
全般
キャリア
運用・保守
投稿内容
スクリプトを作成して業務で使用するとなると、ログを出力する必要が出てきますよね。

PowerShellでは色々な方法があるログメッセージの残し方を幾つか紹介します。


※ PowerShell 6.1を使用します。


以下のようなサンプルを用意しました。関数を作ると楽です。

=====<Logging.ps1>=====
# LogMessage関数を作成。
function LogMessage($Message){
    Write-Output "$(Get-Date -Format G): $Message"
}

LogMessage "スクリプトを開始したよ(*´ー`*)"

# ここでメインの処理を実行。サンプルは5秒待機を5回。
for ($i=1; $i -le 5; $i++){
    Start-Sleep 5
    LogMessage "$i 番目の処理が完了したよ(*´ー`*)"
}

LogMessage "全ての処理が完了したよ(*´ー`*)"
LogMessage "スクリプトを終了するよ(*´ー`*)"
=====<Logging.ps1>=====
Write-Outputはコマンドプロンプトで言うechoに相当し、PowerShellでは「echo」がWrite-Outputのエイリアスとして使用できます。
このスクリプトを実行したときの出力は以下のようになります。

これだけでは画面への出力しか行われませんので、更にファイルへの出力を考えていきます。


■Start/Stop-Transcriptの使用
スクリプトを以下のように改修します。(赤字が変更点)
=====<Logging-Transcript.ps1>=====
# ログ出力先
$logFile = $PSScriptRoot + "\log\logfile.txt"

# LogMessage関数を作成。
function LogMessage($Message){
    Write-Output "$(Get-Date -Format G): $Message"
}

Start-Transcript -Path $logFile -Append

LogMessage "スクリプトを開始したよ(*´ー`*)"

# ここでメインの処理を実行。サンプルは5秒待機を5回。
for ($i=1; $i -le 5; $i++){
    Start-Sleep 5
    LogMessage "$i 番目の処理が完了したよ(*´ー`*)"
}

LogMessage "全ての処理が完了したよ(*´ー`*)"
LogMessage "スクリプトを終了するよ(*´ー`*)"

Stop-Transcript
=====<Logging-Transcript.ps1>=====
このスクリプトの出力結果とファイルの中身は以下のようになります。


ご覧のようにTranscriptは記述が簡単ですが、情報量が多く不要なものまで追記の度に書き込まれるため視認性が悪くなりがち。
また、エンコードの指定が出来ません。
Transcriptは直接コンソール上で作業するログを残すには有用です。

■リダイレクト演算子(>/>>)の使用

=====<Logging-Redirect.ps1>=====
# ログ出力先
$logFile = $PSScriptRoot + "\log\logfile.txt"

# LogMessage関数を作成。
function LogMessage($Message){
    $msg = "$(Get-Date -Format G): $Message"
    Write-Output $msg
    $msg >> $logFile

}

LogMessage "スクリプトを開始したよ(*´ー`*)"
(中略)
LogMessage "スクリプトを終了するよ(*´ー`*)"

==<Logging-Redirect.ps1>=====

出力結果とファイルは以下のようになります。




リダイレクト演算子もエンコードの指定が出来ません。


■Add(Set)-Contentの使用

※これ以降紹介するスクリプトは全てリダイレクト演算子を用いた場合と同様の出力結果となります。 

=====<Logging-AddContent.ps1>=====

# ログ出力先
$logFile = $PSScriptRoot + "\log\logfile.txt"

# LogMessage関数を作成
function LogMessage($Message){
    Write-Output "$(Get-Date -Format G): $Message" `
        |Add-Content -LiteralPath $logFile -Encoding UTF8 -PassThru
}

LogMessage "スクリプトを開始したよ(*´ー`*)"
(中略)
LogMessage "スクリプトを終了するよ(*´ー`*)"
=====<Logging-AddContent.ps1>=====
出力結果はリダイレクト演算子を使ったものと同様です。
追記ではなく上書きする場合はSet-Contentを使います。


Add-Contentは特徴としてファイル書き込み時にファイルに読み込み/書き込みロックをかけるため、処理中はファイルを開けなくなる場合があります。
内部的に、読み書きをロックして開く → 書き込み → 閉じる が繰り返されるイメージです。
書き込み中にファイルを開くと以下のようなポップアップが表示されます。


■Tee-Objectの使用
=====<Logging-Tee.ps1>=====
# ログ出力先
$logFile = $PSScriptRoot + "\log\logfile.txt"

# LogMessage関数を作成
function LogMessage($Message){
    Write-Output "$(Get-Date -Format G): $Message" `
        |Tee-Object -FilePath $logFile -Append
}

LogMessage "スクリプトを開始したよ(*´ー`*)"
(中略)
LogMessage "スクリプトを終了するよ(*´ー`*)"
=====<Logging-Tee.ps1>=====
Linuxのteeコマンドのような標準出力とファイルへ書き込むコマンドです。
エンコードの指定は出来ません。
後述の方法で、ファイルではなく変数へ渡すことも出来ます。

■Out-Fileの使用
=====<Logging-OutFile.ps1>=====
# ログ出力先
$logFile = $PSScriptRoot + "\log\logfile.txt"

# LogMessage関数を作成
function LogMessage($Message){
    $msg = "$(Get-Date -Format G): $Message"
    Write-Output $msg
    $msg |Out-File -LiteralPath $logFile -Encoding UTF8 -Append
}

LogMessage "スクリプトを開始したよ(*´ー`*)"
(中略)
LogMessage "スクリプトを終了するよ(*´ー`*)"
=====<Logging-OutFile.ps1>=====
リダイレクト演算子と似ていますが、こちらはエンコードの指定が出来ます。
Tee-Objectと組み合わせて以下のような記述も可能です。

===================
function LogMessage($Message){
    Write-Output "$(Get-Date -Format G): $Message" `
        |Tee-Object -Variable msg
    $msg |Out-File -LiteralPath $logFile -Encoding UTF8 -Append
}
===================


エンコード指定が可能で読み込み禁止がかからないOut-Fileが基本的には最良の選択肢かなぁと思います。


コメント


MiracleJobBanaRight1
MiracleJobBanaRight2
MiracleJobBanaRight3