tech.guitarrapc.cóm

Technical updates

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

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

Filter を利用しよう

guitarrapc/PowerShellUtil - Out-LogHost/Out-LogHost.ps1 | GitHub

出力に渡す内容は、その前のコマンドレット結果です。つまり| %{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色で出力しつつログに書き出します。

PS> $log = "d:\message.log"
PS> "hogehoge" | Out-LogHost -logfile $log -message
[08/14/2013 07:57:58][message][hogehoge][08/14/2013 08:05:15][message][hogehoge]

データ出力の例として、hostにださずログだけ書き出します。

PS> $log = "d:\hidedata.log"
PS> ps | select -First 1 | Out-LogHost -logfile $log -hidedata
Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
    264      26     5456        484   115     0.48  13276 AppleMobileDeviceHelper

データ出力の例として、hostに白文字で出力しつつログに書き出します。

PS> $log = "d:\showdata.log"
PS> ps | select -First 1 | Out-LogHost -logfile $log -showdata
Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
    264      26     5456        484   115     0.48  13276 AppleMobileDeviceHelper

エラー出力の例として、hostにthrowしつつログに書き出します。

PS> $log = "d:\error.log"
PS> try { ps -Name hoge -ErrorAction Stop; } catch { $_ | Out-LogHost -logfile $log -error; }
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

-Appedなどもスイッチ出来るようにすると良いですね。