SEブログ

【PowerShell】ログの処理方法について

 

こんにちは!SE ブログの相馬です。

 

 

 

今回は、PowerShell でログの処理方法について書いてみました。

 

 

何かの処理結果をログとして残す事は重要です。処理が成功したのか失敗したのか、その結果をログファイルとして PC やサーバー上の指定のフォルダ内に溜め込んでおくようなイメージです。

 

 

そこでログの出力などどのように書いたら良いのか、一つの例として参考になればという事で、皆さまのお役に立てれば良いと思います。

 

 

また、前提としてファイルやフォルダの操作する知識が必要ですので、もし分からないようであれば以下の記事を読んでいただいてから進んで頂く事をお勧めします。

 

【PowerShell】ファイルやフォルダを操作する

 

 

 

スポンサーリンク

サンプル処理内容

 

 

それではいきなりですがサンプルを見てみましょう。適当ではありますが情報ログ、警告ログ、エラーログという文字列をログファイルに入れて出力する内容です。

 

 

ログの内容を変数にどんどん格納してゆかなければなりませんので、変数は配列化しなければなりませんが、PowerShell は省略しても問題ないようですが、ここでは一応明示的に書いてあります。また、ログの内容は配列に += で追加で代入しなければなりません。= で書くと前のログが上書きされてしまいますので注意が必要です。

 

 

また、ログファイルにタイムスタンプを付けましょう。いつログが出力されたか後で分からないといけませんよね。

 

# 配列化 (省略してもOK)
$Msg = @()

# 文字列をログの変数に代入
$Msg += "情報ログ"
$Msg += "警告ログ"
$Msg += "エラーログ"

# ログの出力先
$LogPath = "D:\Log"

# ログファイル名
$LogName = "log"

# Log 出力文字列に時刻を追加
$Time = (Get-Date).ToString("yyyy-MM-dd")

# ログファイル(XXXX_YYYY-MM-DD.log)
$LogFile = $LogName + "_" + $Time + ".log"

# ログフォルダーがなかったら作成
if(-not(Test-Path $LogPath)) {
    New-Item $LogPath -Type Directory
}

# ログファイル名作成 Join-Path で変数を結合
$LogFileName = Join-Path $LogPath $LogFile

# ログ出力
Write-Output $Msg | Out-File -FilePath $LogFileName -Encoding Default -append

 

 

 

処理結果、以下のように D:\Log にファイル (log_yyyy-mm-dd) が出力されました。※PC の日付を和暦で設定しているので表示では 01 になっています。

 

 

 

ログの内容です。代入した文字列が全て入っていますね。

 

 

 

 

スポンサーリンク

ログの出力方法

 

 

ログファイルですので、拡張子 .log を使います。また $Msg に溜め込んだログを Out-File コマンドレットでファイルとして保存する方法になります。

 

Write-Output $Msg | Out-File -FilePath $LogFileName -Encoding Default -append

 

 

また、出力したログをパイプでファイル出力に渡しているので、その辺はパイプについて理解されていたほうが良いでしょう。

 

【PowerShell】Pipeline(パイプライン)とは何か

 

 

 

関数化してみる

 

 

ログの出力処理はスクリプト内で何度も使われる場合があります。というか使われます。

 

 

処理に成功したらログに出力する、失敗してもログに出力するのですが、処理内容の中で失敗した場合のほうが明らかに多いためにエラー処理の中で何度も再利用する事になります。

 

 

そのたびに上の処理内容をエラー処理の中に都度書くと処理内容が多くなってしまうばかりか、保守性によくありません。例えば、エラー処理毎にログの処理を書いているスクリプトをリリースした場合、その後にログの処理を変更する事になった場合、ログの処理を書いた分全てを修正しなければなりません。

 

 

これは労力が要りますし、時間の無駄でもあり、一部のログの内容を修正しわすれてしまって処理が失敗してしまったという人的ミスになりかねません。これは避けたいところですよね。

 

 

このように、処理を再利用しなければならない場合は関数化してしまえば 1 つの処理内容だけメンテナンスすれば良くなりますので効率的です。

 

 

関数について知識がまだ無い方は、以下の記事を理解してから進んで頂く事をお勧めします。

 

【PowerShell】関数(function)を使ってみる

 

 

 

ここでは、テキストファイルの中にユーザー名があると仮定して、そのテキストファイルがあれば Import-Csv コマンドレットで読み込んでから ForEach-Object を使い繰り返し処理で AD のグループにユーザーを追加する処理を書いてみました。

 

function Log($Msg) {

    # ログの出力先
    $LogPath = "D:\Log"

    # ログファイル名
    $LogName = "log"

    # Log 出力文字列に時刻を追加
    $Time = (Get-Date).ToString("yyyy-MM-dd")

    # ログファイル(XXXX_YYYY-MM-DD.log)
    $LogFile = $LogName + "_" + $Time + ".log"

    # ログフォルダーがなかったら作成
    if( -not (Test-Path $LogPath) ) {
        New-Item $LogPath -Type Directory
    }

    # ログファイル名
    $LogFileName = Join-Path $LogPath $LogFile

    # ログ出力
    Write-Output $Msg | Out-File -FilePath $LogFileName -Encoding Default -append

}
$Msg = @()

$File = "D:\Work\AddUser.txt"
# 処理開始の宣言
$Msg += Write-Output "$(Get-Date) ADグループにメンバを追加する処理を開始します。"

# ファイルの有無確認
If (Test-Path $File) {

    # ファイルの読み込み
    Import-CSV -Path $File | `
    # 繰り返し処理で、ADのグループにユーザーを追加
    ForEach-Object { `
        Add-ADGroupMember -Identity "Marketing" -Members $_.'user' -Confirm:$false `
    }
}
# 成功した場合のメッセージ追加
$Msg += Write-Output "$(Get-Date) ADグループにメンバを追加しました。"

} Else {
    # 失敗した場合のメッセージ追加
    $Msg += Write-Output "$(Get-Date) ファイルが見つかりません。"
    # 関数に$Msgを渡す
    Log($Msg)
    # 処理中断
    Exit

}
# 関数に$Msgを渡す
Log($Msg)

 

 

 

スポンサーリンク

まとめ

 

 

以上になります。いかがでしょうか。

 

 

スクリプトを書くにあたり、ログの処理は必須ですのでこの処理内容には慣れておくと良いでしょう。また関数に慣れて再利用できるようにもしておきましょう。

 

 

関数は慣れないとなかなか使えないと思います。私がそうでしたが最初は、function の関数と一緒に指定する引数が最初は分かりにくいのかなと思ったりします。あと、関数を実行する際に指定する引数についても分かりにくいと思います。

 

 

これは慣れるしかないので、コードを書いて実行する事を繰り返しやっていけば理解できるようになりますので心配ないと思います。とにかく継続してスクリプトを書いてみましょう。

 

 

それでは最後までお読みいただきありがとうございました!