web-dev-qa-db-ja.com

1つの端末を終了するときに、他の端末のbash履歴を更新します

ここで尋ねられるので、私はこの質問が曖昧ではないことを知っています 更新を続けます (そして 重複 ここで)。

私が達成しようとしていることは少し異なります。 lshistory -a; history -c; history -r)と入力するたびにプロンプ​​トがファイルを書き換えるというアイデアは好きではありません。

終了時にファイルを更新したいのですが。これは簡単です(実際にはデフォルトです)が、書き直す代わりに追加する必要があります。

shopt -s histappend

さて、端末が閉じているときは、開いたままになっている他のすべての端末に更新を認識させたいと思います。

入力するすべてのcommand$PS1を介してチェックせずにこれを行うことを好みます。ある種の信号をキャプチャしたほうがいいと思います。どうしますか?不可能な場合は、単純なcronjob

どうすればこのパズルを解くことができますか?

15
Dr Beco

創造的で関与するシグナル、あなたは言いますか? OK:

trap on_exit EXIT
trap on_usr1 USR1

on_exit() {
    history -a
    trap '' USR1
    killall -u "$USER" -USR1 bash
}

on_usr1() {
    history -n
}

.bashrcでそれをチャックして行きます。これはシグナルを使用して、すべてのbashプロセスに、別のプロセスが終了したときに新しい履歴エントリをチェックするように指示します。これはかなりひどいですが、実際に機能します。


どのように機能しますか?

trapはシグナルハンドラーを設定します システムシグナルまたはBashの内部イベントの1つに対して。 EXITイベントはシェルの制御された終了であり、USR1SIGUSR1であり、私たちが流用している意味のないシグナルです。

シェルが終了するたびに、次のことを行います。

  • すべての履歴をファイルに明示的に追加します。
  • SIGUSR1ハンドラーを無効にして、このシェルを ignore シグナルにします。
  • 同じユーザーから実行中のすべてのbashプロセスにシグナルを送信します。

SIGUSR1が到着すると、次のようになります。

  • 履歴ファイルからすべての新しいエントリをシェルのメモリ内履歴リストにロードします。

Bashがシグナルを処理する方法のため、ヒットするまで実際には新しい履歴データを取得しません Enter 次回は、 history -nPrompt_COMMANDに入れるよりも、この面でうまくいくことはありません。ただし、何も起こらなかったときにファイルの読み取りを常に節約し、シェルが終了するまで書き込みはまったく行われません。


ただし、ここにはまだいくつかの問題があります。 1つ目は、 SIGUSR1へのデフォルトの応答は終了することです シェルです。その他のbashプロセス(シェルスクリプトの実行など)はすべて強制終了されます。 .bashrcは、非対話型シェルによってロードされません。代わりに、 BASH_ENVという名前のファイルがロードされます :環境内のその変数をグローバルに設定して、次のファイルを指すようにすることができます。

trap '' USR1

それらの中の信号を無視するためにその中に(問題を解決します)。

最後に、これはあなたが要求したことを行いますが、あなたが得る順序は少し変わっています。特に、履歴のビットは、別々にロードおよび保存されるため、異なる順序で繰り返されます。これは本質的にあなたが求めているものに固有のものですが、上向きの履歴はこの時点ではるかに役に立たなくなることに注意してください。 履歴置換 などは共有され、うまく機能します。

15
Michael Homer