常に複数のターミナルを開いています。 2から10のどこでも、さまざまな小技やボブを行います。ここで、別の端末セットを再起動して開いたとします。特定のことを覚えている人もいれば、忘れている人もいます。
次のような履歴が必要です。
ls
を実行している場合は、既に実行中の別の端末に切り替えてから上に押すと、ls
が表示されます)もっとbashをそのように機能させるために私ができることは何ですか?
以下を〜/ .bashrcに追加します
# Avoid duplicates
HISTCONTROL=ignoredups:erasedups
# When the Shell exits, append to the history file instead of overwriting it
shopt -s histappend
# After each command, append to the history file and reread it
Prompt_COMMAND="${Prompt_COMMAND:+$Prompt_COMMAND$'\n'}history -a; history -c; history -r"
だから、これは私の歴史に関連するすべてです.bashrc
事:
export HISTCONTROL=ignoredups:erasedups # no duplicate entries
export HISTSIZE=100000 # big big history
export HISTFILESIZE=100000 # big big history
shopt -s histappend # append to history, don't overwrite it
# Save and reload the history after each command finishes
export Prompt_COMMAND="history -a; history -c; history -r; $Prompt_COMMAND"
Mac OS X 10.5ではbash 3.2.17、10.6ではbash 4.1.7でテスト済み。
これが、Bashセッションの履歴共有における私の試みです。これにより、bashセッション間の履歴共有が有効になり、履歴カウンターが混同されず、_!number
_のような履歴拡張が機能します(いくつかの制約あり)。
Ubuntu 10.04 LTS(Lucid Lynx)でBashバージョン4.1.5を使用する。
_HISTSIZE=9000
HISTFILESIZE=$HISTSIZE
HISTCONTROL=ignorespace:ignoredups
_bash_history_sync() {
builtin history -a #1
HISTFILESIZE=$HISTSIZE #2
builtin history -c #3
builtin history -r #4
}
history() { #5
_bash_history_sync
builtin history "$@"
}
Prompt_COMMAND=_bash_history_sync
_
入力した行を_$HISTFILE
_に追加します(デフォルトは_.bash_history
_です)。これにより、_$HISTFILE
_が1行大きくなります。
特殊変数_$HISTFILESIZE
_をある値に設定すると、最も古いエントリが削除され、Bashは_$HISTFILE
_を_$HISTFILESIZE
_行以下に切り詰めます。
実行中のセッションの履歴をクリアします。これにより、履歴カウンターが_$HISTSIZE
_の量だけ減ります。
_$HISTFILE
_の内容を読み取り、現在実行中のセッション履歴に挿入します。これにより、履歴カウンターが_$HISTFILE
_の行数分増加します。 _$HISTFILE
_の行数は必ずしも_$HISTFILESIZE
_ではないことに注意してください。
history()
関数は、組み込み履歴をオーバーライドして、履歴が表示される前に同期されるようにします。これは、番号による履歴の拡張に必要です(これについては後で詳しく説明します)。
ステップ1では、現在実行中のセッションからのコマンドがグローバル履歴ファイルに書き込まれるようにします。
手順4では、他のセッションからのコマンドが現在のセッション履歴に読み込まれるようにします。
手順4では履歴カウンターが増えるため、何らかの方法でカウンターを減らす必要があります。これはステップ3で行われます。
手順3では、履歴カウンターが_$HISTSIZE
_だけ減らされます。ステップ4で、履歴カウンターは_$HISTFILE
_の行数だけ増加します。手順2では、_$HISTFILE
_の行数が_$HISTSIZE
_であることを確認します(つまり、_$HISTFILESIZE
_は_$HISTSIZE
_と同じでなければなりません)。
番号による履歴拡張を使用する場合、使用する前にalways番号を調べるimmediatelyする必要があります。つまり、番号の検索と使用の間にbashプロンプトが表示されないということです。通常は、EnterキーもCtrl + Cキーもありません。
通常、Bashセッションが複数ある場合、2つのBashプロンプト表示の間で、数値による履歴拡張がその値を保持するという保証はありません。 _Prompt_COMMAND
_が実行されると、他のすべてのBashセッションの履歴が現在のセッションの履歴に統合されるためです。他のbashセッションに新しいコマンドがある場合、現在のセッションの履歴番号は異なります。
この制約は妥当だと思います。とにかく私は任意の履歴番号を思い出せないのでとにかく毎回番号を調べなければなりません。
通常はこのように番号による履歴展開を使います
_$ history | grep something #note number
$ !number
_
以下のBashオプションの使用をお勧めします。
_## reedit a history substitution line if it failed
shopt -s histreedit
## edit a recalled history line before executing
shopt -s histverify
_
何かにパイプされた履歴コマンドを実行すると、そのコマンドは履歴に2回リストされます。例えば:
_$ history | head
$ history | tail
$ history | grep foo
$ history | true
$ history | false
_
すべてが2回履歴にリストされます。なぜか分かりません。
関数_bash_history_sync()
を変更して、毎回実行されないようにします。たとえば、プロンプトで_CTRL+C
_の後に実行しないでください。長いコマンドラインを実行しない場合は、_CTRL+C
_を使用して長いコマンドラインを破棄することがよくあります。場合によっては、Bash完了スクリプトを停止するために_CTRL+C
_を使用する必要があります。
現在のセッションからのコマンドは、常に現在のセッションの履歴の中で最新のものでなければなりません。これには、特定の履歴番号がこのセッションの履歴エントリの値を保持するという副作用もあります。
bash
の使い方を知りません。しかし、これは zsh
の最も人気のある機能の1つです。
個人的にはzsh
よりもbash
を好むので、試すことをお勧めします。
これが私の.zshrc
の歴史を扱っている部分です。
SAVEHIST=10000 # Number of entries
HISTSIZE=10000
HISTFILE=~/.zsh/history # File
setopt APPEND_HISTORY # Don't erase history
setopt EXTENDED_HISTORY # Add additional data to history like timestamp
setopt INC_APPEND_HISTORY # Add immediately
setopt HIST_FIND_NO_DUPS # Don't show duplicates in search
setopt HIST_IGNORE_SPACE # Don't preserve spaces. You may want to turn it off
setopt NO_HIST_BEEP # Don't beep
setopt SHARE_HISTORY # Share history between session/terminals
これを行うには、~/.bashrc
に2行追加する必要があります。
shopt -s histappend
Prompt_COMMAND="history -a;history -c;history -r;$Prompt_COMMAND"
man bash
から:
Histappendシェルオプションが有効になっている場合(以下のシェルの組み込みコマンドの下のshoptの説明を参照)、行が履歴ファイルに追加されます。そうでない場合、履歴ファイルは上書きされます。
Muerrが提案した「history -a」と「history -r」を実行するようにBASHプロンプトを編集できます。
savePS1=$PS1
(あなたが何かを台無しにした場合、それはほぼ保証されています)
PS1=$savePS1`history -a;history -r`
(これらはバックティックであることに注意してください。これらはすべてのプロンプトでhistory -aおよびhistory -rを実行します。テキストを出力しないため、プロンプトは変更されません。
PS1変数を希望どおりに設定したら、〜/ .bashrcファイルに永続的に設定します。
テスト中に元のプロンプトに戻りたい場合は、次のようにします。
PS1=$savePS1
これについては基本的なテストを行って、動作することを確認しましたが、すべてのプロンプトでhistory -a;history -r
を実行した場合の副作用については説明できません。
以下の問題も解決するbashまたはzsh履歴同期ソリューションが必要な場合は、 http://ptspts.blogspot.com/2011/03/how-to-automatically-synchronize-Shell.html)で参照してください。
問題は次のとおりです。2つのシェルウィンドウAとBがあります。シェルウィンドウAでsleep 9999
を実行し、シェルウィンドウBで(スリープが終了するのを待たずに)表示したいbash履歴のsleep 9999
。
ここで他のほとんどのソリューションがこの問題を解決しない理由は、Prompt_COMMAND
またはPS1
を使用して履歴変更を履歴ファイルに書き込んでいるためです。 sleep 9999
コマンドが終了しました。
そうです、最後にこれはまともな解決策を見つけるのに私を悩ませました:
# Write history after each command
_bash_history_append() {
builtin history -a
}
Prompt_COMMAND="_bash_history_append; $Prompt_COMMAND"
これが行うことは、このスレッドで言われたことの一種の融合ですが、すべてのコマンドの後にグローバル履歴をリロードする理由がわかりません。他の端末で何が発生するかを気にすることはほとんどありませんが、常に1つの端末で一連のコマンドを実行します。
make
ls -lh target/*.foo
scp target/artifact.foo vm:~/
(簡略化した例)
そして別の:
pv ~/test.data | nc vm:5000 >> output
less output
mv output output.backup1
コマンドを共有したくない
history -a
を使用して現在のセッションの履歴をhistfileに追加し、他の端末でhistory -r
を使用してhistfileを読み取ることができます。
ここに私が使用する代替案があります。面倒ですが、@ axel_cが言及した、各端末で個別の履歴インスタンスを作成したい場合がある問題(1つはmake、もう1つは監視、vimなど)に対処します。
常に更新する個別の履歴ファイルを保持しています。以下をホットキーにマッピングしました:
history | grep -v history >> ~/master_history.txt
これにより、現在の端末からのすべての履歴がホームディレクトリのmaster_history.txtというファイルに追加されます。
マスター履歴ファイルを検索するための別のホットキーもあります。
cat /home/toby/master_history.txt | grep -i
猫を使う|カーソルを最後に置いて正規表現に入るので、grep。これを行うためのそれほど醜くない方法は、これらのタスクを実行するためにパスにいくつかのスクリプトを追加することですが、ホットキーは私の目的のために機能します。また、定期的に履歴を他のホストから取得し、その履歴をmaster_history.txtファイルに追加します。
使用したトリッキーな正規表現や、7か月前に思いついた奇妙なPerlワンライナーをすばやく検索して見つけることができるのは、いつも素晴らしいことです。
最後の修正を提供できます。環境変数HISTCONTROLで「ignorespace」(または「ignoreboth」)が指定されていないことを確認してください。
しかし、私は複数の同時セッションであなたの痛みを感じます。単にbashではうまく処理されません。
@lesmanaの answer に対する私の拡張を以下に示します。主な違いは、並行ウィンドウは履歴を共有しないことです。これは、他のウィンドウからのコンテキストが現在のウィンドウに読み込まれなくても、ウィンドウで作業を続けることができることを意味します。
「履歴」を明示的に入力すると、OR新しいウィンドウを開くと、以前のすべてのウィンドウから履歴が取得されます。
また、 この戦略 を使用して、自分のマシンでこれまでに入力されたすべてのコマンドをアーカイブします。
# Consistent and forever bash history
HISTSIZE=100000
HISTFILESIZE=$HISTSIZE
HISTCONTROL=ignorespace:ignoredups
_bash_history_sync() {
builtin history -a #1
HISTFILESIZE=$HISTSIZE #2
}
_bash_history_sync_and_reload() {
builtin history -a #1
HISTFILESIZE=$HISTSIZE #2
builtin history -c #3
builtin history -r #4
}
history() { #5
_bash_history_sync_and_reload
builtin history "$@"
}
export HISTTIMEFORMAT="%y/%m/%d %H:%M:%S "
Prompt_COMMAND='history 1 >> ${HOME}/.bash_eternal_history'
Prompt_COMMAND=_bash_history_sync;$Prompt_COMMAND
複数のユーザーが同じサーバーで作業している可能性があるため、私は履歴をfile-per-ttyに入れることを選択しました。各セッションのコマンドを分離すると、監査が容易になります。
# Convert /dev/nnn/X or /dev/nnnX to "nnnX"
HISTSUFFIX=`tty | sed 's/\///g;s/^dev//g'`
# History file is now .bash_history_pts0
HISTFILE=".bash_history_$HISTSUFFIX"
HISTTIMEFORMAT="%y-%m-%d %H:%M:%S "
HISTCONTROL=ignoredups:ignorespace
shopt -s histappend
HISTSIZE=1000
HISTFILESIZE=5000
履歴は次のようになります。
user@Host:~# test 123
user@Host:~# test 5451
user@Host:~# history
1 15-08-11 10:09:58 test 123
2 15-08-11 10:10:00 test 5451
3 15-08-11 10:10:02 history
ファイルは次のようになります。
user@Host:~# ls -la .bash*
-rw------- 1 root root 4275 Aug 11 09:42 .bash_history_pts0
-rw------- 1 root root 75 Aug 11 09:49 .bash_history_pts1
-rw-r--r-- 1 root root 3120 Aug 11 10:09 .bashrc
ここで私は1つの問題を指摘します
export Prompt_COMMAND="${Prompt_COMMAND:+$Prompt_COMMAND$'\n'}history -a; history -c; history -r"
そして
Prompt_COMMAND="$Prompt_COMMAND;history -a; history -n"
Source〜/ .bashrcを実行すると、$ Prompt_COMMANDは次のようになります。
"history -a; history -c; history -r history -a; history -c; history -r"
そして
"history -a; history -n history -a; history -n"
この繰り返しは、「source〜/ .bashrc」を実行するたびに発生します。 'echo $ Prompt_COMMAND'を実行することで、 'source〜/ .bashrc'を実行するたびにPrompt_COMMANDを確認できます。
「history -n history -a」のように、いくつかのコマンドが明らかに壊れていることがわかります。しかし、良いニュースは、他の部分がまだ有効なコマンドシーケンスを形成しているため、それでも機能することです(いくつかのコマンドを繰り返し実行するため、追加のコストがかかるだけです。それほどクリーンではありません)。
個人的に私は次のシンプルなバージョンを使用しています:
shopt -s histappend
Prompt_COMMAND="history -a; history -c; history -r"
これはほとんどの機能を備えていますが、上記のような問題はありません。
本当に何も魔法はありません。 Prompt_COMMANDは、単なるbash環境変数です。その中のコマンドは、bashプロンプト($記号)を取得する前に実行されます。たとえば、Prompt_COMMANDが「echo 123」で、ターミナルで「ls」を実行するとします。この効果は、 "ls; echo 123"を実行するようなものです。
$ Prompt_COMMAND="echo 123"
出力( 'Prompt_COMMAND = "echo 123"; $ Prompt_COMMAND'を実行するのと同じように):
123
以下を実行します。
$ echo 3
出力:
3
123
"history -a"は、メモリ内の履歴コマンドを〜/ .bash_historyに書き込むために使用されます
「history -c」は、メモリ内の履歴コマンドをクリアするために使用されます
「history -r」は、履歴コマンドを〜/ .bash_historyからメモリに読み取るために使用されます
ここで履歴コマンドの説明を参照してください: http://ss64.com/bash/history.html
PS:他のユーザーが指摘したように、exportは不要です。参照: 。bashrcでのエクスポートの使用
セッションまたはタスクごとに履歴ファイルを設定するためのスクリプトを作成しました。
# write existing history to the old file
history -a
# set new historyfile
export HISTFILE="$1"
export HISET=$1
# touch the new file to make sure it exists
touch $HISTFILE
# load new history file
history -r $HISTFILE
すべての履歴コマンドを保存する必要はありませんが、気になるものを保存し、それらを取得してすべてのコマンドを実行する方が簡単です。私のバージョンはまた、すべての履歴ファイルをリストし、それらすべてを検索する機能を提供します。
完全なソース: https://github.com/simotek/scripts-config/blob/master/hiset.sh
これは、個々のセッションの履歴をしない解決策です!
基本的に、各セッションの履歴を個別に保存し、すべてのプロンプトでそれを再作成する必要があります。はい、より多くのリソースを使用しますが、聞こえるほど遅くはありません-100000を超える履歴エントリがある場合にのみ遅延が顕著になります。
コアロジックは次のとおりです。
# on every Prompt, save new history to dedicated file and recreate full history
# by reading all files, always keeping history from current session on top.
update_history () {
history -a ${HISTFILE}.$$
history -c
history -r
for f in `ls ${HISTFILE}.[0-9]* | grep -v "${HISTFILE}.$$\$"`; do
history -r $f
done
history -r "${HISTFILE}.$$"
}
export Prompt_COMMAND='update_history'
# merge session history into main history file on bash exit
merge_session_history () {
cat ${HISTFILE}.$$ >> $HISTFILE
rm ${HISTFILE}.$$
}
trap merge_session_history EXIT
いくつかの保護手段とパフォーマンスの最適化を含む完全なソリューションについては、 この要点 を参照してください。
カスタムファイルに保存した無限の履歴が好きだから。私はこの構成を https://stackoverflow.com/a/19533853/4632019 に基づいて作成します:
export HISTFILESIZE=
export HISTSIZE=
export HISTTIMEFORMAT="[%F %T] "
export HISTFILE=~/.bash_myhistory
Prompt_COMMAND="history -a; history -r; $Prompt_COMMAND"
これはZSHで機能します
##############################################################################
# History Configuration for ZSH
##############################################################################
HISTSIZE=10000 #How many lines of history to keep in memory
HISTFILE=~/.zsh_history #Where to save history to disk
SAVEHIST=10000 #Number of history entries to save to disk
#HISTDUP=erase #Erase duplicates in the history file
setopt appendhistory #Append history to the history file (no overwriting)
setopt sharehistory #Share history across terminals
setopt incappendhistory #Immediately append to the history file, not just when a term is killed
私は長い間、特に新しいプロジェクトで再実行するために実行された場所でコマンドを取得する機能(またはコマンドでディレクトリを検索する機能)を望んでいました。したがって、私は this tool を組み合わせて、グローバルCLI履歴を保存するための以前のソリューションと、percol(C ^ Rにマップされる)と呼ばれるインタラクティブなgreppingツールを組み合わせます。それは私がそれを使い始めた最初のマシンではまだ滑らかで、2年以上前のCLI履歴があります。
矢印キーに関する限り、これはローカルCLI履歴を混乱させませんが、グローバル履歴に非常に簡単にアクセスできます(C ^ R以外のものにマップすることもできます)。
これが私の.bashrcのスニペットであり、必要に応じて簡単な説明を示します。
# The following line ensures that history logs screen commands as well
shopt -s histappend
# This line makes the history file to be rewritten and reread at each bash Prompt
PROMPT_COMMAND="$Prompt_COMMAND;history -a; history -n"
# Have lots of history
HISTSIZE=100000 # remember the last 100000 commands
HISTFILESIZE=100000 # start truncating commands after 100000 lines
HISTCONTROL=ignoreboth # ignoreboth is shorthand for ignorespace and ignoredups
HISTFILESIZEとHISTSIZEは個人的な設定であり、好みに応じて変更できます。