SSブログ

SSH端末を切断したりして、.bash_logout が走らない時の対応策。 [Linux]

Linuxのログアウトの時に、コマンド履歴をクリアしたい場面があるとします。
これは ~/.bash_logout に以下の処理を入れ込めばできます。

history -c
history -w


履歴をクリアにしてから、ファイルに上書きするのですね。history -cだけで消えたと思ってしまいますが、メモリに常駐しているヒストリーが消えただけなので、次の時に.bash_historyから復活してしまいます。以前のexit時に.bash_historyがなければ、exitで消えてしまうので問題ないんですが、history -w しない片手落ちのサイトをそこそこ見ました。

なお、消すだけじゃなくて、履歴をどこかに取っておきたいなら、history -cの前でhistoryコマンドを適当なディレクトリでリダイレクトします。


ただ、そこには問題があって、exitコマンドを打って終了してあげないと、.bash_logoutが発動しないんですね。SSH端末ごと終了したり、何かのタイムアウトで接続が切れてしまったりしても、.bash_logoutの処理は走りません(少なくとも自分のところの環境ではみなそうであった)。仮に上のようにコマンド履歴をクリアしたくても自動でしてくれなくなってしまう。

https://yeupou.wordpress.com/2018/03/29/clearing-bash-history-on-exit-of-any-kind/
https://tutorialmore.com/questions-183794.htm

ここ↑の両サイトには以下のような.bashrcを書けばよいと書いてあります。
もちろん /etc/bashrc に書いてもいい。

exit_session() {
 . "$HOME/.bash_logout"
}
trap exit_session SIGHUP

alias exit='. "$HOME/.bash_logout" ; exit'

でも、自分のところではこれではSSH端末を終了させたときに.bash_logoutが発動しなかった。
それとaliasで始まる最後の行はなくても大丈夫みたい。

自分のところで動いたコードは、最後の行が

trap exit_session EXIT


でした。SIGHUPをEXITにしただけ。その他のところは変えなくても問題なく動くみたいです。
SIGHUPではダメな人はEXITをお試しあれ。
exitせずにSSH端末を落としても、たぶん他のところから回線が切られても.bash_logoutは動作します。ただこれはRHELとTeraTermやRLoginの組み合わせなので、他では効いてこないかもしれないです。

https://shellscript.sunone.me/signal_and_trap.html

https://unix.stackexchange.com/questions/371161/bash-logout-is-not-running-on-exit-of-putty
https://superuser.com/questions/410525/explain-why-bash-logout-wont-run-commands/410534#410534

ここいらへんを見て、少し試行錯誤しました。コンピュータ関係では書いてあることと違う事も結構ある。確かにSIGHUPを無視するnohupというコマンドもあるくらいだから、SIGHUPで良さそうだけど実際には動かなかった。なので動くコードが正本ってことで、自分の環境には適用しました。動かないと話にならないもんね。

というか、正常終了しなくても.bash_logoutが動いてほしいんだけど。


《後記》
trap exit_session EXIT という書き方で一般ユーザーはきちんと.bash_logoutの処理が動いていたんだけれど、rootだとなぜか動かないんだよね。/root/.bash_logoutに設定しているんだけども、rootで端末ぶち切ったときには発動しない。なぜなんだろう…


解決したようです。
trap exit_session EXIT
trap exit_session 1 2 3 15

と書けば動作しました。
https://shellscript.sunone.me/signal_and_trap.html

1,2,3,15のシグナルでrootでは引っ掛かってる模様。それなら
trap exit_session 0 1 2 3 15

で良さそうなものだけれど、分けて書いたほうがいいみたいなサイトもあったので結局分けた。

でも、それでもまだ問題が出た。消すだけならいいんだけど、先にも言ったようにhistoryをリダイレクトして他の場所に出力すると、なぜかファイルが空になる。何で履歴が空になるんだろうと不思議に思っていたんだけど、どうやら.bash_logout が少なくとも2回実行されているみたいなのだ。なので1回目のリダイレクトで書き込めても、2回目に空になったhistoryの出力で上書きされて空になる。

bashのバグか、それもそのバージョンだけのbashのバグかわからないけど、場合によっては2回実行される(いつもではない)のは再現している。さらに面倒なことにそこのサーバはユーザーを段階的に踏んで、rootになるようになっていて(まぁ普通はrootでいきなり入れないようにする)、rootになるまで数ユーザーを経ている。なのでSSHクライアントをぶち切った後、各ユーザーの.bash_logoutの処理が走るわけだが、そのせいもあるのかもしれない。

処理的には使っている各ユーザーの処理がスタックされて.bash_logoutが走っているのはわかるのだが、2回走る意味がわからない。設定でそうなっている可能性はあるのだが、そこまで調べたくない。なので

history > /var/log/history_user01`date +%Y%m%d%H%M`.log

history >> /var/log/history_user01`date +%Y%m%d%H%M`.log
に変えた。
そうすれば2回目に空の内容を書き込もうとしても、1回目の出力は消えない。やっと解決した感じ。




問題として
・SIGHUPでtrapされない
・rootで実行されない
・.bash_logout が複数回実行される

ということがあったわけだが、

・trapをEXITにする
・trapを1 2 3 15 にする
・historyの出力をリダイレクトする場合、上書きでなく追記にする

でとりあえず解決した。遠い道のりであった…
最後に関しては特定のバージョンのバグぽいので、やらなくていい場合はあると思うけど、やっておいてもたぶん害はないので大丈夫なはず。

コメント(0) 
共通テーマ:パソコン・インターネット

コメント 0