PowerShellの実行結果を「画面」と「ログ」に同時出力する方法4選

Windows
記事内に広告が含まれています。

はじめに:ログだけだと不安、画面だけだと後で困る

PowerShellでスクリプトを動かすとき、実行状況をリアルタイムで見たいですよね。
ログファイルだけだと「今どこで止まった?」が分かりづらいですし、画面だけだと後から検証できません。
だって人間だもの、途中経過を見て安心したいものです。

私も運用現場で「夜間処理が動いている最中に、進んでいるのか止まっているのか分からない問題」に何度も悩みました。
そこでこの記事では、ターミナル(コンソール)に表示しながら、同じ内容をログファイルにも保存する方法を、初心者でも再現できる形で4つまとめます。

結論から言うと、状況によって最適解が変わります。
PowerShellには「パイプラインに流れる出力」と「画面に直接出す出力」があり、さらにエラーや警告などは“別の通り道(ストリーム)”を通ります。
ここを理解すると、ハマりにくくなります。

先に知っておくとラク:PowerShellの「出力の種類」ざっくり

PowerShellの出力には種類があります。
代表的には次のようなものです。

  • 成功出力(標準出力):コマンドの結果(オブジェクト)
  • エラー出力:例外やエラー
  • 警告(Warning)詳細(Verbose)デバッグ(Debug)情報(Information)

これらはPowerShell内部で「ストリーム」として分かれており、リダイレクト(向き先変更)の書き方も決まっています。
たとえば、エラーを成功出力と同じ場所に混ぜたいときは 2>&1 のような記法を使います。

この「どの出力を拾いたいか」で、使う方法が変わります。


方法1:Tee-Object(いちばん手軽。パイプライン出力に強い)

Tee-Object は「出力を2方向に分岐する」コマンドです。
ファイルに保存しつつ、パイプラインにも流す(最後なら画面に表示される)という動きです。

基本形

Get-Process | Tee-Object -FilePath .\run.log

これで、プロセス一覧が画面にも出て、run.log にも同じ内容が残ります。

追記したい場合(ログを上書きしたくない)

Get-Process | Tee-Object -FilePath .\run.log -Append

「エラーも一緒に」ログに入れたい場合

コマンドのエラー(ストリーム2)を成功出力(ストリーム1)に混ぜてから、Teeに流します。

Get-ChildItem C:\NoSuchFolder 2>&1 | Tee-Object -FilePath .\run.log -Append

向いている場面:Get-ChildItem、Get-Processなど「パイプライン出力」が中心の処理

苦手な場面:外部exeが“画面に直接”文字を出すケース(後述)


方法2:Start-Transcript(セッション丸ごと記録。操作ログを残すのに強い)

Start-Transcript は、PowerShellセッションの「画面に出たもの」をまとめて記録する仕組みです。
入力したコマンドや、コンソールに表示された出力が記録されます。

基本形(開始→終了)

Start-Transcript -Path .\transcript.log

# ここに処理を書く
Get-Date
Get-Process | Select-Object -First 3

Stop-Transcript

これで、画面に出た内容がそのままログに残ります。
スクリプトの「ここからここまでログを取りたい」という範囲指定もしやすいです。

注意点:外部exeがコンソールに直接書き込むタイプだと、Transcriptに入らない場合があります(環境・exe次第)。
この場合は次の「方法3」が強いです。

向いている場面:運用作業の証跡を残したい、作業手順と結果をまとめて残したい


方法3:実行時リダイレクト(外部コマンド込みで“全部”拾いたいならこれ)

外部exe(例:robocopy、git、pythonなど)が出す文字は、PowerShellのパイプラインに乗らず「標準出力・標準エラー」として出てくることがあります。
こういうときは、実行時のリダイレクトが安定します。

外部コマンドの標準出力と標準エラーをまとめて扱う

robocopy C:\src C:\dst /E > .\run.log 2>&1
type .\run.log

ただ、これだと「リアルタイム表示」が弱くなりがちです。
そこで、PowerShell側で“まとめた出力”をTeeに流す形にします。

PowerShellの複数ストリームをまとめてTee-Object(*=全部)

& .\myscript.ps1 *>&1 | Tee-Object -FilePath .\run.log -Append

*>&1 は「PowerShellの複数ストリームを成功出力にまとめる」書き方です。
これを挟むことで、エラーや警告なども一緒にTeeに流しやすくなります。

向いている場面:外部コマンドを多用する、どの種類の出力も取りこぼしたくない


方法4:自作のWrite-Log関数(読みやすい運用ログにしたい人向け)

「ログを残す」だけなら上の方法で十分ですが、運用だと次の悩みが出ます。

  • いつのログか分かるようにしたい(日時を付けたい)
  • INFO/WARN/ERRORみたいにレベル分けしたい
  • 後で検索しやすい整形にしたい

この場合は、自分でログ関数を作るのがいちばんコントロールしやすいです。

コピペで使える例(画面+ファイルに同時出力)

function Write-Log {
    param(
        [Parameter(Mandatory)]
        [string]$Message,

        [ValidateSet('INFO','WARN','ERROR')]
        [string]$Level = 'INFO',

        [string]$Path = '.\run.log'
    )

    $ts = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
    $line = "$ts [$Level] $Message"

    # 画面に表示
    Write-Host $line

    # ファイルに追記(UTF-8)
    $line | Out-File -FilePath $Path -Append -Encoding utf8
}

Write-Log "処理を開始します"
Write-Log "フォルダ確認OK" -Level INFO
Write-Log "対象ファイルが見つかりません" -Level WARN
Write-Log "コピーに失敗しました" -Level ERROR

ポイント:この方法は「自分が書いたメッセージ」を確実に両方へ出せます。
逆に、外部コマンドの出力を全部整形して入れたい場合は、方法3と組み合わせるのが現実的です。


結局どれを選べばいい?使い分け早見

  • とにかく手軽:方法1(Tee-Object)
  • 作業記録を丸ごと残す:方法2(Start-Transcript)
  • 外部exe含めて取りこぼしゼロ寄り:方法3(リダイレクト+*でまとめてTee)
  • 読みやすい運用ログを作りたい:方法4(Write-Log関数)

よくあるハマりどころ(初心者がつまずく所だけ先回り)

1)Tee-Objectを使ったのにログに入らない

多くの場合、「パイプラインに流れていない出力」を期待しています。
Write-Host や外部exeの出力は、素直にTeeに乗らないことがあります。そういうときは方法2か3に切り替えるのが早いです。

2)エラーだけログに出ない

エラーは別ストリームなので、2>&1 でまとめてからTeeに流します。

3)Verbose(詳細)がログに入らない

Verboseは別ストリームなので、*>&1 のように「全部まとめる」形にすると拾いやすいです。


まとめ:人間はリアルタイムで見たいし、あとで読み返したい

PowerShellで「画面に出しながらログも残す」は、運用の安心材料です。
リアルタイムで進捗を見られると、余計な不安が減りますし、ログが残れば後で原因調査ができます。

まずは一番簡単な Tee-Object から試して、外部コマンドが絡むなら *>&1 | Tee-Object、作業記録を丸ごと残すなら Start-Transcript、運用ログを整えるなら Write-Log と、段階的にレベルアップするのがおすすめです。

免責規定

この記事で提供される情報は、一般的なガイダンスを目的としており、すべての環境やシステムでの動作を保証するものではありません。
OSのバージョンやリリースによっては、記載されている事が実行できない、または異なる結果をもたらす可能性があります。
また、会社所有のパソコン、スマホ、タブレットなどでは、ポリシーや権限によって実行できない場合があります。
この記事の情報を使用することによって生じる問題や結果について、筆者およびサイト管理者は責任を負いません。
すべての操作は自己責任で行ってください。

もし、記事の中で間違いやご指摘があればコメントを頂けると大変ありがたいです。
最後までお読みいただきありがとうございました。
またお会いしましょう!

コメント

タイトルとURLをコピーしました