GNU/Linux >> Linux の 問題 >  >> Linux

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

問題は、実際には、ログイン シェルと非ログイン シェルの異なる動作に要約されます。 ~/.bahsrc で履歴を制御する変数を設定しました .このファイルは、ログイン シェルの起動時には読み取られず、対話型の非ログイン シェルによってのみ読み取られます (man bash 以降)。 ):

<ブロック引用>

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

[。 . . ]

ログイン シェルではないインタラクティブ シェルが開始されると、bash は ~/.bashrc ファイルが存在する場合はそこからコマンドを読み取り、実行します。これは、 --norc オプションを使用することで抑制できます。 --rcfile file オプションは、bash が ~/.bashrc ではなく、ファイルからコマンドを読み取って実行するように強制します。

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

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


私の提案は、別のファイルを HISTFILE として使用することです 、デフォルトの ~/.bash_history ではありません .

分析的な説明はありませんが、この提案に至った理由を概説してみます:If you use 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 からコマンドを読み取り、実行します (そのファイルが存在する場合)。そのファイルを読み取った後、~/.bash_profile を探します (...)

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


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

オンライン リファレンスによると、シェルが SIGHUP を受信した場合にのみ、正常な終了 (保存された履歴) が発生します。再起動時にシステムがどのようにシグナルを伝達するかについては説明できませんが、シェルが SIGKILL または SIGPWR で終了するのではないかと思います。

WM が非同期 (待機) で実行され、bash が存在する WM から生成されたターミナル エミュレーターが 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 をキャッチして処理します (wait ビルトインが中断可能になるようにするため)。 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 が wait ビルトインを介して非同期コマンドを待機している場合、トラップが設定されているシグナルを受信すると、wait ビルトインは 128 より大きい終了ステータスですぐに戻り、その直後にトラップが実行されます。

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


Linux
  1. Bash履歴コマンドの使用方法

  2. Bash履歴で実行する各コマンドの日付と時刻を設定する

  3. バッシュ履歴の自動クリーンアップ?

  1. Bashシェルのカスタマイズ

  2. LinuxでのBash履歴の解析

  3. タイプアヘッドをBash履歴検索(ctrl-r)に適用するにはどうすればよいですか?

  1. 壊れた歴史?

  2. シェル変数の関数?

  3. Linuxのログイン履歴を確認する方法