it-swarm-tr.com

Birden fazla terminal penceresinde bash geçmişini koru

Sürekli olarak birden fazla terminalim açık. İki ile on arasında herhangi bir yerde, çeşitli bitler ve bobs yapıyor. Şimdi yeniden başlatıp başka bir terminal seti açtığımı varsayalım. Bazıları bazı şeyleri hatırlar, bazıları unutur.

Ben bir tarih istiyorum:

  • Her terminalden her şeyi hatırlar
  • Her terminalden anında erişilebilir (örneğin, birinde _ ls varsa, zaten çalışan başka bir terminale geçin ve yukarı basın, ls görünür)
  • Komutun önünde boşluklar varsa komutu unutmaz.

Bash'in bu şekilde çalışmasını sağlamak için yapabileceğim bir şey var mı?

565
Oli

Aşağıdakileri ~/.bashrc dizinine ekleyin

# 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"
355
Pablo R.

Yani, hepsi benim tarihimle ilgili .bashrc şey:

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'te bash 3.2.17, 10.6'da bash 4.1.7 ile test edilmiştir.

257
kch

İşte Bash oturum geçmişi paylaşma girişimim. Bu, bash oturumları arasında geçmiş sayacının, tarih sayacının karışmayacağı ve _!number_ gibi geçmiş genişlemesinin çalışacağı şekilde (bazı kısıtlamalarla) tarih paylaşımını mümkün kılacaktır.

Ubuntu 10.04 LTS (Lucid Lynx) altında Bash sürüm 4.1.5'i kullanma.

_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 "[email protected]"
}

Prompt_COMMAND=_bash_history_sync
_

Açıklama:

  1. Yeni girilen satırı _$HISTFILE_ öğesine ekleyin (varsayılan _.bash_history_). Bu _$HISTFILE_ 'in bir satır büyümesine neden olur.

  2. _$HISTFILESIZE_ özel değişkeninin bir değere ayarlanması, Bash'in _$HISTFILE_ satırını en eski girişleri kaldırarak _$HISTFILESIZE_ satırından daha uzun olmamasına neden olur.

  3. Çalışan oturumun geçmişini temizleyin. Bu, tarih sayacını _$HISTSIZE_ kadar azaltacaktır.

  4. _$HISTFILE_ içeriğini okuyun ve geçerli çalışan oturum geçmişine ekleyin. bu, tarih sayacını _$HISTFILE_ içindeki satır miktarına yükseltir. _$HISTFILE_ satır sayısının mutlaka _$HISTFILESIZE_ olmadığını unutmayın.

  5. history() işlevi, geçmişin görüntülenmeden önce senkronize edildiğinden emin olmak için yerleşik geçmişi geçersiz kılar. Tarihin sayıya göre genişletilmesi için bu gereklidir (bunun hakkında daha sonra daha fazla bilgi).

Daha fazla açıklama:

  • Adım 1, geçerli çalışan oturumdaki komutun genel geçmiş dosyasına yazılmasını sağlar.

  • Adım 4, diğer oturumlardan gelen komutların geçerli oturum geçmişine okunmasını sağlar.

  • 4. adım tarih sayacını yükselteceğinden sayacı bir şekilde azaltmamız gerekir. Bu, 3. adımda yapılır.

  • 3. adımda tarih sayacı _$HISTSIZE_ ile azaltılır. 4. adımda tarih sayacı, _$HISTFILE_ içindeki satır sayısı ile artırılır. 2. adımda, _$HISTFILE_ satır sayısının tam olarak _$HISTSIZE_ olduğundan emin oluruz (bu, _$HISTFILESIZE_ 'nin _$HISTSIZE_ ile aynı olması gerektiği anlamına gelir.

Tarih genişlemesinin kısıtlamaları hakkında:

Numaraya göre geçmiş genişlemesini kullanırken, kullanmadan önce her zaman numaraya bakmalısınız hemen. Bu, numarayı arama ve kullanma arasında bash istemi gösterilmemesi anlamına gelir. Bu genellikle enter ve ctrl + c anlamına gelir.

Genel olarak, birden fazla Bash oturumu yaptıktan sonra, numaraya göre bir geçmiş genişletmesinin iki Bash İstemi ekranı arasındaki değerini koruyacağının garantisi yoktur. Çünkü _Prompt_COMMAND_ yürütüldüğünde, diğer tüm Bash oturumlarının geçmişi mevcut oturumun geçmişine entegre edilir. Başka bir bash oturumunun yeni bir komutu varsa, geçerli oturumun geçmiş numaraları farklı olacaktır.

Bu kısıtlamayı makul buluyorum. Her seferinde numaraya bakmalıyım çünkü keyfi geçmiş sayılarını hatırlayamıyorum.

Genellikle tarih genişlemesini şu şekilde kullanırım

_$ history | grep something #note number
$ !number
_

Aşağıdaki Bash seçeneklerini kullanmanızı tavsiye ederim.

_## reedit a history substitution line if it failed
shopt -s histreedit
## edit a recalled history line before executing
shopt -s histverify
_

Garip böcekler:

Herhangi bir şeye bağlı geçmiş komutunu çalıştırmak, bu komutun geçmişte iki kez listelenmesine neden olur. Örneğin:

_$ history | head
$ history | tail
$ history | grep foo
$ history | true
$ history | false
_

Hepsi tarihte iki kez listelenecek. Neden olduğuna dair hiçbir fikrim yok.

İyileştirmeler için fikirler:

  • _bash_history_sync() işlevini, her seferinde yürütülmeyecek şekilde değiştirin. Örneğin, İstemde bir _CTRL+C_ sonrasında çalıştırılmamalıdır. Bu satırı yürütmek istemediğime karar verdiğimde uzun bir komut satırını atmak için genellikle _CTRL+C_ kullanıyorum. Bazen bir Bash tamamlama komut dosyasını durdurmak için _CTRL+C_ kullanmalıyım.

  • Geçerli oturumdaki komutlar, geçerli oturumun geçmişindeki her zaman en son olmalıdır. Bu, belirli bir geçmiş numarasının bu oturumdaki geçmiş girişleri için değerini tutmasının da yan etkisi olacaktır.

123
lesmana

bash kullanarak hiçbir şekilde farkında değilim. Ancak zsh 'ın en popüler özelliklerinden biridir.
Şahsen zsh yerine bash tercih ederim, bu yüzden denemenizi tavsiye ederim.

İşte benim .zshrc tarihle ilgileniyor:

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
45
Maciej Piechotka

Bunu yapmak için ~/.bashrc:

shopt -s histappend
Prompt_COMMAND="history -a;history -c;history -r;$Prompt_COMMAND"

man bash:

Histappend Shell seçeneği etkinse (aşağıdaki Shell BUILTIN COMMANDS altındaki shopt açıklamasına bakın), satırlar geçmiş dosyasına eklenir, aksi takdirde geçmiş dosyası üzerine yazılır.

17
Chris Down

Muerr tarafından önerilen "history -a" ve "history -r" yi çalıştırmak için BASH İsteminizi düzenleyebilirsiniz:

savePS1=$PS1

(bir şeyi karıştırmanız durumunda, neredeyse garantilidir)

PS1=$savePS1`history -a;history -r`

(bunların geri keneler olduğunu unutmayın; her İstemde -a ve geçmiş -r geçmişini çalıştırırlar. Herhangi bir metin vermedikleri için İsteminiz değişmez.

PS1 değişkeninizi istediğiniz gibi ayarladıktan sonra, ~/.bashrc dosyanızda kalıcı olarak ayarlayın.

Test sırasında orijinal Bilgi İsteminize geri dönmek istiyorsanız, şunları yapın:

PS1=$savePS1

Bu tür bir çalışma sağlamak için temel test yaptım, ancak her İstemi üzerinde history -a;history -r Çalıştırmak herhangi bir yan etkisi konuşamıyor.

11
Schof

Aşağıdaki sorunu da çözen bir bash veya zsh geçmiş senkronizasyon çözümüne ihtiyacınız varsa, http://ptspts.blogspot.com/2011/03/how-to-automatically-synchronize-Shell.html adresinde görün.

Sorun şudur: İki A ve B Kabuk pencerem var. A Kabuk penceresinde sleep 9999, ve (uykunun bitmesini beklemeden) Kabuk B penceresinde, sleep 9999 bash tarihinde.

Buradaki diğer çözümlerin çoğunun bu sorunu çözmemesinin nedeni, geçmiş değişikliklerini Prompt_COMMAND veya PS1, her ikisi de çok geç yürütülüyor, ancak sleep 9999 komutu bitti.

10
pts

Doğru, Sonunda bu iyi bir çözüm bulmam için beni rahatsız etti:

# Write history after each command
_bash_history_append() {
    builtin history -a
}
Prompt_COMMAND="_bash_history_append; $Prompt_COMMAND"

Bunun yaptığı şey, bu komutta söylenenlerin bir araya getirilmesidir, ancak her komuttan sonra küresel tarihi neden yeniden yükleyeceğinizi anlamıyorum. Diğer terminallerde ne olduğunu çok nadiren önemsiyorum, ama her zaman bir dizi komut çalıştırıyorum, örneğin bir terminalde:

make
ls -lh target/*.foo
scp target/artifact.foo vm:~/

(Basitleştirilmiş örnek)

Ve bir başkasında:

pv ~/test.data | nc vm:5000 >> output
less output
mv output output.backup1

Komutun paylaşılmasını istemem

9
Yarek T

Kullanabilirsiniz history -a geçerli oturumun geçmişini hist dosyasına eklemek için history -r diğer terminallerde histfile okumak için.

9
jtimberman

İşte benim kullandığım bir alternatif. Bu hantal ama @axel_c'nin bazen her terminalde ayrı bir geçmiş örneğine sahip olmak isteyebileceğiniz (biri yapmak için, biri izlemek için, biri vim için vb.) Bahsettiği sorunu ele alıyor.

Sürekli güncellediğim ayrı bir ekli geçmiş dosyası tutuyorum. Bir kısayol tuşu eşlenmiş aşağıdaki var:

history | grep -v history >> ~/master_history.txt

Bu, geçerli terminaldeki tüm geçmişi ana dizininizdeki master_history.txt adlı bir dosyaya ekler.

Ayrıca ana geçmiş dosyasını aramak için ayrı bir kısayol tuşu var:

cat /home/toby/master_history.txt | grep -i

Kedi kullanıyorum | grep çünkü regex girmek için imleç sonunda bırakır. Bunu yapmanın daha az çirkin bir yolu, bu görevleri gerçekleştirmek için yolunuza birkaç komut dosyası eklemek olacaktır, ancak kısayol tuşları benim amacım için çalışır. Ayrıca periyodik olarak üzerinde çalıştığım diğer ana bilgisayarlardan geçmişi aşağı çeker ve bu geçmişi master_history.txt dosyasına eklerim.

Kullandığınız zor regex'i veya 7 ay önce ortaya çıkardığınız garip Perl tek astarını hızlı bir şekilde aramak ve bulmak her zaman güzeldir.

8
Toby

Sonuncusu için bir düzeltme önerebilirim: HISTCONTROL env değişkeninin "ignorespace" (veya "ignoreboth") belirtmediğinden emin olun.

Ama birden fazla eşzamanlı seansla acını hissediyorum. Sadece bash iyi ele alınmaz.

7
jmanning2k

İşte @ lesmana'nın yanıt . Temel fark, eşzamanlı pencerelerin geçmişi paylaşmamasıdır. Bu, mevcut pencerelerinize başka pencerelerden içerik yüklenmeden pencerelerinizde çalışmaya devam edebileceğiniz anlamına gelir.

Açıkça 'history' yazarsanız, OR yeni bir pencere açarsanız, geçmişi önceki tüm pencerelerden alırsınız.

Ayrıca, bu strateji , makineme yazılan her komutu arşivlemek için kullanıyorum.

# 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 "[email protected]"
}

export HISTTIMEFORMAT="%y/%m/%d %H:%M:%S   "
Prompt_COMMAND='history 1 >> ${HOME}/.bash_eternal_history'
Prompt_COMMAND=_bash_history_sync;$Prompt_COMMAND
7
rouble

Birden çok kişi aynı sunucu üzerinde çalışabileceğinden geçmişi her bir dosyaya koymayı seçtim - her oturumun komutlarını ayırmak denetlemeyi kolaylaştırır.

# 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

Tarih artık şuna benziyor:

[email protected]:~# test 123
[email protected]:~# test 5451
[email protected]:~# 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

Dosyalar şöyle görünürken:

[email protected]:~# 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
6
Litch

Burada bir problemi göstereceğim

export Prompt_COMMAND="${Prompt_COMMAND:+$Prompt_COMMAND$'\n'}history -a; history -c; history -r"

ve

Prompt_COMMAND="$Prompt_COMMAND;history -a; history -n"

~/.Bashrc kaynağını çalıştırırsanız, $ Prompt_COMMAND şöyle olur

"history -a; history -c; history -r history -a; history -c; history -r"

ve

"history -a; history -n history -a; history -n"

Bu tekrarlama, 'source ~/.bashrc' komutunu her çalıştırışınızda gerçekleşir. 'Source ~/.bashrc' komutunu her çalıştırdıktan sonra 'echo $ Prompt_COMMAND' komutunu çalıştırarak Prompt_COMMAND öğesini kontrol edebilirsiniz.

Görünüşe göre bazı komutlar bozuldu: "history -n history -a". Ancak iyi haber şu ki, hala çalışıyor, çünkü diğer bölümler hala geçerli bir komut dizisi oluşturuyor (Sadece bazı komutların tekrar tekrar yürütülmesi nedeniyle ekstra maliyete neden oluyor. Ve çok temiz değil.)

Şahsen aşağıdaki basit sürümü kullanıyorum:

shopt -s histappend
Prompt_COMMAND="history -a; history -c; history -r"

işlevselliğin çoğuna sahipken, yukarıda belirtildiği gibi bir sorun yoktur.

Dikkat edilmesi gereken başka bir nokta: gerçekten sihirli bir şey yok . Prompt_COMMAND yalnızca düz bir bash ortam değişkenidir. İçindeki komutlar bash istemini ($ işareti) almadan önce yürütülür. Örneğin, Prompt_COMMAND "echo 123" dir ve terminalinizde "ls" çalıştırın. Etkisi "ls; echo 123" çalıştırmak gibidir.

$ Prompt_COMMAND="echo 123"

output (Tıpkı 'Prompt_COMMAND = "echo 123"; $ Prompt_COMMAND' gibi):

123

Aşağıdakileri çalıştırın:

$ echo 3

çıktı:

3
123

"history -a", bellekteki geçmiş komutlarını ~/.bash_history'ye yazmak için kullanılır

"history -c" bellekteki geçmiş komutlarını silmek için kullanılır

"history -r" ~/.bash_history'den belleğe geçmiş komutlarını okumak için kullanılır

Geçmiş komutu açıklamasına buradan bakın: http://ss64.com/bash/history.html

Not: Diğer kullanıcıların belirttiği gibi, dışa aktarma gereksizdir. Bakınız: .bashrc'de dışa aktarmayı kullanarak

5
fstang

Ben her oturum veya görev başına bir geçmiş dosyası ayarlamak için bir komut dosyası yazdım onun dayalı.

        # 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

Her geçmiş komutunu kaydetmek gerekli değildir, ancak önem verdiklerimi kaydeder ve daha sonra her komuttan geçerek bunları almak daha kolaydır. Sürümüm ayrıca tüm geçmiş dosyalarını listeler ve bunların tümünü arama olanağı sağlar.

Tam kaynak: https://github.com/simotek/scripts-config/blob/master/hiset.sh

3
simotek

İşte bireysel oturumlardan geçmişleri karıştırmayan bir çözüm!

Temel olarak, her oturumun geçmişini ayrı ayrı saklamak ve her İstemde yeniden oluşturmak gerekir. Evet, daha fazla kaynak kullanıyor, ancak göründüğü kadar yavaş değil - gecikme yalnızca 100000'den fazla geçmiş girdiniz varsa fark edilmeye başlar.

İşte temel mantık:

# 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

Bazı önlemler ve performans optimizasyonları da dahil olmak üzere eksiksiz bir çözüm için this Gist adresine bakın.

3
Jan Warchoł

Çünkü özel dosyaya kaydedilmiş sonsuz geçmişi tercih ederim. Bu yapılandırmayı 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"
2
Eugen Konkov

Bu ZSH için çalışır

##############################################################################
# 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
2
Mulki

Uzun zamandır bunu istedim, özellikle yeni bir projede yeniden yürütmek (veya bir komutla bir dizin bulmak) için çalıştırılan bir komutu alma yeteneği. Bu yüzden, global CLI geçmişini depolamak için önceki çözümleri percol (C ^ R ile eşleştirilmiş) adı verilen etkileşimli bir açma aracıyla birleştiren bu araç bir araya getirdim. Kullanmaya başladığım ilk makinede hala kaygan, şimdi> 2 yıllık bir CLI geçmişi var.

Ok tuşları söz konusu olduğunda yerel CLI geçmişiyle uğraşmaz, ancak küresel geçmişe kolayca erişmenizi sağlar (C ^ R dışında bir şeye de eşleştirebilirsiniz)

2
Gordon Wells

İşte .bashrc kod parçacığı ve gerektiğinde kısa açıklamalar:

# 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 ve HISTSIZE kişisel tercihlerdir ve bunları zevkinize göre değiştirebilirsiniz.

0
Hopping Bunny