web-dev-qa-db-ja.com

Bashでhistappendがoffに設定されていると、履歴が上書きされずに追加されるのはなぜですか?

数日前、1つのターミナルタブでsshを実行し、もう1つのタブでローカルで多くの作業を実行していました。次に、マシンを再起動しました(Mavericksを搭載したMacの場合)。

もう一度ターミナルを実行したところ、2番目のタブのすべてのコマンド履歴がそこにないことがわかりました。 sshコマンドしかありませんでした。

そこで、どういうわけか履歴を「マージ」する方法を検索したところ、shopt -s histappendファイルで~/.bashrcを実行して、「上書き」ではなく履歴を追加する必要があることがわかりました。ある履歴セットが他のセットを上書きすることは望ましくありません。追加したい。

ただし、OS XYosemiteボックスに移動してshoptを使用すると、histappendがオフになっていることがわかりましたが、2つのタブを開くと、1つはecho abcを実行し、もう1人はecho defを実行して終了し、ターミナルを再度開いてhistoryコマンドを発行し、echo abcコマンドとecho defコマンドの両方を確認しました。

次に、VirtualBoxでUbuntu 2014-10を実行し、同様のことを行いましたが、両方の履歴が記録されていました(最初に、両方のBashでshopt -u histappendを実行して、オプションを最初にオフに設定しました)。

では、実際にはどのようなメカニズムがそれを行っているのでしょうか。次に、histappendは、オンまたはオフに設定しても問題がない場合、意味がありませんか?

また、shopt -s histappend.bashrcをコメントアウトし、ターミナルを再起動して再試行したところ、両方のタブの履歴を組み合わせることができました...これは本当に奇妙な動作であり、何が原因でしょうか。

6
nonopolarity

@ David Dai このbash-helpスレッドについては正しいです。

ここ はCの関連するbashコードです。

_if (history_lines_this_session <= where_history () || force_append_history)
  {
    result = append_history (history_lines_this_session, hf);
    history_lines_in_file += history_lines_this_session;
  }
else
  {
    result = write_history (hf);
    history_lines_in_file = history_lines_this_session;
  }
_

_shopt -s histappend_は_force_append_history_をゼロ以外(true)に設定します。

_history_lines_this_session_は、このインタラクティブなbashセッションで入力したコマンドの数です。最初にbashを開始したときは、0です。毎回1ずつ増加します。 Enter 履歴に保存されるコマンド。

where_history()は、インデックス0から始まる、メモリ内履歴リストへのインデックスです。これは、履歴を書き込む次のインデックスを指します。たとえば、履歴が0の場合、インデックス0になります。履歴が6行の場合、インデックス6になります。

bashを最初に開始し、HISTFILEに履歴がある場合、where_history()は増加しますが、_<= HISTSIZE_に制限されます。したがって、where_history()の最大値はHISTSIZEです。

HISTFILEを読み取った後、where_history()は増加しますが、_history_lines_this_session_は0のままです。 Enter _HISTSIZE + 1_コマンドの数、_history_lines_this_session == HISTSIZE + 1_およびwhere_history() == HISTSIZE(最大で上限があるため)。この時点で、_(history_lines_this_session <= where_history()) == false_なので、histappendがオフの場合、履歴は上書きされます。

これは、bashで自分でテストできます。 histappendがオフの場合、_HISTSIZE + 1_のコマンド数を実行すると、_history_lines_this_session_はwhere_history()を1超え、HISTFILEは上書きされます。ただし、テストが機能するためには、他のコマンドが履歴を混乱させていないことを確認する必要があります(macOSで発生します)。次のコマンドを使用して、履歴を混乱させる可能性のあるコマンドをオフにします。

_trap - EXIT
Prompt_COMMAND=
Shell_SESSION_HISTORY=0 # for macOS only
_
2
dosentmatter

histappendoneターミナルに設定された動作だと思います。

新しいターミナルで次のことを試してください。

shopt -s histappend
export HISTSIZE=1
export HISTFILESIZE=500

次に、ターミナルを閉じます。次に、履歴ファイルに、すでに持っていた最後の499個のコマンドと、入力したばかりの「export HISTFILESIZE=50」がどのように含まれているかがわかります。履歴が追加され、500に切り捨てられました。

次に、別の新しいターミナルでこれを試してください。

shopt -u histappend
export HISTIZE=1
export HISTFILESIZE=500

そして、もう一度、ターミナルを閉じます。端末にコマンド「export HISTFILESIZE=500」が1つしかないことがわかります。

秘訣は、histappendがないと、履歴ファイルが端末履歴に現在あるもので上書きされることです(1つのコマンド)。

HISTFILE = HISTFILESIZEの場合、その動作に気付くことはありませんが、複数の端末での作業とは関係がないと思います。これは他の何かで管理する必要があります...

1
poinu