Bash tarihi: “yok sayılanlar” ve “silinen” oturumlar arasında ortak tarih ile çatışan


84

Her şeyden önce, bu SE üzerindeki mevcut konuların kopyası değildir. Bu iki konuyu daha iyi bash tarihiyle ilgili okudum ( 1. , 2. ), ancak cevapların hiçbiri işe yaramaz - - Bu arada Fedora 15'im.

Aşağıdakileri .bashrckullanıcı dizinindeki dosyaya ekledim (/ home / aahan /), ve çalışmıyor. Bir ipucu olan var mı?

HISTCONTROL=ignoredups:erasedups  # no duplicate entries
HISTSIZE=1000                     # custom history size
HISTFILESIZE=100000                 # custom history file size
shopt -s histappend                      # append to history, don't overwrite it
PROMPT_COMMAND="history -a; history -c; history -r; $PROMPT_COMMAND"  # Save and reload the history after each command finishes

Tamam, bash tarihiyle istediğim şey bu (öncelik):

  • kopyaları saklamayın, var olanları silin
  • derhal tüm açık terminallerle geçmişi paylaş
  • her zaman tarih ekler, üzerine yazmaz
  • çok satırlı komutları tek bir komut olarak sakla (varsayılan olarak kapalıdır)
  • varsayılan Geçmiş boyutu ve geçmiş dosyası boyutu nedir?

çarpmak! kimse? Hiç birşey çalışmıyor. Bu Fedora 15 ile ilgili bir sorun olabilir mi (Gnome 3 ile ve Windows ana bilgisayarında çalışan bir makinede)?
its_me

Lütfen burada yayınlara "çarpma" yapmayın. Eğer cevap alamıyorlarsa, daha net bir şekilde sormanız gerekir, bağlam ipuçlarının doğru parçalarını ya da bir şeyleri ekleyin. Yayınlarınıza dikkat etmeniz gerekiyorsa, daha fazla insanın onlara daha fazla dikkat etmesine yardımcı olan ödüller verebilirsiniz.
Caleb

1
Bash kullandığınızdan emin misiniz? ( echo $SHELL). Manüel olarak açık kabuğunuzdan çalıştırırsanız ayarlar çalışır mı? Açıkçası, pek çokları için çalıştıkları için ayarlar doğru, sadece onları yanlış uyguluyorsunuz. Ve hiçbir Fedora15 / Gnome3 / sanal makine olmanın asıl işlevi ile ilgisi yok bash.
Caleb

@Caleb, önce yazıyı çarptığın için üzgünüm. Ayrıca, çok net olmak için elimden geleni yaptım. Hayır, onları kabuğun içinde yayınlamadım. Onları kopyaladım .bashrc. Yanlış mı? Bu yazıya gerçek kabuk komutlarıyla bir "cevap" ekleyebilir misiniz? (lütfen noob-
ity'ye katlanın

1
Komut dosyalarına veya .bashrcARE gerçek kabuk komutlarına yazdığınız her şey . Scriptler sadece kabuk komutları dizisidir. Ayrıca, son zamanlarda exportbiti çıkarmadan yaptığınız düzenleme kötü bir fikirdi, tutulması gereken.
Caleb

Yanıtlar:


119

Bu aslında gerçekten ilginç bir davranış ve başlangıçta soruyu büyük ölçüde hafife aldığımı itiraf ediyorum. Ama önce gerçekler:

1. Ne işe yarıyor

İşlevsellik, her biri biraz farklı olsa da, çeşitli yollarla sağlanabilir. Her durumda, tarihin başka bir terminale (güncellenmiş) "aktarılması" için, kişinin Entertarih almak istediği terminale basması gerektiğini unutmayın.

  • seçenek 1:

    shopt -s histappend
    HISTCONTROL=ignoredups
    PROMPT_COMMAND="history -a; history -n; $PROMPT_COMMAND"

    Bunun iki dezavantajı var:

    1. Oturum açma sırasında (bir terminal açma), geçmiş dosyasındaki son komut mevcut terminalin geçmiş arabelleğine iki kez okunur;
    2. Farklı uçbirimlerin arabellekleri, geçmiş dosyasıyla eşit kalmaz.
  • seçenek 2:

    HISTCONTROL=ignoredups
    PROMPT_COMMAND="history -a; history -c; history -r; $PROMPT_COMMAND"

    (Evet, gerek yok shopt -s histappendve evet, tam ortasında olmalı ) Bu sürümün iki önemli dezavantajı var:history -cPROMPT_COMMAND

    1. Geçmiş dosyası başlatılmalıdır. En az bir boş olmayan satır içermesi gerekir (herhangi bir şey olabilir).
    2. historyKomut yanlış çıktı verebilir - aşağıya bakın.

[Düzenle] "Ve kazanan ..."

  • seçenek 3:

    HISTCONTROL=ignoredups:erasedups
    shopt -s histappend
    PROMPT_COMMAND="history -n; history -w; history -c; history -r; $PROMPT_COMMAND"

    Bu olabildiğince uzak. Aynı anda hem ortak tarihin çalışabilmesi tek seçenek erasedups. Bu muhtemelen son çözüm tüm sorunları Aahan için.


2. Neden gelmez seçenek 2 çalışması değildi (ya da: gerçekten neyi beklendiği gibi çalışmaz)?

Bahsettiğim gibi, yukarıdaki çözümlerin her biri farklı şekilde çalışır. Ancak ayarların nasıl yürüdüğüne dair en yanlış yorumlama historykomutun çıktısını analiz etmekten gelir . Çoğu durumda, komut yanlış çıktı verebilir . Neden? Çünkü ! ' Da yer alan diğer komutların dizisinden önce yürütülür . historyPROMPT_COMMANDBununla birlikte, ikinci veya üçüncü seçeneği kullanırken, kişi .bash_historyiçeriğin değişimlerini izleyebilir ( watch -n1 "tail -n20 .bash_history"örneğin kullanarak ) ve gerçek tarihin ne olduğunu görebilir.

3. Seçenek 3 neden bu kadar karmaşık?

Her şey yolunda yatar erasedups. Bash el kitabında belirtildiği gibi, "(...) erasedups, geçerli satırla eşleşen önceki tüm satırların o satır kaydedilmeden önce geçmiş listesinden kaldırılmasına neden olur" . Dolayısıyla OP'nin istediği şey buydu (ve daha önce düşündüğüm gibi, sırayla görünen hiçbir kopyası olmadı ) . İşte bu nedenle, her bir history -.komutun aşağıdakileri yapması veya alması gerekmiyor PROMPT_COMMAND:

  • history -n sahiptir önce orada olmak history -wokumak için .bash_historybaşka herhangi bir terminalden kaydedilen komutlar,

  • history -w vardır dosya ve çiftleri silmek için geçmişi kaydetmek amacıyla orada olmak,

  • history -a olmamalıdır yerine orada yerleştirilmelidir history -wo silme çiftleri tetiklemez, çünkü

  • history -cayrıca her komuttan sonra tarih arabelleğinin silinmesini önlediği için de gereklidir ,

  • ve son olarak, history -rbir ihtiyaç dolayısıyla nihayet terminal oturumları arasında paylaşılan tarih yapmak, dosyadan tarih tampon geri yükleyin.


2
+1 "Ancak ayarların nasıl çalıştığının en yanlış yorumlanması, tarih komutunun çıktısını analiz etmekten gelir." Bunun OP'nin konusunun özü olduğunu düşünüyorum. Mükemmel kesinti.
jasonwryan

2
Sonunda amacını gördüm. 'Çoğaltır' derken benden başka bir şey ifade ediyordun. Sadece aynı komutun dizilerine odaklandım . Cevabım güncellendi - bkz. "Seçenek 3". Ayrıca, sizin durumunuz için, tarihin nasıl çalıştığını test etmek için, watch "tail -n 20 .bash_history"bunun yerine gerçekten kullanmanız gerekir tail -f .bash_history.
rozcietrzewiacz

2
Seçenek 3, 100.000 tarihimin tümünü sildim :( (bash 3.2.25 (1) - yayınlanma)
Felipe Alvarez

2
history -cayrıca her komuttan sonra tarih arabelleğinin silinmesini önlediği için de gereklidir. Neden bu geçiş oluyor?
Piotr Dobrogost

2
Çözümünüz 3 aslında işe yaramıyor. Aşırı derecede sorunlu ve kullanıcıların, farklı terminallerde girdikleri sıraya göre değişiyor. Özellikle terminaller arasında ileri ve geri geçiş yaparken genellikle komutların kaybolmasına neden olur. Kaynak: denedi.
6

8

Komut isteminizde, -canahtarı kullanıyorsunuz . Kimden man bash:

-c   Tüm girişleri silerek geçmiş listesini temizle

Geçmişinizi tüm açık terminallerle paylaşmak için, şunları kullanabilirsiniz -n:

-n   Geçmiş dosyasından henüz okunmamış geçmiş satırlarını geçerli geçmiş listesine okuyun. Bunlar, geçerli bash oturumunun başlangıcından beri geçmiş dosyasına eklenen çizgilerdir.

Varsayılan boyut kılavuzda da bulunur:

HISTSIZE Komut geçmişinde hatırlanması gereken komut sayısı (aşağıdaki TARİHÇE bakınız). Varsayılan değer 500'dür.

Çok satırlı komutları kaydetmek için:

Cmdhist kabuk seçeneği etkinleştirildiğinde, sözdizimsel doğruluğunu korumak için gerekli noktalı virgül ekleyerek, aynı tarih girişinde bir çok satırlı komutunun her satırı kaydetmek teşebbüs kabuk neden olur. Lithist kabuk seçeneği gömülü satırbaşıyla yerine noktalı virgül ile komutu kaydetmek için kabuk neden olur.

Ayrıca, HIST * komutlarının önüne geçmemelisiniz export- bunlar çevresel değişkenler değil sadece bash değişkenleridir: HISTCONTROL=ignoredups:erasedupsyeterlidir.


Yani bu export PROMPT_COMMAND="history -a; history -n; history -r; $PROMPT_COMMAND"doğru mu? Ayrıca, tarihçe dosya deposunu çok satırlı komutları tek bir komut olarak nasıl yapabilirim biliyor musunuz?
its_me

1
Evet. Yukarıda belirtilen man sayfasına göre, shopt -s cmdhistçok satırlı tasarruf sağlayacaktır.
jasonwryan

tamam, hepsini denedim. Çalışmıyor gibi görünüyor HISTCONTROL=ignoredups:erasedups. Ayrıca .bashrcdosyada (özel işlevler arasında) sahip olmayı da denedim . Sorunun ne olduğu hakkında bir fikrin var mı? Fedora 15'i sanal bir makinede kullanıyorum - - Windows 7 ana bilgisayarı.
its_me

Diğer başlangıç dosyalarının gibi hiçbir şey yoktur emin olun /etc/bashrc, .bash_profilebunu geçersiz kıldı vb.
jasonwryan

.bash_profileDosyayla ilgili herhangi bir sorun görmüyorum . /etc/bashrcBuraya koyduğum içeriğe gelince , lütfen bir göz atın - pastebin.com/Uae6sE6s
its_me

8

Bu benim geldiğim şeydi ve şimdiye kadar mutluyum…

alias hfix='history -n && history | sort -k2 -k1nr | uniq -f1 | sort -n | cut -c8- > ~/.tmp$$ && history -c && history -r ~/.tmp$$ && history -w && rm ~/.tmp$$'  
HISTCONTROL=ignorespace  
shopt -s histappend  
shopt -s extglob  
HISTSIZE=1000  
HISTFILESIZE=2000  
export HISTIGNORE="!(+(*\ *))"  
PROMPT_COMMAND="hfix; $PROMPT_COMMAND" 

NOTLAR:

  • Evet, karmaşık ... ... ama tüm kopyaları kaldırıyor ve her terminalde kronolojiyi koruyor!
  • Benim HISTIGNOREargüman olmayan tüm komutları yok sayar. Bu, bazı insanlar tarafından istenmeyebilir ve dışarıda bırakılabilir.


0

İşe yaramıyor, çünkü unutuyorsun:

 -n   read all history lines not already read from the history file
      and append them to the history list

Ama göründüğü history -nzaman sadece buggy görünüyor export HISTCONTROL=ignoreboth:erasedups.

Deney yapalım:

$ PROMPT_COMMAND=
$ export HISTCONTROL=ignoreboth:erasedups
$ export HISTFILE=~/.bash_myhistory
$ HISTIGNORE='history:history -w'
$ history -c
$ history -w

Burada silmeyi önleriz, geçmişi özel dosyaya geçiririz, geçmişi sileriz. Tüm komutları tamamladıktan sonra boş geçmiş dosyamız ve mevcut tarihte bir komutumuz var.

$ history
$ cat ~/.bash_myhistory
$ history
$ 1  [2019-06-17 14:57:19] cat ~/.bash_myhistory

İkinci terminali aç ve şu altı komutu da çalıştır. Daha sonra:

$ echo "X"
$ echo "Y"
$ history -w
$ history
  1  [2019-06-17 15:00:21] echo "X"
  2  [2019-06-17 15:00:23] echo "Y"

Şu anki geçmişinizde iki komut var ve geçmiş dosyanız şunları içeriyor:

#1560772821
echo "X"
#1560772823
echo "Y"

İlk terminale geri dön:

$ history -n
$ history
1  [2019-06-17 14:57:19] cat ~/.bash_myhistory 
2  [2019-06-17 15:03:12] history -n

Huh ... hiçbir echokomut okunmuyor. İkinci terminale tekrar geç ve:

$ echo "Z"
$ history -w

Şimdi geçmiş dosya:

#1560772821
echo "X"
#1560772823
echo "Y"
#1560773057
echo "Z"

Tekrar ilk terminale geç:

$ history -n
$ history
  1  [2019-06-17 14:57:19] cat ~/.bash_myhistory 
  2  [2019-06-17 15:03:12] history -n
echo "Z"

Bu echo "Z"komutun birleştiğini görebilirsiniz history -n.

Sanırım bir başka hata da emirlerin emirlerden emir sayısından emir sayısından gelmesidir. echoTarihte başkalarının da görünmesini bekliyorum.


0

Silinenler, bazı ve sondaki boşlukları kesmez (bazı dillerdeki chomp gibi). Bu bir hatadır. Ayrıca silinen önceki girişlerin tümünü silmez.

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.