まず、これはSEの既存のスレッドの複製ではありません。私はより良いbash履歴でこれら2つのスレッド( 1st 、 2nd )を読みましたが、どれも機能しません-ちなみに私はFedora 15を使用しています。
ユーザーディレクトリ(/ home/aahan /)の.bashrc
ファイルに以下を追加しましたが、機能しません。誰か手がかりはありますか?
HISTCONTROL=ignoredups:erasedups # no duplicate entries
HISTSIZE=1000 # custom history size
HISTFILESIZE=100000 # custom history file size
shopt -s histappend # append to history, don't overwrite it
Prompt_COMMAND="history -a; history -c; history -r; $Prompt_COMMAND" # Save and reload the history after each command finishes
わかりました、これはbashの履歴(優先度)に必要なものです。
これは実際には非常に興味深い動作であり、私は最初に質問を非常に過小評価していたことを認めます。しかし、最初の事実:
機能はいくつかの方法で実現できますが、それぞれの動作は少し異なります。いずれの場合も、履歴を別の端末に「転送」(更新)するには、 Enter ターミナルで、履歴を取得したい場合。
オプション1:
shopt -s histappend
HISTCONTROL=ignoredups
Prompt_COMMAND="history -a; history -n; $Prompt_COMMAND"
これには2つの欠点があります。
オプション2:
HISTCONTROL=ignoredups
Prompt_COMMAND="history -a; history -c; history -r; $Prompt_COMMAND"
(はい、shopt -s histappend
は不要です。はいはhistory -c
の真ん中にある必要がありますPrompt_COMMAND
)このバージョンには、2つの重要な欠点もあります。
history
コマンドは誤った出力を出す可能性があります-以下を参照してください。[編集] "そして勝者は..."
オプション3:
HISTCONTROL=ignoredups:erasedups
shopt -s histappend
Prompt_COMMAND="history -n; history -w; history -c; history -r; $Prompt_COMMAND"
これは可能な限りです。 erasedups
と共通の履歴の両方を同時に機能させるのはonlyオプションです。 これはおそらく、すべての問題の最終的な解決策です、アーハン。
すでに述べたように、上記のソリューションはそれぞれ異なる動作をします。しかし設定がどのように機能するかについて最も誤解を招く解釈は、history
コマンドの出力を分析することから得られます。多くの場合、コマンドはfalse出力を提供できます。どうして? それが実行されるのでbeforePrompt_COMMAND
!に含まれる他のhistory
コマンドのシーケンスただし、2番目または3番目のオプションを使用する場合は、.bash_history
の内容の変更を監視して(たとえばwatch -n1 "tail -n20 .bash_history"
を使用して)、実際の履歴を確認できます。
それはすべてerasedups
の動作にあります。 bashマニュアルに記載されているように、 "(...)erasedups
を指定すると、現在の行と一致する以前のすべての行が、その行が保存される前に履歴リストから削除されます"。したがって、これは実際にOPが望んだものです(そして、以前考えたように、重複が表示されないようにするだけではありません順番に)。 history -.
コマンドのそれぞれがPrompt_COMMAND
に含まれる必要がある、または含まれない理由は次のとおりです。
history -n
has他の端末から保存されたコマンドをhistory -w
から読み取る.bash_history
の前にある、
history -w
has履歴をファイルに保存し、重複を消去するためにそこにあります、
history -a
必須ではありませんhistory -w
の代わりに配置します。これは、重複の消去をトリガーしないためです。
history -c
も必要です。これは、各コマンドの後に履歴バッファが破棄されるのを防ぐためです。
そして最後に、history -r
は必要であり、ファイルから履歴バッファを復元し、最終的に履歴を端末セッション間で共有します。
プロンプトコマンドでは、-c
スイッチを使用しています。 man bash
から:
-cすべてのエントリを削除して履歴リストをクリアします
開いているすべてのターミナルで履歴を共有するには、-n
を使用できます。
-n履歴ファイルから現在の履歴リストにまだ読み込まれていない履歴行を読み取ります。これらは、現在のbashセッションの開始以降に履歴ファイルに追加された行です。
デフォルトのサイズもマニュアルにあります:
HISTSIZEコマンド履歴に記憶するコマンドの数(以下の履歴を参照)。デフォルト値は500です。
複数行のコマンドを保存するには:
cmdhist Shellオプションを有効にすると、シェルは複数行コマンドの各行を同じ履歴エントリに保存しようとし、構文の正確さを保つために必要に応じてセミコロンを追加します。 lithist Shellオプションを使用すると、シェルはコマンドをセミコロンの代わりに改行を埋め込んで保存します。
また、HIST *コマンドの前にexport
を付けないでください。これらは環境変数ではなくbash専用の変数です。HISTCONTROL=ignoredups:erasedups
で十分です。
これが私が思いついたもので、今のところ満足しています…
alias hfix='history -n && history | sort -k2 -k1nr | uniq -f1 | sort -n | cut -c8- > ~/.tmp$$ && history -c && history -r ~/.tmp$$ && history -w && rm ~/.tmp$$'
HISTCONTROL=ignorespace
shopt -s histappend
shopt -s extglob
HISTSIZE=1000
HISTFILESIZE=2000
export HISTIGNORE="!(+(*\ *))"
Prompt_COMMAND="hfix; $Prompt_COMMAND"
ノート:
HISTIGNORE
は、引数を持たないすべてのコマンドを無視します。これは、一部の人々にとって望ましくない場合があり、除外することができます。代わりにこれを使用してください:
HISTCONTROL=ignoreboth
次のことを忘れているため、機能しません。
-n read all history lines not already read from the history file and append them to the history list
ただし、history -n
が有効な場合、export HISTCONTROL=ignoreboth:erasedups
はバグがあるようです。
実験してみましょう:
$ Prompt_COMMAND=
$ export HISTCONTROL=ignoreboth:erasedups
$ export HISTFILE=~/.bash_myhistory
$ HISTIGNORE='history:history -w'
$ history -c
$ history -w
ここでは、dupsの消去をオンにし、履歴をカスタムファイルに切り替え、履歴をクリアします。すべてのコマンドが完了すると、空の履歴ファイルと現在の履歴に1つのコマンドがあります。
$ history
$ cat ~/.bash_myhistory
$ history
$ 1 [2019-06-17 14:57:19] cat ~/.bash_myhistory
2番目のターミナルを開き、これらの6つのコマンドも実行します。その後:
$ echo "X"
$ echo "Y"
$ history -w
$ history
1 [2019-06-17 15:00:21] echo "X"
2 [2019-06-17 15:00:23] echo "Y"
現在の履歴には2つのコマンドがあり、履歴ファイルには次のものが含まれています。
#1560772821
echo "X"
#1560772823
echo "Y"
最初のターミナルに戻る:
$ history -n
$ history
1 [2019-06-17 14:57:19] cat ~/.bash_myhistory
2 [2019-06-17 15:03:12] history -n
ええと... echo
コマンドはどれも読み込まれません。もう一度2番目の端末に切り替えて、
$ echo "Z"
$ history -w
履歴ファイルは次のとおりです。
#1560772821
echo "X"
#1560772823
echo "Y"
#1560773057
echo "Z"
もう一度最初の端末に切り替えます。
$ history -n
$ history
1 [2019-06-17 14:57:19] cat ~/.bash_myhistory
2 [2019-06-17 15:03:12] history -n
echo "Z"
echo "Z"
コマンドがhistory -n
にマージされていることがわかります。
別のバグは、コマンドがコマンド時間ではなくコマンド番号で履歴から読み取られるためだと思います。他のecho
コマンドが履歴に表示されることを期待しています
私はここに答えを組み合わせて行きました:
$ ./.secretfunction -user myuser -password mypassword
はスペースで始まるため、保存されません。history*
とexit
をHISTIGNOREに追加したのは、history | grep awesomecommand
などの過去の履歴を含むコマンドを通常は必要としないためです。 logout、fg、bgなどのような他のものを追加できます。HISTCONTROL=ignoreboth:erasedups:ignorespace
HISTIGNORE="history*:exit"
HISTFILE=~/.bash_history/.$(hostname)_history
shopt -s histappend
function historymerge {
history -n; history -w; history -c; history -r;
}
trap historymerge EXIT
Prompt_COMMAND="history -a; $Prompt_COMMAND"
〜/をGrepしてPrompt_COMMANDを実行し、history -aですでに変更されていないことを確認します。 TIME/DATE形式HISTTIMEFORMAT="%x %r %Z "
も追加しましたが、ロケールに依存するため、上記のブロックには含めませんでした。
erasedupsは、先頭と末尾のスペースを切り捨てません(一部の言語ではchompのように)。これはバグです。また、erasedupsは以前のすべてのエントリを削除しません。
@rozcietrzewiaczのオプション3と終了トラップを組み合わせて使用すると、端末は、終了時に収束する独自の独立した履歴セッションを維持できます。リモートのホームディレクトリを共有する異なるマシン間での複数のセッションでもうまく機能するようです。
export HISTSIZE=5000
export HISTFILESIZE=5000
export HISTCONTROL=ignorespace:erasedups
shopt -s histappend
function historymerge {
history -n; history -w; history -c; history -r;
}
trap historymerge EXIT
Prompt_COMMAND="history -a; $Prompt_COMMAND"
historymerge
関数は、履歴ファイルからセッション外の行をロードし、それらをセッション履歴と結合し、重複除去を使用して新しい履歴ファイルを書き出し(これにより、以前に追加された重複行をつぶす)、履歴を再ロードします。
history -a
プロンプトでは、すべてのコマンドで重複排除を行わずに履歴ファイルを更新するため、履歴が失われる可能性を最小限に抑えます。
最後に、トラップはセッションを閉じるときにhistorymerge
をトリガーし、最新のクリーンな履歴ファイルを探します。最近閉じたセッションのコマンドは、ファイルの最後にバブリングされます(私はそう思います)。
これにより、各ターミナルセッションには、起動から始まる独自の独立した履歴があります。さまざまなタスクのためにさまざまなターミナルを開く傾向があるので(そのため、それぞれでさまざまなコマンドを繰り返したいので)、さらに便利です。また、複数の端末が分散方式で常にordered履歴を再同期しようとしていることを理解するよりも、非常に簡単です(ただし、選択セッションでhistorymerge
関数を使用して意図的にそれを行うことはできますが、それらすべて)。
必要な履歴の長さを保持するのに十分な大きさのサイズ制限が必要であることに注意してくださいplus同時にアクティブなすべてのセッションによって追加される重複排除されていないラインのボリューム。主にHISTIGNORE
を使用してスパム性のある低価値のコマンドを除外しているおかげで、5000で十分です。