コマンドプロンプトのログ取得方法 (Bash on Ubuntu on Windows活用)

               公開日:2017/05/20

はじめに

2017年5月、Windows10のコマンドプロンプトのログを簡単に取得する方法がありましたのでメモします。

コマンドプロンプト

コマンドプロンプト

最近は、Windows10のGUIベースでほとんどの処理を実行できます。しかし、コマンドプロンプトのCUIベースでコマンドを入力して処理した方が簡単な場合もあります。私は、MS-DOS時代からコマンドベースで操作してきたので、今でもコマンドプロンプトをよく使います。

コマンドプロンプトで操作しているときに、画面に表示されたログをテキストで保存したいことがあります。そのときに使用するテクニックについてメモしておきます。

ログ取得方法 (その1)

コマンドプロンプトには画面バッファがあり、スクロールして画面から消えたログも記録しています。ログをテキストで保存するには、画面バッファから保存するログ部分を選択してコピペします。

  1. タイトルバー右端のコマンドプロンプトアイコンをクリックします。
  2. [編集(E)]−[マーク(K)]を選び、コピーする文字列を選択します。
  3. [編集(E)]−[コピー(Y)]を選び、クリップボードにテキストをコピーします。
  4.  コピー先のテキストエディタ等で、CTRL+Vで貼り付けます。
コマンドプロンプト編集

コマンドプロンプト編集

Windows10では、コマンドプロンプト(cmd.exe)が強化されて使いやすくなりました。Windowsの標準作法である CTRL+C/CTRL+V によるコピペ操作がコマンドプロンプトで使用できるようになりました。

コマンドプロンプト・プロパティのオプションタグに「コンソールの新機能の詳細」というリンクがあります。

コマンドプロンプトのプロパティ

コマンドプロンプトのプロパティ

このリンクをクリックして、マイクロソフト TechNetの
What’s New in the Windows Console in Windows Server 2016 Technical Preview」というページを見ます。

You can copy and paste text in the console using keyboard commands.
CTRL+C now serves two functions.
If no text is selected when you use it, it sends the BREAK command as usual.
If text is selected, the first use copies the text and clears the selection; the second use sends BREAK.

【要約】

キーボードコマンドを使用して、コンソールにテキストのコピーとペーストができます。
CTRL+Cは2つの機能を提供するようになりました。
テキストが選択されていない場合、通常どおりBREAKコマンドが送信されます。
テキストが選択されている場合、最初の使用でテキストがコピーされ、選択がクリアされます。2回目の使用でBREAKが送信されます。

MS-DOS時代からコマンドプロンプトでCTRL+Cを入力すると、プログラムの強制終了になりました。CTRL+C入力が、テキストを選択している場合はテキストのコピー機能となったわけです。

キーボード操作でコマンドプロンプトのログをコピペすることが可能になりました。CTRL+M で選択モードを開始します。矢印キーで上下左右にカーソルを移動させて、Shiftキーを押しながらテキストを選択します。CTRL+C で選択したテキストをコピーします。コピー先のテキストエディタ等で、CTRL+Vで貼り付けます。

ログ取得方法 (その2)

別の方法について検討します。

コマンドプロンプトの操作では、標準出力をリダイレクトしてコマンド出力をファイルに出力する方法をよく使います。

E:\> dir >log.txt

しかし、この方法ではコマンド出力はファイル出力しますが、画面に表示されません。


Linuxでは、標準入力を標準出力とファイルに出力する tee というコマンドがあります。コマンド出力をパイプ接続してteeコマンドを使用すると、コマンド出力を画面とファイルに出力することができます。

$ dir | tee log.txt

Windowsのコマンドプロンプトには、teeコマンドがありません。

しかし、Bash on Ubuntu on Windows(Ubuntu 16.04.2 LTS)を使用すると、Windows環境のコマンドプロンプトからUbuntu環境のコマンドを実行することが可能になりました。

コマンドプロンプトのdirコマンド出力をパイプ接続して、Ubuntu環境(bash)のteeコマンドに出力して画面とファイルに出力します。

dir | bash -c "tee log.txt"

ログ取得方法 (その3)

コマンド入力ごとに、標準出力をパイプ接続してteeコマンドでファイル出力するのは面倒な操作です。

そこで、コマンドプロンプト自体の出力をハイプ接続してteeコマンドを使用するようにします。


コマンドプロンプトで、cmdと入力すると子プロセスでコマンドプロンプト(cmd.exe)を実行します。

E:\> cmd
Microsoft Windows [Version 10.0.15063]
(c) 2017 Microsoft Corporation. All rights reserved.

E:\> echo %OS%
Windows_NT

E:\> del a.txt
E:\a.txt が見つかりませんでした。

E:\> exit

echoコマンドで、環境変数 OSの値を表示すると、Windows_NTとなります。
存在しないファイル a.txt を削除すると、エラーとなります。
exitコマンドで子プロセスを終了します。


コマンドプロンプトを子プロセスで実行するときに標準出力をパイプ接続してteeコマンドでファイル出力します。

E:\> cmd | bash -c "tee log.txt"
Microsoft Windows [Version 10.0.15063]
(c) 2017 Microsoft Corporation. All rights reserved.

E:\> echo %OS%
Windows_NT

E:\> del a.txt
Could Not Find E:\a.txt

E:\> exit

echoコマンドで、環境変数 OSの値を表示すると、Windows_NTとなります。
存在しないファイル a.txt を削除すると、エラーとなります。なぜかエラーメッセージが英語となりました。

log.txt の内容を確認します。

E:\> type log.txt
Microsoft Windows [Version 10.0.15063]
(c) 2017 Microsoft Corporation. All rights reserved.

E:\>Windows_NT

E:\>
E:\>

なんか、ログの内容が不足していますね。

標準出力をパイプ接続してteeコマンドでファイル出力しているだけなので、キーボードから入力した「echo %OS%」と「del a.txt」の部分はファイル出力されていません。また、存在しないファイル a.txt を削除するときのエラーメッセージがファイル出力されていません。


エラーメッセージは、標準出力(stdout)ではなく標準エラー出力(stderr)に出力します。

コマンドプロンプトを子プロセスで実行するときに、標準エラー出力を標準出力にマージしてから、標準出力をパイプ接続してteeコマンドでファイル出力します。

E:\> cmd 2>&1 | bash -c "tee log.txt"
Microsoft Windows [Version 10.0.15063]
(c) 2017 Microsoft Corporation. All rights reserved.

E:\> echo %OS%
Windows_NT

E:\> del a.txt
Could Not Find E:\a.txt

E:\> exit

log.txt の内容を確認します。

E:\> type log.txt
Microsoft Windows [Version 10.0.15063]
(c) 2017 Microsoft Corporation. All rights reserved.

E:\> Windows_NT

E:\>Could Not Find E:\a.txt

E:\>

標準エラー出力のエラーメッセージがファイル出力されるようになりました。


キーボードからの入力も含めてファイル出力するために、次のようにします。

E:\> type con| cmd 2>&1 | bash -c "tee log.txt"
Microsoft Windows [Version 10.0.15063]
(c) 2017 Microsoft Corporation. All rights reserved.

E:\> echo %OS%
echo %OS%
Windows_NT

E:\> del a.txt
del a.txt
Could Not Find E:\a.txt

「con」は、MS-DOS時代から使用しているデバイスファイル名のひとつで、コンソール(標準入出力)を現します。出力先として使用した場合は画面出力、入力元として使用した場合はキーボード入力となります。

typeコマンドで、conデバイス(キーボード)から入力したストリングを標準出力に出力します。その標準出力をパイプ接続して、cmdコマンドに入力します。cmdコマンドの標準出力は、キーボードからの入力とコマンドの実行結果となります。cmdコマンドの標準エラーを標準出力にマージして、teeコマンドでファイルに出力します。

パイプで接続した、type – cmd – tee は並行動作するのでキーボードの入力は、すぐに実行してファイル出力します。teeコマンドは英語の「T」文字の形がイメージするようにパイプを分岐ています。

コマンドプロンプトのログ取得

コマンドプロンプトのログ取得

 

画面上にキーボード入力とそれを標準出力したストリングを表示しているので、入力したコマンド部分が二重になって見えます。

log.txt の内容を確認します。

E:\> type log.txt
Microsoft Windows [Version 10.0.15063]
(c) 2017 Microsoft Corporation. All rights reserved.

E:\> echo %OS%
Windows_NT

E:\> del a.txt
Could Not Find E:\a.txt

キーボードからの入力も含めてファイル出力しました。

exitコマンドで子プロセスのコマンドプロンプトを終了しますが、パイプ破棄とコマンドプロンプト終了のタイミングが合わず、下記エラーが発生します。

プロセスが、存在しないパイプに書き込もうとしました。

対策方法は不明です。exitコマンドで終了させないようにします。

ログ取得方法 (お勧め)

Bash on Ubuntu on Windows(Ubuntu 16.04.2 LTS)を活用して、Windows環境のコマンドプロンプトからUbuntu環境(bash)のteeコマンドを実行することにより、コマンドプロンプトのログを取得できました。

bashを使用できるので、ログファイル名を日時付きにします。

E:\> type con| cmd 2>&1 | bash -c "tee log$(date +%Y%m%d_%H%M%S).txt"
Microsoft Windows [Version 10.0.15063]
(c) 2017 Microsoft Corporation. All rights reserved.

「log$(date +%Y%m%d_%H%M%S).txt」で、dateコマンドで日付「YYMMDD」と時分秒「hhmmss」をファイル名に埋め込んで、logYYMMDD_hhmmss.txtというログファイルに出力します。

最後に

これで、コマンドプロンプトで操作しているときに画面に表示されたログをテキストで保存することができました。

ログ取得するのに便利となりました。
しかし、コマンドプロンプトの便利な機能であるTABキーによるファイル名補完機能が無効になってしまいました。

 

 

このエントリーをはてなブックマークに追加