ログインごとに500行に切り捨てられたBASH履歴


22

何らかの理由で、再起動後にシステムにBASH履歴を保持させることができません。ここに私の関連セクションがあります~/.bashrc

shopt -s histappend
PROMPT_COMMAND='history -a; updateWindowTitle'
export HISTCONTROL=ignoredups
export HISTSIZE=9999
export HISTFILESIZE=999999
export HISTFILE="$HOME/.bash_history"

私が知る限り、これらはすべて必要なオプションです(過去にこれらのすべてがなくても、複数の再起動にわたって履歴を保持できることがわかっていました)。ただし、これらのオプションを数回再起動する前に追加したにもかかわらず、再起動後に履歴のほとんどが失われます。空ではありませんが、再起動する前に持っていた9999行はありません。

誰かが文句を言う前に、はい、私はこれらの質問を読みました。上記のリストのいくつかの提案を実装しましたが、残りは役に立たないか関連性がありませんでした。

そこに他の関連コマンドがある可能性がありますので、~/.bashrc ここで私の全体を見ることができます。

だから、私は何が欠けていますか?履歴が保存されないのはなぜですか?別のファイルが関連していると思われる場合はお知らせください。投稿します。私は実行して確認しgrep -i hist \.*、私の中に$HOMEのみ関連することを示している.ファイルが文字列を含むhistか、HISTでした.bashrc

Linux Mint Debian Edition、GNU bash、バージョン4.2.36(1)-release(x86_64-pc-linux-gnu)を実行しており、私のお気に入りのターミナルエミュレーター(関連する場合)はterminatorです。


更新:

コメントでの@mpyの提案に従って、デフォルトではなく~/.bashrcset に変更HISTFILE=~/bash_historyしました。これにより、対話型シェルの~/.bash_history問題が解決されるようです。ログインシェルは同じ動作を表示しますが、履歴は行で切り捨てられます。ただし、関連するファイルには関連する変数は設定されていません。500HIST

$ for f in /etc/profile ~/.profile ~/.bash_profile ~/.bash_login; do \
   echo -ne "$f :"; echo `grep HIST $f`; \
done
/etc/profile :
/home/terdon/.profile :grep: /home/terdon/.profile: No such file or directory
/home/terdon/.bash_profile :grep: /home/terdon/.bash_profile: No such file or directory
/home/terdon/.bash_login :grep: /home/terdon/.bash_login: No such file or directory
$ grep -r HIST /etc/profile.d/  <-- returns nothing

それでは、なぜ設定されるHISTSIZEHISTFILESIZE~/.bashrc、私は明示的に設定しない限り、十分ではない$HISTFILE、デフォルト以外のものに~/.bash_history


あなたは.bash_historyまたはrootの所有者ですか?Do ls -l .bash_history
Adnan Bhatti

1
@MSStpはい、それは私が所有しています。提案に感謝しますが、とにかくアクセス許可の問題になる可能性があるかどうかはわかりません。読み取り/書き込みアクセス権があるかどうかはわかりません。いくつかの履歴が保存されるので、明らかにします。このファイルがユーザーによって所有されていないときにbashに問題を引き起こす設定がある場合、文句を言うか、履歴機能全体が機能しません。
テルドン

historyコマンドを実行すると、表示される出力cat .bash_historyは、行番号以外は実行中の表示と同じになりますか?つまり、historyコマンドはタイムスタンプやその他の情報をリストしますか?私が尋ねる理由は、これらの難解なものを見た場合、それは別のモジュール/機能/プログラムがあり、それがシェルの歴史とそれが何であれ間違っているかバグのあるバージョンを混乱させていることを意味します。
メルバースラン

@Mel_Burslanはい、同じです。唯一の違いは行番号です。
テルドン

2
OK、やや奇妙な提案ですが、それは厄介な問題でもあります;):別のファイルをデフォルトではなくHISTFILEとして試してください~/.bash_history。非常に構成された説明:bashがデフォルトのシェルであると仮定するため、システム起動時に非対話型シェルがXセッションの親になります(Xを使用すると仮定します)。これはhistappendオプションについて何も知りません(.bashrcは、その限り、この親シェルの実行のすべてが正常であるが、終了時(つまりシステム停止が)それが優先されます)インタラクティブシェルによって読み取ら~/.bash_history...あなたの歴史まで(デフォルト)と台無し
MPY

回答:


17

この問題は、実際には、ログインシェルと非ログインシェルの異なる動作に要約されます。履歴を制御する変数を設定していました~/.bahsrc。このファイルは、ログインシェルを起動しても読み込まれません。対話型の非ログインシェル(からman bash)のみが読み込まれます。

bashが対話型ログインシェルまたは--loginオプション付きの非対話型シェルとして呼び出された/etc/profile場合、ファイルが存在する場合、最初にfileからコマンドを読み取って実行します。そのファイルを読み取った後、〜/ .bash_profile、、~/.bash_loginおよび~/.profileをこの順序で探し 、存在し、読み取り可能な最初のコマンドからコマンドを読み取り、実行します。の--noprofileシェルは、この動作を抑制するために開始されたときにオプションを使用することができます。

[。。。]

ログインシェルではないインタラクティブシェルが開始されると、bashは〜/ .bashrcからコマンドを読み取り、実行します(そのファイルが存在する場合)。--norcオプションを使用すると、これを禁止できます。--rcfile fileオプションは、bashに〜/ .bashrcの代わりにfileからコマンドを強制的に読み取り、実行させます。

したがって、ログインするか、ttyにドロップするか、sshを使用するたび.historyに、適切なサイズに設定していなかったため、ファイルが切り捨てられてい~/.profileました。私は最終的にこれを実現し、変数が~/.profile 属する場所に変数を設定するだけでなく、~/.bashrc

だから、私~/.historyが切り捨てられた理由は、対話型の非ログインシェルによって読み取られたファイルにHISTORY変数のみを設定していたため、異なるタイプのシェルを実行するたびに変数が無視され、ファイルがカットされるためでしたそれに応じて。


非常に良い点、共有してくれてありがとう!ただし、私は同意しません。このファイルは、ログインシェルを起動したときに読み込まれません。インタラクティブシェルによってのみ読み込まれます。ログインシェルもインタラクティブにできるためです。そうしないと、履歴メカニズム全体が意味をなさないでしょう。私見.bashrcは(非対話型またはログインシェル)によって読み取られません。
mpy

@mpy確かに、申し訳ありませんが、対話型の非ログインシェルを意味しました。回答を編集しました。
テルドン

1
@terdon、一般的なイディオムは、対話型シェルオプションが〜/ .profileまたは〜/ .bash_profileに含まれないことです。対話型シェルオプションは〜/ .bashrcに配置されます。2つの場所で設定を維持する必要がないように、次のコマンドを〜/ .bash_profile export BASH_ENV=~/.bashrc ; if [ -f ~/.bashrc ]; then . ~/.bashrc; fiの先頭に配置することができます。[ -z "$PS1" ] && return...もちろん、それは単なるイディオムです。
ノアスプリアー14年

1
@NoahSpurrier BASH_ENVは関連性がなく、非対話型シェルにのみ影響します。「イディオム」に関しては、Debianが始めたものであり、個人的には同意しません。私はよくxset.bashrcにグラフィカルオプション(など)を持っていますが、ログインシェルをttyからまたはを通じて実行するときにそれらをアクティブにしたくないのですssh。.profileと.bashrcを別々にしたい。多くの(すべてではありませんが)ログインマネージャーは、ログイン時に.profileをソースするため、グローバル変数は、ターミナルを開くたびに読み込まれるのではなく、一度だけ読み込まれるように設定するのが最適です。
テルドン14年

1
@WilsonFはい。ファイルは順番に読み込まれ、個人ファイル(~/.profileまたは~/.bashrc)は最後に読み込まれます。それらで設定されたものはすべて、グローバル設定よりも優先されます。まったくその通りです/etc/bash.bashrc。これらの変数をに設定するべきではありません。代わりに~/.profile(または~/.bash_profile)を使用してください。
テルドン

11

私の提案はHISTFILE、デフォルトではなく別のファイルを使用することです~/.bash_history

分析的な説明はありませんが、この提案に至った理由の概要を説明します:bashデフォルト(ログイン)シェルとして使用し、X(両方とも非常に可能性が高い)を使用するbash場合、(グラフィカルな) ログインする:

systemd
 ...
  |-login
  |   `-bash      <<====
  |       `-slim
  |           |-X -nolisten tcp vt07 -auth /var/run/slim.auth
  |           |  `-{X}
  |           `-fluxbox
  |               `-xterm -bg black -fg white
  |                   `-bash
 ...

このインスタンスはログインシェルだと思うので、あなた~/.bashrcを読まないので、histappendオプションについて何も知りません:

man bash(1)ログインシェルではない対話型シェルが起動されると、bashは/etc/bash.bashrcおよび〜/ .bashrcからコマンドを読み取り、実行します(これらのファイルが存在する場合)。(...)

この「親シェル」が実行されている限り、すべては問題ありませんが、終了(つまりシステム停止)するとオーバーライドし~/.bash_history(デフォルト値であるため)、履歴を台無しにするか、システム起動時にクリップします(再びデフォルト)500行。(またはおそらく両方...)

また、履歴設定をに含めるだけでは十分では~/.bashrcないことも印象的です。これは、それほど一般的な設定ではないためです。私にはその説明がありません。


「ログインシェルが引き続き同じ動作をする」という問題については、次の場所にも履歴設定を含めることができます~/.bash_profile

man bash(1):bashが対話型ログインシェルとして、または--loginオプションを使用した非対話型シェルとして呼び出されると、ファイル/ etc / profileが存在する場合、最初にファイル/ etc / profileからコマンドを読み取って実行します。そのファイルを読み込んだ後、〜/ .bash_profileを探します(...)

残念ながらbash、私はzsh男なので、自分の設定から詳細を含むより正当な説明を投稿することはできません...


2
明示的に履歴オプションを設定すると~/.bash_profile、問題が解決しました。現在~/.bash_history、履歴ファイルとして使用していますが~/.bashrc、質問に表示されているすべての行をに追加しただけ~/.bash_profileです。誰がインタラクティブなシェルを台無しにしていたのかはまだわかりませんが、今はうまくいくようです、ありがとう!
テルドン

1
受け入れられず申し訳ありませんが、何が起こっているのかを説明する回答を投稿するのを忘れていました。しばらく前に@Gillesの助けを借りてそれを理解し、ついに答えを投稿することになりました。(非常に良い)回避策を提供する代わりに実際に問題を説明し、将来の訪問者を助けることができるので、私は私のものを受け入れたかった。
テルドン

2

すべての設定はマニュアルページに従って順番に並んでおり、履歴ファイルはサイズ(バイト)によって制限されていないため、考えられる唯一の説明です。シェルの死に関係しています。

オンラインリファレンスによると、シェルがSIGHUPを受け取ったときにのみ、正常な終了(保存された履歴)が発生します。リブート時にシステムがシグナルを伝搬する方法を実際に説明することはできませんが、シェルがSIGKILLまたはSIGPWRで終了するのではないかと考えています。

WMが非同期に実行(待機)され、ターミナルエミュレータがWMから生成され、bashがSIGHUP以外の終了強制信号を受け取ることが原因である可能性があります。また、初期のグレースフルSIGHUPがX-> WM-> xtermを介してシェルに到達する前に、OSがすべてのプロセスに「最終キル」をすばやく送信することも考えられます。 OSがダウンする準備ができるには時間がかかります。

私はこのようなもので深海にいますが、それらの線に沿った何かが不規則な行動を引き起こすと思います。私は以前この問題を抱えていましたが、最も堅実な解決策はexit、履歴を保持したいbashです。

history -aはあなたの質問に気づきました、そして、なぜそれが歴史を保存するのに十分ではないかについて考えることができません。

あなたがbashを本当に殺すものを理解し、信号の発生場所を見つけて問題を修正することで問題を解決するか、最後の信号がわかっているときに履歴をフラッシュすることができます(ディスクがまだオンラインであると仮定して) ):

trap "echo got 1  >/tmp/sig1;  exit" SIGHUP
trap "echo got 2  >/tmp/sig2;  exit" SIGINT
trap "echo got 15 >/tmp/sig15; exit" SIGTERM
 .. and so on...

含まれているスクリーンショットは、2番目と3番目の段落で私が話していることを示しています。そこにあるシーケンスは、左から私がシェルで、右から左のシェルを殺し、歴史を猫にします。

男バッシュ

起動時、(...)HISTFILEの値で指定されたファイルは、必要に応じて、HISTFILESIZEの値で指定された行数(+デフォルト500)を超えないように切り捨てられます。

histappendシェルオプションが有効になっている場合(ここでは+デフォルト)、行は履歴ファイルに追加されます。それ以外の場合、履歴ファイルは上書きされます。

オンライン参照

3.7.6シグナル

Bashは、トラップがない場合にインタラクティブである場合、SIGTERMを無視し(「kill 0」はインタラクティブシェルを強制終了しません)、SIGINTがキャッチされて処理されます(ビルトイン待機が割り込み可能になるように)。BashはSIGINTを受け取ると、実行中のループから抜け出します。すべての場合において、BashはSIGQUITを無視します。ジョブ制御が有効な場合(ジョブ制御を参照)、BashはSIGTTIN、SIGTTOU、およびSIGTSTPを無視します。

Bashによって開始された非組み込みコマンドには、シェルがその親から継承した値に設定されたシグナルハンドラがあります。ジョブ制御が有効でない場合、非同期コマンドはこれらの継承されたハンドラーに加えてSIGINTおよびSIGQUITを無視します。コマンド置換の結果として実行されるコマンドは、キーボードで生成されたジョブ制御シグナルSIGTTIN、SIGTTOU、およびSIGTSTPを無視します。

シェルは、SIGHUPを受信するとデフォルトで終了します。終了する前に、対話型シェルは、実行中または停止中のすべてのジョブにSIGHUPを再送信します。停止したジョブにはSIGCONTが送信され、SIGHUPを確実に受信します。シェルがSIGHUPシグナルを特定のジョブに送信しないようにするには、disownビルトイン(ジョブ制御ビルトインを参照)でジョブテーブルから削除するか、disown -hを使用してSIGHUPを受信しないようにマークする必要があります。

huponexitシェルオプションがshoptで設定されている場合(The Shopt Builtinを参照)、インタラクティブログインシェルが終了すると、BashはすべてのジョブにSIGHUPを送信します。

Bashがコマンドの完了を待機しており、トラップが設定されたシグナルを受信した場合、トラップはコマンドが完了するまで実行されません。Bashが待機ビルトインを介して非同期コマンドを待機している場合、トラップが設定された信号を受信すると、待機ビルトインは直ちに終了ステータス128を超えて戻り、トラップが実行されます。

デモ用スクリーンショット

信号


そのスクリーンショットであなたが何をしているのか本当に分かりません。/tmp/psoあなたが殺しているのは何ですか?さまざまなキルシグナルについてあなたの意見があります(あなたが言うように、私history -aはそれが対処するべきものだと思いました)。しばらくテストしてから報告します。
テルドン

$猫TMP / PS * \ n個のps -o pidを= |ヘッド-n1>〜は/ tmp / PSO \ nは17201 \ nは
ЯрославРахматуллин

0

/ etc / profileおよび/etc/profile.d/*を確認します

たぶん、そこに歴史の設定を台無しにする何かがある。


ありがとう、しかしgrep -r HIST /etc/profile.d/何も返さず、私はすでにチェックしました/etc/profile
テルドン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.