at posts/single.html

ターミナルのログを自動保存したい

LinuxやMacOS Xのターミナルで作業したときに、入力したコマンドやその結果を自動で記録したい。

terminal

今までは手動でメモ帳やEvernoteにコピー&ペーストしてたけど、さすがにコマンドごとにコピペするのは面倒。 自動で保存する方法を調べてみた。

script コマンド

昔からあるスタンダードな方法。 script [ログファイル名]で保存を開始し、exitもしくはCTRL+Dで保存終了。 ファイル名を省略するとtypescriptというファイルに出力される。

$ script
Script started, output file is typescript

$ ls -l
total 504
drwx------+ 14 machu  staff     476  5 28 09:11 Desktop/
drwx------+ 54 machu  staff    1836  5  1 12:09 Documents/
drwx------+ 47 machu  staff    1598  5 26 22:13 Downloads/
drwxr-xr-x@ 13 machu  staff     442  5 26 10:48 Dropbox/

$ exit

Script done, output file is typescript

ログファイルをcatコマンドで表示すると、先ほどの記録 (ls -lコマンドの実行)が確認できる。

Script started on Sat May 28 09:19:19 2011
$ ls -l
total 504
drwx------+ 14 machu  staff     476  5 28 09:11 Desktop/
drwx------+ 54 machu  staff    1836  5  1 12:09 Documents/
drwx------+ 47 machu  staff    1598  5 26 22:13 Downloads/
drwxr-xr-x@ 13 machu  staff     442  5 26 10:48 Dropbox/

$ exit

Script done on Sat May 28 09:19:37 2011

ログファイルにはターミナルへの出力内容が、制御文字を含めてそのまま出力される。 そのため、残念ながらテキストエディタでは開くと可読性が落ちる。

$ less typescript
Script started on Sat May 28 09:19:19 2011
ESC_machu@macbook:~ESC\ESC[1;34m[machu:~]$ESC[0m ls -l
total 504
drwx------+ 14 machu  staff     476  5 28 09:11 Desktop/
drwx------+ 54 machu  staff    1836  5  1 12:09 Documents/
drwx------+ 47 machu  staff    1598  5 26 22:13 Downloads/
drwxr-xr-x@ 13 machu  staff     442  5 26 10:48 Dropbox/
ESC_machu@macbook:~ESC\ESC[1;34m[machu:~]$ESC[0m exit

Script done on Sat May 28 09:19:37 2011

.zshrc などに書いておけば、シェルの起動時に自動的に保存することもできそう。 詳しくはコアテクの路地 - 作業ログの取り方などを。

screen コマンドのログ

screen コマンドを使っている場合は、screen側でログを記録することもできる。

CTRL+Aの後に大文字の「H」で記録を開始し、もう一度同じコマンドで記録終了。 また、 .screenrcコマンドに以下のように書いておけば、自動的にログを記録してくれる。 「deflog on」が自動保存の設定で、「logfile [ファイル名]」が保存先のファイル名。

deflog on
logfile "logs/screen-%Y%m%d-%n.log"

ログファイル名には年月日+ウインドウ番号が含まれる。

$ ls -l logs
total 312
-rw-r--r--  1 machu  staff   3899  5 28 09:27 screen-20110528-0.log
-rw-r--r--  1 machu  staff   6089  5 28 09:27 screen-20110528-1.log

ログファイルの中身は script コマンドと同様に、制御文字が含まれる。 表示するには cat コマンドを使う。

ちなみに、開いているウインドウと同じ番号のログファイルを開くと、無限ループに突入しファイルサイズが一気に大きくなるので注意。 (表示しているログの内容がログに追記され、それをまた表示しての繰り返し)

screen コマンドのハードコピー

ログに制御文字を含みたくない。テキストエディタで開きたいというときには、 screen のハードコピーが使える。 CTRL+Aの後に小文字の「h」で、現在の画面の内容をテキストに書き出してくれる。 ファイル名は hardcopy.0 (数字の箇所はウインドウ番号)で、ホームディレクトリに出力される。

$ vim app/models/user.rb
# vimが起動されている状態でCTRL+A hを押す
Screen image written to "hardcopy.0".

ログファイルには制御文字を含まないので、テキストエディタでも表示できる。 ちゃんとvimのフッタ部分も表示されている。

$ less ~/hardcopy.0
  2   include Mongoid::Document
  3   # Include default devise modules. Others available are:
  4   # :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable
(中略)
 45 end
~
~
app/models/user.rb [Rails][iso-2022-jp][unix]                                                                                                                       45,1     All
"app/models/user.rb" [converted] 45L, 1451C

ただしhardcopyでは、現在ウインドウに表示されている部分しか記録されない。 WindowsのPrintScreenに似ている。 そういった特性があるので、自動保存もできない模様。

まとめ

screenを使っていなければscriptコマンド。 screenを使っていて、ログに制御文字が含まれてもよいならログ機能 (deflog) が使える。 制御文字を含みたくなければ、ハードコピーになる。 ただし、ハードコピーだと、現在の描画部分しか記録されない。

どれも一長一短。 自動保存してEvernoteに送るには、何を使うのが良いのだろうか…。 screen + ログで記録をとって、後から制御文字だけ削除とか?

追記

id:y0sh1kawさんより、コメントをいただいた。

screenのhardcopyは-hをつければスクロールバックバッファ全体を保存できますよ〜。

CTRL+a hでハードコピーをとるのではなく、CTRL+a :(コロン)でコマンドモードに入り、以下のように入力する。

:hardcopy -h test.log
Screen image appended to "test.log".

以下の条件だったら、制御文字を含まずにいい感じでログが保存できた。

  • zshでRPROMPTを使っていない
  • 出力結果に日本語(マルチバイト文字?)が含まれない

毎回ログファイル名を入力しないといけないのは、ちょっと面倒。 終了時に自動的に保存してくれるといいのにね。

-hを指定したハードコピーの取り方は、以下のページも参考になった。

アジアのペンギン: 作業ログの取り方(screen編)

関連する日記