tech.guitarrapc.cóm

Technical updates

PowerShell で 出力先を簡素化したい

PowerShell は スクリプトとして良く利用します。 そのため、場合によっては 「ホスト画面 と ログに出したい!」「ホストには出さずログだけ!」「ログとthrow したい!」などと適宜変えたくなります。 そんな時にどうしようかなーと思って作ったサンプルです。

Filter を利用しよう

出力に渡す内容は、その前のコマンドレット結果全てなわけです。 つまり | %{function} というのはナンセンスで | filter と したいわけです。 function と filter の違いは、 「filter は 入ってきた入力に自動変数 $_ を割り当てて 各入力を同様に処理する」というイメージです。 function だと 入力ごとに処理をするため、| %{function} とする必要がありますが、 filter なら | filter でいいのが楽です。 Foreach-Object (%) のオーバーヘッドが無くなるので大変よろしいです。

サンプル

filter Out-LogHost{

    param(
        [string]
        $logfile,

        [switch]
        $message,

        [switch]
        $showdata,

        [switch]
        $hidedata,

        [switch]
        $error
    )


    if($message)
    {
        Write-Host "$_`n" -ForegroundColor Cyan
        "[$(Get-Date)][message][$_]" | Out-File $logfile -Encoding utf8 -Append -Width 1024
    }
    elseif($showdata)
    {
        $_
        $_ | Out-File $logfile -Encoding utf8 -Append -Width 1024
    }
    elseif($hidedata)
    {
        $_ | Out-File $logfile -Encoding utf8 -Append -Width 1024
    }
    elseif($error)
    {
        $_ | Out-File $logfile -Encoding utf8 -Append -Width 1024
        throw $_
    }
}
このような感じでしょうか。 メッセージの例 (host に cyan色で出力しつつ、 ログに書き出す)
$log = "d:\message.log"
"hogehoge" | Out-LogHost -logfile $log -message
ホスト画面にでつつ [office src="https://skydrive.live.com/embed?cid=D0D99BE0D6F89C8B&resid=D0D99BE0D6F89C8B%211756&authkey=ABGDmVkIc1nElpM" width="318" height="63"] ログもでます。
[08/14/2013 07:57:58][message][hogehoge][08/14/2013 08:05:15][message][hogehoge]
データ出力の例 (hostにださず ログだけ書き出す)
$log = "d:\hidedata.log"
ps | select -First 1 | Out-LogHost -logfile $log -hidedata
画面にでませんが、 [office src="https://skydrive.live.com/embed?cid=D0D99BE0D6F89C8B&resid=D0D99BE0D6F89C8B%211758&authkey=AAo3dEqZUpnFAHw" width="316" height="43"] ログに出ます。
Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
    264      26     5456        484   115     0.48  13276 AppleMobileDeviceHelper
データ出力の例 (hostに白文字で出力しつつ、 ログに書き出す)
$log = "d:\showdata.log"
ps | select -First 1 | Out-LogHost -logfile $log -showdata
画面にでつつ、 [office src="https://skydrive.live.com/embed?cid=D0D99BE0D6F89C8B&resid=D0D99BE0D6F89C8B%211757&authkey=AKRmutabgONO3qI" width="315" height="57"] ログにも出ます。
Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
    264      26     5456        484   115     0.48  13276 AppleMobileDeviceHelper
エラー出力の例 (hostにthrowしつつ、 ログに書き出す)
$log = "d:\error.log"
try
{
    ps -Name hoge -ErrorAction Stop
}
catch
{
    $_ | Out-LogHost -logfile $log -error
}
ホストにエラーを表示しつつ [office src="https://skydrive.live.com/embed?cid=D0D99BE0D6F89C8B&resid=D0D99BE0D6F89C8B%211759&authkey=ABFXML7ewvDQn5c" width="319" height="115"] エラーもログ出力されます。
ps : Cannot find a process with the name "hoge". Verify the process name and call the cmdlet again.
At line:4 char:5
+     ps -Name hoge -ErrorAction Stop
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (hoge:String) [Get-Process], ProcessCommandException
    + FullyQualifiedErrorId : NoProcessFoundForGivenName,Microsoft.PowerShell.Commands.GetProcessCommand
defaultparameterset使うの忘れてましたが、まぁまた今度で。 -Apped などもスイッチ出来るようにすると良いですね。

GitHub

挙げておきます。
https://github.com/guitarrapc/PowerShellUtil/blob/master/Out-LogHost/Out-LogHost.ps1
実はこの制御を楽にするのは意味があります。それは次回の記事で。