読者です 読者をやめる 読者になる 読者になる

(O+P)ut

IT系の記事やその他諸々,不定期で更新していきます(∵)

【Cygwin】作業ログを自動で残す

テクノロジー Cygwin Linux

明けましておめでとうございます。今年は、少なくとも月1ペースで更新したいと考えています!

さて、Cygwinでちょこちょこと作業をすることが多いのですが script コマンドなるものを使えば、簡単に作業ログを残せることを知りました。
それを自動で行えるようにした際の備忘録です。

scriptコマンドの使い方は、ターミナルで script と打てば以下のようになるかと思います。

$ script
スクリプトを開始しました。ファイルは typescript です

ここから記録が ./typescript に始まり、終了する際は exit と打てば以下のように終了します。

$ exit
exit
スクリプトを終了しました。ファイルは typescript です

オプションや引数をつけることで、ファイルを上書きしたりファイル名を指定もできます。

問題は、これを起動時に自動で実行しようとする際です。
単純に .bashrc に

script

と書くとすごいことになります。以下が私の環境で実際に上記の記述を.bashrcに行い、起動した際の出力です...

スクリプトを開始しました。ファイルは typescript です
スクリプトを開始しました。ファイルは typescript です
スクリプトを開始しました。ファイルは typescript です
スクリプトを開始しました。ファイルは typescript です
スクリプトを開始しました。ファイルは typescript です
スクリプトを開始しました。ファイルは typescript です
スクリプトを開始しました。ファイルは typescript です
スクリプトを開始しました。ファイルは typescript です
スクリプトを開始しました。ファイルは typescript です
スクリプトを開始しました。ファイルは typescript です
スクリプトを開始しました。ファイルは typescript です

実はscriptコマンドは新たにシェルを立ち上げる挙動をするようですので、新たなシェルが立ち上がる→scriptコマンド実行→新たなシェルが... の無限ループになるみたいですね。

$ ps
      PID    PPID    TTY       STIME COMMAND
    13052       1    ?         01:08:49 /usr/bin/mintty
     6288    1936    pty0      01:08:56 /usr/bin/ps
     1936   13052    pty0      01:08:49 /usr/bin/bash

$ script
スクリプトを開始しました。ファイルは typescript です

$ ps
      PID    PPID   TTY      STIME COMMAND
     1288    5712  pty0      01:09:01 /usr/bin/script
    11180    4176  pty1      01:09:04 /usr/bin/ps
     5712    1936  pty0      01:09:01 /usr/bin/script
     4176    1288  pty1      01:09:02 /usr/bin/bash
    13052       1  ?         01:08:49 /usr/bin/mintty
     1936   13052  pty0      01:08:49 /usr/bin/bash

上がすごい分かりやすいと思います。pty1が立ち上がってカレントシェルが変更になります。

なので、今回は簡易的に現在のシェルの親プロセスが /usr/bin/mintty な場合にのみ script を動かすようにします。

autoscript.shというスクリプトを記述しました。*1

#!/bin/sh

ppcheck=`ps | grep $PPID | grep -v pty | awk '{print $8}'`
ttynum=`echo \`tty\` | awk '{print substr($0,(length($0)+1)-1,1)}'`
nowtime=`date +"%Y%m%d%H%M%S"`
filename="${nowtime}_${ttynum}"

if [[ ${ppcheck} = "/usr/bin/mintty" ]]; then
        script -f script_log/$filename
fi

簡単に説明しますと、ppcheckで現在のシェルの親プロセスのIDでプロセスを絞り込み、ttyが?となっている/usr/bin/minttyをppcheckとして取り込んでいます。
それを、現在のttyの最後の数字と現在の時刻とするファイル名でログをとる、という感じですね。こうしておけば、scriptで立ち上がったシェルの親プロセスは/usr/bin/minttyではなくなるので、ループは起きないといった感じです。ファイル名は、時刻だけだと同時にCygwinの窓を複数立ち上げるとやっかいかなーと思ったのでttyから値を持ってきてます。特に深い意味はありません...

これを起動時に実行するために .bashrc に以下のように記載します。

. ./autoscript.sh

カレントシェルで実行するよう記述しているのは、親プロセスが変わってしまうのを防ぐためです。

これでCygwinを立ち上げると

スクリプトを開始しました。ファイルは script_log/20170129011831_0 です

$ ls script_log/
20170129011831_0

とまぁ、こんな感じで機能しています。

とりあえずこれで運用してみて、挙動が怪しい場合にはまたその都度修正していこうと思います。
Cygwinをお使いの方で、同じようなことに興味がある方はご参考ください。

*1:直接.bashrcに記述してもいいですが、テストしやすかったのでそのままshファイルを起動するという構成にしています