Bashの履歴:「ignoredups」および「erasedups」設定は、セッション全体で共通の履歴と競合します


84

まず第一に、これはSE上の既存のスレッドの複製ではありません。私はこれらの2つのスレッド(1st2nd)をより良いbash履歴で読みましたが、答えはどれも機能しません--ところでFedora 15を使用しています。

.bashrcユーザーディレクトリ(/ home / aahan /)のファイルに次を追加しましたが、機能しません。誰にも手がかりがありますか?

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の履歴(優先度)で欲しいものです:

  • 重複を保存せず、既存のものを消去します
  • 開いているすべての端末とすぐに履歴を共有する
  • 常に履歴を追加し、上書きしない
  • 複数行のコマンドを単一のコマンドとして保存します(デフォルトではオフになっています)
  • デフォルトの履歴サイズと履歴ファイルサイズはどのくらいですか?

バンプ!誰でも?何も動作しません。これはFedora 15(Gnome 3でWindowsホスト仮想マシンで実行中)の問題でしょうか?
its_me

ここに投稿を「バンプ」しないでください。回答が得られない場合は、より明確に尋ねる必要があります。コンテキストの手がかりなどを適切に含める必要があります。投稿に注意を払う必要がある場合は、より多くの人にもっと注意を払ってもらうための報奨金を発行できます。
カレブ

1
bashを使用していてもよろしいですか?(echo $SHELL)。開いているシェルから手動で設定を実行した場合、設定は機能しますか?明らかに、他の多くの設定が正しく機能するため、設定は正しいので、あなたはそれらを間違って実装しているだけです。また、Fedora15 / Gnome3 /仮想マシンであることは、の実際の機能とはほとんど関係ありませんbash
カレブ

@Caleb、まず投稿をぶつけてすみません。また、私は非常に明確になるように最善を尽くしました。いいえ、シェルで発行していません。コピーして.bashrcファイルに貼り付けました。それは間違っていますか?実際のシェルコマンドを使用して、この投稿に「回答」を追加できますか?(私のnoob-ityに耐えてください。)
its_me

1
スクリプトで記述したもの、または.bashrc実際のシェルコマンドです。スクリプトは単なるシェルコマンドのシリーズです。また、最近exportビットを削除した編集は悪い考えでしたので、それを保持する必要があります。
カレブ

回答:


119

これは実際に非常に興味深い振る舞いであり、最初はこの質問を大きく過小評価していたことを認めます。しかし、最初の事実:

1.動作するもの

機能はいくつかの方法で実現できますが、それぞれが少し異なります。いずれの場合も、履歴を別の端末に「転送」する(更新する)Enterには、履歴を取得する端末を押す必要があります。

  • オプション1:

    shopt -s histappend
    HISTCONTROL=ignoredups
    PROMPT_COMMAND="history -a; history -n; $PROMPT_COMMAND"
    

    これには2つの欠点があります。

    1. ログイン(端末を開く)時に、履歴ファイルから最後のコマンドが2回、現在の端末の履歴バッファに読み込まれます。
    2. 異なる端末のバッファは、履歴ファイルと同期しません。
  • オプション2:

    HISTCONTROL=ignoredups
    PROMPT_COMMAND="history -a; history -c; history -r; $PROMPT_COMMAND"
    

    (はい、必要はshopt -s histappendありません、はい、それ history -cの中間にある必要がありますPROMPT_COMMAND)このバージョンには、2つの重要な欠点もあります。

    1. 履歴ファイルを初期化する必要があります。空でない行を少なくとも1つ含める必要があります(何でもかまいません)。
    2. historyコマンドが誤った出力を与えることができます-以下を参照してください。

[編集] 「そして勝者は...」

  • オプション3:

    HISTCONTROL=ignoredups:erasedups
    shopt -s histappend
    PROMPT_COMMAND="history -n; history -w; history -c; history -r; $PROMPT_COMMAND"
    

    これは得られる限りです。両方の共通履歴を同時に機能させる唯一のオプションerasedupsです。 これがおそらくすべての問題に対する最終的な解決策です、アーハン。


2. オプション2が機能しないように見えるのはなぜですか(または、期待どおりに機能しないものは何ですか)。

前述したように、上記のソリューションはそれぞれ異なる方法で機能します。しかし、設定がどのように機能するかについて最も誤解を招く解釈は、historycommand の出力を分析することから来ています。多くの場合、コマンドは誤った出力をする可能性があります。どうして?これは、!に含まれる他のコマンドのシーケンスのに実行されるhistoryPROMPT_COMMANDためです。ただし、2番目または3番目のオプションを使用する場合、.bash_historyコンテンツの変更を監視し(watch -n1 "tail -n20 .bash_history"たとえば、使用して)、実際の履歴を確認できます。

3.なぜオプション3がそんなに複雑なのですか?

それはすべて、そのerasedups働き方にあります。bashのマニュアルにあるように、 「(...)erasedupsは、現在の行に一致するすべての以前の行を、その行が保存される前に履歴リストから削除します」。したがって、これはOPが本当に望んでいたことです(以前に思ったように、重複が連続して現れないようにするだけではありません)。以下に、各history -.コマンドが必要な場合とできない場合を示しPROMPT_COMMANDます。

  • history -n 持って前にそこにhistory -wからの読み取りに.bash_history他の端末から保存されたコマンド、

  • history -w 履歴をファイルに保存して重複を消去するためにそこになければなりません。

  • history -a 代わりにそこに配置history -wしないでください。重複の消去をトリガーしないためです。

  • history -cまた、されて必要なことは、各コマンドの後、履歴バッファを中傷防ぐので、

  • そして最後に、history -rされる必要なので、最終的には、端末セッション間で共有の歴史を作り、ファイルから履歴バッファを復元します。


2
「ただし、設定がどのように機能するかについて最も誤解を招く解釈は、履歴コマンドの出力の分析に由来します。」これがOPの問題の中核だと思います。優れた控除。
-jasonwryan

2
私はついにあなたの要点を見ました。「重複」とは、私以外の何かを意味します。私は同じコマンドのシーケンスにのみ焦点を当てました。私の答えを更新しました-「オプション3」を参照してください。また、あなたの場合、履歴がどのように機能するかをテストするwatch "tail -n 20 .bash_history"には、の代わりに実際に使用する必要がありますtail -f .bash_history
rozcietrzewiacz

2
オプション3は、私の100,000行の履歴をすべて消去しただけです:((bash 3.2.25(1)-release)
フェリペアルバレス14年

2
history -cまた、各コマンドの後に履歴バッファーを破棄しないようにするために必要です。なぜこの破棄が発生するのですか?
ピョートルドブロゴスト

2
ソリューション3は実際には機能しません。これは非常にバグが多く、ユーザーが異なる端末で入力する順序に依存します。特に端末間で切り替えを行う場合は、多くの場合、コマンドが失われます。ソース:試してみました。
6cef

8

プロンプトコマンドで、-cスイッチを使用しています。からman bash

-c   すべてのエントリを削除して履歴リストをクリアします

開いているすべての端末と履歴を共有するには、次を使用できます-n

-n   履歴ファイルからまだ読み込まれていない履歴行を現在の履歴リストに読み込みます。これらは、現在のbashセッションの開始以降に履歴ファイルに追加される行です。

デフォルトのサイズもマニュアルに記載されています。

HISTSIZEコマンド履歴に記憶するコマンドの数(下記の履歴を参照)。デフォルト値は500です。

複数行のコマンドを保存するには:

cmdhistのシェルオプションが有効になっている場合、構文上の正確さを維持するために必要なセミコロンを追加し、同じ履歴エントリに複数行のコマンドの各ラインを保存しようとするシェルの原因となります。lithistのシェルオプションが埋め込まれた改行の代わりにセミコロンでコマンドを保存するには、シェルの原因となります。

また、HIST *コマンドの前に、export環境変数でHISTCONTROL=ignoredups:erasedupsはなくbash専用の変数を追加することはできません。十分です。


だから、これexport PROMPT_COMMAND="history -a; history -n; history -r; $PROMPT_COMMAND"は正しいですか?また、履歴ファイルに複数行のコマンドを単一のコマンドとして保存する方法を知っていますか(デフォルトではオフになっています)?
its_me

1
はい。上記で引用したmanページに従って、shopt -s cmdhist複数行を保存します。
-jasonwryan

さて、私はすべてを試しました。HISTCONTROL=ignoredups:erasedups動作していないようです。また、.bashrc(カスタム関数の中で)それをファイルに含めてみました。何が間違っている可能性がありますか?仮想マシンでFedora 15を使用しています-Windows 7ホスト。
-its_me

何ものような、他のスタートアップファイルに存在しないことを確認し/etc/bashrc.bash_profileそれをオーバーライドしていることなど。
-jasonwryan

.bash_profileファイルに関する問題は見当たりません。内容については/etc/bashrc、ここでそれを置くI、見てください- pastebin.com/Uae6sE6s
its_me

8

これが私が思いついたものであり、これまでのところ満足しています…

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は引数を持たないすべてのコマンドを無視します。これは一部の人にとって望ましくない場合があり、省略できます。

1

代わりにこれを使用してください:

HISTCONTROL=ignoreboth

0

次のことを忘れているため、機能しません。

 -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

ここでは、DUPの消去をオンにし、履歴をカスタムファイルに切り替え、履歴をクリアします。すべてのコマンドが完了すると、空の履歴ファイルと現在の履歴に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は歴史に他のコマンドが登場することを期待しています


0

erasedupsは、先頭および末尾のスペースをトリミングしません(一部の言語のchompのように)。これはバグです。また、erasedupsは以前のすべてのエントリを削除しません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.