Bir terminalden çıkarken bash geçmişini diğer terminallerde güncelleme


15

Burada sorulduğu gibi bu sorunun belirsiz olmadığını biliyorum (ve burada çoğaltılır ) güncellemeye devam edin .

Ulaşmaya çalıştığım şey biraz farklı. Yazdığım her dosyayı ls( history -a; history -c; history -r) yazdığım isteminden hoşlanmıyorum .

Çıkışta dosyayı güncellemek istiyorum. Bu kolay (aslında varsayılan), ancak yeniden yazmak yerine eklemeniz gerekir:

shopt -s histappend

Şimdi, bir terminal kapatıldığında, güncellemenin farkında olmak için açık kalan tüm diğerlerini yapmak istiyorum.

Bunu yazdığım $PS1her commandşeyi kontrol etmeden yapmayı tercih ederim . Bence bir tür sinyal yakalamak daha iyi olur. Bunu nasıl yaptın? Mümkünse, belki basit bir cronjob?

Bu bulmacayı nasıl çözebiliriz?


1
Zsh'ın bunu kutudan çıkardığını unutmayın (ve geçmiş paylaşımında ince ayar yapmak için birçok seçeneğe sahiptir).
Gilles 'SO- kötü olmayı bırak

Teşekkürler @Gilles; Komik, yıllar Linux kullanarak ve ben asla başka bir şey denedim bash. Belki de sadece eğlence için yeni bir şeyi kontrol etme zamanı.
Dr Beco

Yanıtlar:


15

Yaratıcı ve ilgili sinyalleri mi söylüyorsunuz? TAMAM:

trap on_exit EXIT
trap on_usr1 USR1

on_exit() {
    history -a
    trap '' USR1
    killall -u "$USER" -USR1 bash
}

on_usr1() {
    history -n
}

İçine çek .bashrcve git. Bu, sinyallere her bashişlemden başka bir çıkış olduğunda yeni geçmiş girişlerini kontrol etmesini bildirmek için kullanır . Bu oldukça korkunç, ama gerçekten işe yarıyor.


O nasıl çalışır?

trapbir sistem sinyali veya Bash'ın dahili olaylarından biri için bir sinyal işleyici ayarlar . EXITİse olay, kabuğun herhangi kontrollü fesih olduğunu USR1ise SIGUSR1, biz mülk ediyoruz anlamsız bir sinyali.

Mermi her çıktığında:

  • Tüm geçmişi dosyaya açıkça ekleyin.
  • SIGUSR1İşleyiciyi devre dışı bırakın ve bu kabuğun sinyali yok saymasını sağlayın .
  • Sinyali bashaynı kullanıcıdan gelen tüm çalışan işlemlere gönderin .

Geldiğinde SIGUSR1, biz:

  • Geçmiş dosyasındaki tüm yeni girdileri kabuğun bellek içi geçmiş listesine yükleyin.

Eğer çarpana kadar biçimi nedeniyle Bash kolları sinyallerin, aslında yeni geçmiş verileri almazsınız Enterdahaki sefere bu koyarak daha iyi bu cephede yapmaz, bu yüzden history -niçine PROMPT_COMMAND. Yine de hiçbir şey olmadığı zaman dosyayı okumaktan tasarruf eder ve kabuk çıkana kadar hiçbir yazı yoktur.


Bununla birlikte, burada hala birkaç sorun var. Birincisi , varsayılan yanıtıSIGUSR1 kabuğun sonlandırılmasıdır . Diğer tüm bashişlemler (örneğin, kabuk komut dosyalarını çalıştırma) öldürülecektir. .bashrcetkileşimli olmayan mermiler tarafından yüklenmez. Bunun yerine, adlı bir dosya BASH_ENVyüklenir : ortamınızdaki bu değişkeni global olarak aşağıdakileri içeren bir dosyaya işaret edecek şekilde ayarlayabilirsiniz:

trap '' USR1

içindeki sinyali görmezden gelmek için (sorunu çözer).

Son olarak, bu ne istediğini yapsa da, aldığınız sipariş biraz olağandışı olacaktır. Özellikle, tarih bitleri ayrı yüklendikçe ve kaydedildikçe farklı siparişlerde tekrarlanacaktır. Bu aslında ne istediğinin doğasında var, ancak yukarı ok tarihinin bu noktada çok daha az kullanışlı hale geldiğini unutmayın. Bununla birlikte, tarih ikameleri ve benzerleri paylaşılacak ve iyi çalışacaktır.


.bashrcDosyada zaman damgasını etkinleştirip etkinleştirmediğinizi ve sonra bir cronjob gibi bir şey gelip dosyayı periyodik SIGUSR1olarak çağırarak, snippet'inize göre bir kronolojik yukarı ok geçmişi kazanıp kazanamayacağınızı merak ediyorum.
forquare

Bu temiz bir çözüm, ancak diğer süreçler USR1 üzerinde sona eriyor. Bu davranış USR2 ile de olur mu?
Dr Beco

İkinci bir yorum ekleyeceğim, çünkü şaşırdım. Süreç TERM'yi USR1 ile nasıl ilişkilendirir? USR1 sadece kullanıcı tarafından kullanılacak bir şey değil mi ?? Bu biraz mı linux bug?? Neden diğer süreçler USR1'i yakalıyor? (Burada tartışılmak istenmediğini biliyorum, ama belki de bunu doğru yerde ışığa getireceğim)
Dr Beco

Neredeyse tüm sinyallerin varsayılan davranışı sona erdirmektir; POSIX'te belirtilmiştir . Bu bir hata değil. Bash, sinyalin tüm işlemleri için göz ardı edileceğini belirtmenize izin verecektir, bu nedenle bizim amaçlarımız için iyi.
Michael Homer

Teşekkürler @MichaelHomer. Yapmak istediğiniz bu özellik BASH_ENVbu cevapta belirtildiği gibi mi? Yoksa bu kötülüğü kapatmanın daha standart bir yolunu biliyor musunuz?
Dr Beco
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.