Birden çok terminal penceresinde bash geçmişini koru


526

Sürekli olarak birden fazla terminal açıkım var. Her iki ila on arasında, çeşitli bit ve bobs yapıyor. Şimdi başka bir terminal setini yeniden başlatıp açtım diyelim. Bazıları bazı şeyleri hatırlar, bazıları unutur.

Bir tarih istiyorum ki:

  • Her terminaldeki her şeyi hatırlar
  • Her terminalden anında erişilebilir (örneğin, eğer lsbir içindeysem, çalışmakta olan başka bir terminale geç ve sonra lsaçılır)
  • Komutun önünde boşluklar varsa komutu unutma.

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


57
Bunun avantajını görebiliyorum ama şahsen kabuğumdan nefret ediyorum. Terminalimde çok özel kullanımlar için genellikle 3 veya 4 sekme açık tutarım: biri 'make', biri vi, diğeri eşyaları çalıştırıyor, vb. 'gelir ve böyle devam eder. Bu benim için son derece verimli. Eğer birden bire 'make' sekmesine gidip vurursam ve bazı rastgele grep komutları ortaya çıkarsa, gerçekten çok kızardım! Sadece kişisel bir not olsa
axel_c

4
@axel_c bu doğru. Mevcut terminallerin yalnızca kendi tarihlerini gördüğü, ancak yenilerinin kronolojik olarak doğru bir komut listesi gördüğü yerlerde bunu yapmanın akıllıca bir yolunu düşünemiyorum.
Oli

8
@Oli, "Mevcut terminallerin yalnızca kendi tarihlerini gördüğü, ancak yenilerinin kronolojik olarak doğru bir komut listesi gördüğü yerlerde bunu yapmanın akıllıca bir yolunu düşünemiyorum." Dedi. Nasıl hakkında (denenmemiş): export PROMPT_COMMAND="history -a; $PROMPT_COMMAND". Mevcut mermiler, yeni mermilerin görmesi için her komutu geçmiş dosyasına ekler, ancak yalnızca kendi geçmişini gösterir.
Chris Sayfa

2
Geçmişin hepsinin ayrı ayrı depolanmasını mı yoksa hepsini tek bir tarih dosyasında birleştirilmesini mi istiyorsunuz?
kbyrd

3
Kısa cevap: bash geliştiricileri tarafından tasarlanmamıştır. Yıkamaya dayanan ve ardından tarihi yeniden okuyan çözümler muhtemelen işe yarar , ancak Shlemiel The Painter'a dikkat edin . Düz bir deyişle: Her komut arasındaki işlem işi miktarı tarihçe boyutuyla orantılıdır.
Stéphane Gourichon 19:14

Yanıtlar:


329

Aşağıdakileri ~ / .bashrc dosyasına ekleyin.

# Avoid duplicates
export 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
export PROMPT_COMMAND="${PROMPT_COMMAND:+$PROMPT_COMMAND$'\n'}history -a; history -c; history -r"

20
Bu PROMPT_COMMAND çözümüyle ilgili sorun, her komuttan sonra her bir tarih öğesinin sayısının değişmesidir :(. Örneğin, tarih ve 1) ls 2) rm yazarsanız, o zaman! 1'i tekrarlamak için, tarih numarası değişebilir ve rm komutunu çalıştırabilir ...
Chris Kimpton

2
Bunu yaptığımda, zaten açık olan diğer terminaller, bu terminalde bir komut verene kadar 'Yukarı'ya bastığımda son girilen komutu kullanmıyor - bu bekleniyor mu? Eğer öyleyse, diğer terminallerin tarihini anında değiştirmenin bir yolu var mı?
Suan

7
@Suan, bu komutlara dayanarak bana doğru geliyor. Geçmişi güncellemek için boş bir komut verebiliriz (sadece enter tuşuna basın).
adaçayı

3
Aslında history -a(...) silme çiftleri tetiklemez göre bu soru cevap “ignoredups” ve oturumlar boyunca ortak geçmişi olan çatışmayı ayarı “erasedups”: Bash tarihinin . Bu cevap aynı zamanda ayar history -<option>ile çalışan komutların sırasını da verir HISTCONTROL=ignoredups:erasedups.
Piotr Dobrogost

23
İçin hiçbir neden yoktur ve değişkenler: Eğer bunları tanımlayan böylece (ayrıca savurgan bile etkileşimli olmayan olanlar,) her kabukta belirlenecektir. exportHISTCONTROLPROMPT_COMMAND.bashrc
dolmen

248

Yani, tüm bunlar tarihle ilgili olan .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 ile test edildi, 10.6'da bash 4.1.7.


3
Hmm .. Bu komut numaraları her istemde değiştikçe $ 34'i kullanma yeteneğini öldürür. @Davide @Schof @kch bir geçici çözüm var mı?

5
Sonsuz tarih almak için bunu kullanın: bash sonsuz tarih . Ancak, bu otomatik olarak yeniden yüklenmeyeceğinden yukarıdaki koda ücretsizdir.

7
Bilginize Burada belirtilen çözümlerin hiçbiri aşağıdaki sorunu çözemez. İki kabuk penceresi A ve B var. Kabuk penceresinde A, koştum sleep 9999ve (uykunun bitmesini beklemeden) kabuk penceresinde B, sleep 9999bash geçmişinde görebilmek istiyorum .
puanlar

1
Pts ben de canlı davranışı hedefliyordu, ama sonra farklı terminallerde farklı şeyler üzerinde çalışmayı kolaylaştıran terminale özgü tarihlere sahip olmanın daha uygun olduğunu anladım. Bunu çok faydalı buldum: stackoverflow.com/questions/338285/#answer-7449399 Buna dayanarak, kendime hrefşu anki terminalimin geçmişini anında yenileyip işlemdeki geçmiş dosyasını temizleyen bir takma ad yaptım . Ne zaman yeni bir terminal açsam, bu temizleme / senkronizasyon bashrc dosyamda yürütülüyor, böylece yeni terminal en son tarihe sahip olacak. Bununla birlikte kullanıyorumhistory -a
trusktr 16:12

6
exportDeğişkenlerin hiçbir nedeni yoktur : onları .bashrctanımladığınız için her kabukta tanımlanırlar (etkileşimli olmayanlar da dahil olmak üzere, bunlar israftır)
dolmen

118

İşte Bash oturumu tarih paylaşımı benim girişimi. Bu, bash oturumları arasında tarih sayacının karışmayacağı ve tarihin genişlemesi gibi !number(bazı kısıtlamalarla) işe yaramayacak şekilde paylaşım yapmayı sağlar .

Ubuntu 10.04 LTS (Lucid Lynx) altında Bash sürüm 4.1.5 kullanılması.

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

Açıklama:

  1. Az önce girilen satırı ekle $HISTFILE(varsayılan değer .bash_history). Bu, $HISTFILEbir satır büyümeye neden olur .

  2. Özel değişkeni $HISTFILESIZEbir değere ayarlamak, en eski girişleri kaldırarak Bash'in satırlardan $HISTFILEdaha uzun olmamasına neden olur $HISTFILESIZE.

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

  4. İçeriğini okuyun $HISTFILEve bunları geçerli çalışan oturum geçmişine ekleyin. Bu, tarih sayacını içerdiği satır miktarıyla artıracaktır $HISTFILE. Satır sayısının $HISTFILEmutlaka olmadığına dikkat edin $HISTFILESIZE.

  5. history()Fonksiyon yerleşik tarih görüntülenmeden önce geçmiş senkronize emin olmak için geçersiz kılar. Bu sayıya göre tarih genişlemesi için gereklidir (daha sonra bu konuda daha fazla).

Daha fazla açıklama:

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

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

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

  • 3. adımda tarih sayacı azalır $HISTSIZE. 4. adımda, geçmiş sayıcı içindeki satır sayısı ile yükseltilir $HISTFILE. 2. adımda, satır sayısının $HISTFILEtam olduğundan emin oluruz $HISTSIZE(bu $HISTFILESIZE, aynı olması gerektiği anlamına gelir $HISTSIZE).

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

Sayısına göre tarih genişlemesini kullanırken, gereken her zaman numarayı aramak hemen kullanmadan önce. Bu, numarayı aramak ve kullanmak arasında hiçbir hızlı bilgi istemi göstergesi olmadığı anlamına gelir. Bu genellikle girilmez ve ctrl + c olmaz.

Genel olarak, birden fazla Bash oturumunuz olduğunda, sayı tarihine göre bir genişlemenin iki Bash bilgi istemi ekranı arasındaki değerini koruyacağının garantisi yoktur. Çünkü PROMPT_COMMANDyürütüldüğünde, diğer tüm Bash oturumlarından gelen geçmiş, geçerli oturumun geçmişine entegre edilir. Başka bir bash oturumunun yeni bir komutu varsa, o zaman geçerli oturumun geçmiş numaraları farklı olacaktır.

Bu kısıtlamayı makul buluyorum. Zaten her seferinde bu sayıya bakmak zorundayım çünkü rastgele tarih sayılarını hatırlayamıyorum.

Genellikle tarih genişlemesini bu sayıya kadar kullanırım

$ history | grep something #note number
$ !number

Aşağıdaki Bash seçeneklerini kullanmanızı öneririm.

## 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 aktarılan 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 listelenir. Neden olduğuna dair hiçbir fikrim yok.

İyileştirmeler için fikirler:

  • İşlevi _bash_history_sync(), her seferinde yürütülmeyecek şekilde değiştirin . Örneğin CTRL+C, komut isteminde sonra çalıştırılmamalıdır . CTRL+CBu satırı çalıştırmak istemediğime karar verdiğimde genellikle uzun bir komut satırını atmak için kullanırım . Bazen CTRL+Cbir Bash tamamlama komut dosyasını durdurmak için kullanmam gerekir.

  • Geçerli oturumun komutları, her zaman geçerli oturumun geçmişindeki en son komut olmalıdır. Bu aynı zamanda, belirli bir geçmiş numarasının, bu oturumdan gelen tarih kayıtları için değerini korumasının da yan etkisi olacaktır.


1
Neden "history -c; history -r" yerine "history -n" (yeniden yüklenmemiş satırları yüklemedi)?
Graham,

@ Graham: Kullanmak istemedim history -nçünkü tarih sayacını mahvetti . Ayrıca, history -nçok güvenilmez olduğunu gördüm .
lesmana

1
Tek dezavantaj: Çok satırlı dizgelere sahip komutlar normal olarak geçerli oturumda korunur. Bu numara ile anında bireysel çizgiler halinde bölünürler. -C -r için -n komutunun kullanımı yardımcı olmaz, cmdhist veya lithist da değildir. Bu noktada bir geçici çözüm olduğunu sanmıyorum.
Jo Liss

24
Biraz bu denedikten sonra, aslında sadece çalışan fark ettik history -aolmadan -cve -r(o soru sorulduğunda bu değil gerçi), daha iyi kullanılabilirlik-akıllıca olacaktır. Çalıştırdığınız komutların, geçerli kabuktan çıkmadan önce bile yeni mermilerde anında kullanılabileceği, ancak aynı anda çalışan mermilerde olmadığı anlamına gelir. Bu şekilde, Yukarı Ok her zaman geçerli oturumun son çalıştırma komutlarını seçer , bu da daha az kafa karıştırıcı buluyorum.
Jo Liss,

son derece iyi cevap, bu daha yaygın "tarih-a; tarih -n" aksine güvenilir çalışır
RichVel

42

Kullanmanın hiçbir şekilde farkında değilim bash. Ancak en popüler özelliklerinden biri zsh.
Şahsen ben tercih zshüzerinde bashbu yüzden denemenizi öneririz.

İşte benim .zshrctarihle ilgilenen bölümüm:

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


16

Bunu yapmak için, size iki satır eklemeniz gerekir ~/.bashrc:

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

Kimden man bash:

Histappend kabuğu seçeneği etkinse (aşağıdaki SHELL BUILTIN KOMUTLARI altındaki shopt'un açıklamasına bakınız), çizgiler geçmiş dosyasına eklenir, aksi takdirde geçmiş dosyası yeniden yazılır.


10

Muerr'in önerdiği "history -a" ve "history -r" komutlarını çalıştırmak için BASH isteminizi düzenleyebilirsiniz:

savePS1=$PS1

(bir şeyi karıştırırsanız, neredeyse garantilidir)

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

(bunların geri tıklamalar olduğunu not edin; her komut satırında tarih-a ve tarih -r'yi çalıştırırlar. Herhangi bir metin çıkmadıklarından komut isteminiz değişmeyecektir.

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

Test ederken orijinal isteminize geri dönmek istiyorsanız, aşağıdakileri yapın:

PS1=$savePS1

Bunun işe yarayacağından emin olmak için bu konuda temel testler yaptım, ancak history -a;history -rher istemde çalıştırmanın yan etkileri ile konuşamıyorum .


2
kch'in çözümü benimkinden daha iyi çalışıyor. Şimdi onun çözümünü .bashrc'ımda kullanıyorum.

9

Aşağıdaki sorunu da çözen bir bash veya zsh geçmişi 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 şu: A ve B'de iki kabuk penceresi var: Kabuk penceresinde A, koştum sleep 9999ve (uykunun bitmesini beklemeden) kabuk penceresinde B, sleep 9999bash geçmişinde görebilmek istiyorum .

Buradaki diğer çözümlerin çoğunun bu sorunu çözmemesinin nedeni, geçmiş değişikliklerini PROMPT_COMMANDveya PS1her ikisini de çok geç yürüten geçmiş dosyasında yalnızca sleep 9999komut tamamlandıktan sonra yazarak geçmiş değişikliklerini yazmalarıdır .


1
Bu güzel bir çözüm, ancak birkaç sorum var. 1. Orijinal .bash_history dosyasını kullanabilir miyim, $ HOME'umda başka bir bash geçmişi dosyası olmasını istemiyorum 2. Bunun için bir github repo ayarlamayı düşünmelisiniz.
weynhamz

Hata ayıklama kancası bashdb ile çakışıyor, her bash oturumu başlattığımda takip çıktısı. `` `bash debugger, bashdb, 4.2-0.8 yayın. Copyright 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Rocky Bernstein Bu, GNU Genel Kamu Lisansı kapsamındaki ücretsiz bir yazılımdır ve sizleri bekliyoruz. belirli koşullar altında değiştirin ve / veya kopyalarını dağıtın. ** Dahili hata ayıklama hatası _Dbg_is_file (): file argümanı null bash: _Dbg_filenames [$ fullname]: hatalı dizi alt dizini `` `
weynhamz

@Techlive Zheng: 1. Orijinal .bash_history kasıtlı olarak desteklenmez, çünkü .merged_bash_history farklı bir dosya formatı kullanır; Tasarımdaki sağlamlık, olduğu gibi korunacaktır. 2. Bir github deposu genel olarak iyi bir fikirdir, ancak bu proje için bunu sürdürecek zamanım yok, bu yüzden yapmıyorum. - Evet, bashdb ile çakışıyor ve kolay bir çözüm yok (aynı kancaları kullanıyorlar). Bir düzeltme üzerinde çalışmayı planlamıyorum, ancak yamaları kabul ediyorum.
pts

Tamam teşekkür ederim. Çok basit ve daha iyi bir sulotion ile karşılaştım.
weynhamz

@TechliveZheng: Sizler için basit ve daha iyi bir çözümünüzü bizimle paylaşır mısınız? (Eğer öyleyse, soruya bir yanıt ekleyin.)
puan

8

Sen kullanabilirsiniz history -asonra, HISTFILE geçerli oturumun tarihini eklemek kullanmak history -rHISTFILE okumak için diğer terminallerde. 


8

Doğru, Sonunda bu nezih 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"

Bunu yapan, bu konudaki söylenenlerin bir birleşimidir; bunun haricinde, her emirden sonra neden küresel tarihi yeniden yükleyeceğinizi anlamıyorum. Diğer terminallerde ne olacağını çok nadir umursuyorum, ancak her zaman bir terminalde bir dizi komut çalıştırıyorum:

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

(Basitleştirilmiş örnek)

Ve başka bir:

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

Komutun paylaşılmasını istememe imkân yok


1
Her komuttan sonra geçmişi yeniden yüklemenizin nedeni, sorunun gerektirdiği davranışın olmasıdır (ve bu aslında soruyu asıl olarak cevaplamıyor).
Michael Homer

2
@ MichaelHomer Fuar noktası. Yanıtı en altta kalacak şekilde düşürmekte özgürsünüz, ancak, istenen davranışın ne kadar kötü olduğunu ve bunun çok cilveli bir soru olduğu gerçeğini fark etmeden OP'ye yazıyorum.
Yarek T

3
Op burada, evet, bu adil bir uzlaşma. Asıl şikayetim, tarihi kaybettiğim. Bu, eşzamanlı oturumlar arasında anında güncelleme anlamına gelmese bile, bunu durdurmalıdır.
Oli,

7

İşte kullandığım bir alternatif. Bu çok zahmetlidir, ancak @axel_c'nin bazen her terminalde ayrı bir tarih örneği almak isteyebileceğinizden (biri yapım, diğeri izleme, diğeri vb.) İsteyebileceği konusuna değinir.

Sürekli güncellediğim ayrı bir ekli geçmiş dosyası tutuyorum. Aşağıdakiler bir kısayol tuşuyla eşleştirildi:

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

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

Ayrıca, ana tarih dosyasını aramak için ayrı bir kısayol tuşum var:

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

Ben kedi kullanırım | grep çünkü regex'ime girmek için imleci sonunda bırakır. Bunu yapmanın daha az çirkin bir yolu, bu görevleri gerçekleştirmek için yolunuza birkaç komut dosyası eklemektir, ancak kısayol tuşları benim amaçları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 tarihi master_history.txt dosyasına eklerim.

Kullandığın o zorlu regex'i veya 7 ay önce bulduğun garip perl'i bulmak için hızlıca arama yapmak her zaman güzeldir.


6

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

Fakat acınızı birden fazla eşzamanlı seansla hissediyorum. Basitçe bash içinde iyi işlenmiyor.


6

İşte @ Lesmana en benim geliştirmesidir cevap . En büyük fark, eşzamanlı pencerelerin geçmişi paylaşmamasıdır. Bu, mevcut pencerenize başka pencerelerden içerik yüklenmeden pencerelerinizde çalışmaya devam edebileceğiniz anlamına gelir.

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

Ayrıca, bu stratejiyi 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 "$@"
}

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

5

Aynı sunucu üzerinde birden fazla kişi çalışabileceği için tarih başına dosya başına bir dosya koymayı seçtim - her oturumun komutlarını ayırmak denetlemeyi kolaylaştırıyor.

# 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

Artık tarih şuna benziyor:

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

Gibi görünen dosyaları ile:

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

3

Burada bir sorunu işaret edeceğ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 gibi olacaktır

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

ve

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

Bu tekrar, 'source ~ / .bashrc' dosyasını her çalıştırışınızda gerçekleşir. 'Echo $ PROMPT_COMMAND' komutunu çalıştırarak 'source ~ / .bashrc' komutunu her çalıştırdığınızda PROMPT_COMMAND öğesini kontrol edebilirsiniz.

Bazı komutların açık bir şekilde bozulmuş olduğunu görebiliyordunuz: "history -n history -a". Fakat iyi haber şu ki, hala çalışıyor, çünkü diğer bölümler hala geçerli bir komut dizisi oluşturuyor (Bazı komutları tekrarlı bir şekilde yerine getirme nedeniyle ekstra bir miktar maliyet gerektiriyor. 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şlevselliklerin çoğuna sahip olan ve yukarıda belirtilenlerin hiçbirinde sorun yok.

Yapılması gereken bir başka nokta: Gerçekten sihir yok . PROMPT_COMMAND sadece basit bir bash ortam değişkenidir. İçindeki komutlar bash istemi ($ işareti) almadan önce yerine getirilir. Örneğin, PROMPT_COMMAND cihazınız "echo 123" dür ve terminalinizde "ls" yi çalıştırırsınız. Etki "ls; echo 123" çalıştırmak gibidir.

$ PROMPT_COMMAND="echo 123"

çıktı (Tıpkı 'PROMPT_COMMAND = "echo 123"; $ PROMPT_COMMAND' gibi):

123

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

$ echo 3

çıktı:

3
123

"history -a", geçmiş komutlarını bellekte ~ / .bash_history dosyasına yazmak için kullanılır.

"history -c", bellekteki tarih komutlarını silmek için kullanılır.

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

Burada tarihçe komut açıklamasına bakınız: http://ss64.com/bash/history.html

Not: Diğer kullanıcılar belirttiği gibi, ihracat gereksizdir. Bakınız: .bashrc içindeki dışa aktarımı kullanma


2

Her oturum için bir tarih dosyası veya görev ayarlamak için bir komut dosyası yazdım.

        # 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 tarih komutunu kaydetmeye gerek yoktur, ancak umurumda olanları kaydeder, sonra onları almak daha kolay olur ve her komuttan geçer. Sürümüm ayrıca tüm geçmiş dosyalarını listeliyor ve hepsinde arama yapabilmenizi sağlıyor.

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


2

İşte çözüm gelmez bireysel oturumlarda yapılan geçmişlerini karıştırmak!

Temel olarak, her oturumun geçmişini ayrı ayrı depolamak ve her istekte yeniden oluşturmak zorundadır. Evet, daha fazla kaynak kullanıyor, ancak göründüğü kadar yavaş değil; gecikme yalnızca 100000'den fazla geçmiş girişiniz varsa farkedilmeye başlıyor.

İş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ı güvenlik önlemleri ve performans iyileştirmeleri dahil olmak üzere tam bir çözüm için bu özete bakın .


1

Bu ZSH için çalışıyor

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

Maalesef soru kesinlikle bash :-) içindir
Jaleks

1
Ben de zsh için arama yaptığımda google'da ilk sonucu ... yardımcı olabileceğini düşündüm
Mulki

3
Yeni bir soru sormalısınız, ~ "Zsh tarihçesini çoklu terminal pencerelerinde koru", zaten birinin olmadığını varsaymalısınız. Tamamen iyi - hatta teşvik edilir - iyi bir soru ise kendi sorunuzu cevaplamak için.
Oli,

1

Bunu çok istedim, özellikle de yeni bir projede yeniden çalıştırılmak üzere çalıştırıldığı bir komutu (ya da bir komutla bir dizini bulmak). Bu yüzden , global bir CLI geçmişini saklamak için önceki çözümleri bir araya getiren ve bu aracı percol (C ^ R ile eşlenmiş) olarak adlandırılan etkileşimli bir grepping aracıyla bir araya getirdim. Kullanmaya başladığım ilk makinede, şimdi> 2 yıllık bir CLI geçmişiyle kayganlaşıyor.

Ok tuşlarıyla ilgili olarak yerel CLI geçmişiyle uğraşmaz, ancak küresel tarihe kolayca erişmenize izin verir (C ^ R'den başka bir şeyle de eşleştirebilirsiniz)


bu zsh için mi?
sjas

1
evet, başlangıçta zsh için yaptım. Yine de bash ve balık için çalışıyor. Çalışıp çalışmadığını bana bildirin. Bir süredir değişmedim ve kurulum talimatlarımda ne kadar net olduğumdan emin değilim
Gordon Wells

1

Çünkü ben özel dosyaya kaydedilen sonsuz tarihi tercih ediyorum. Bu yapılandırmayı https://stackoverflow.com/a/19533853/4632019 a dayanarak oluşturuyorum :

export HISTFILESIZE=
export HISTSIZE=
export HISTTIMEFORMAT="[%F %T] "

export HISTFILE=~/.bash_myhistory
PROMPT_COMMAND="history -a; history -r; $PROMPT_COMMAND"

-1

İşte benim .bashrc kod parçacığım ve gereken her yerde 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.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.