bash_history: tehlikeli komutları yorumlar: `#`


16

Bash geçmişinde "tehlikeli" komutların günlüğe kaydedilmesini önlemek için, dosyama aşağıdaki satırı ekledim .bashrc:

HISTIGNORE='rm *:mv *:cp *:cat*>*:pv*>*'

bu iyi çalışıyor, ancak bir yan etkisi var: Bir makinede yürütülen komutların tam geçmişini göremiyorum. Diyelim ki deneyler için birkaç makinem var ve tüm komutları görmek istiyorum. Ben bash dahili historyçalıştırılan komutları görüntülemek için kullanın ve belki de bugünün tarihi için grep:

history | grep Sep-28

Yapmak istediğim şey "tehlikeli" komutları da kaydetmektir, ancak #satırın başına bir a koymak , böylece komutu yanlışlıkla tarihe göre yürütürsem, hiçbir hasar olmazdı.

Bunun mümkün olup olmadığı hakkında hiçbir fikrim yok.

Güncelleme ve açıklama:

Bunun benim için bir sorun olmasının ana nedeni, genellikle birkaç terminalden makineme bağlı olmam ve bir terminalde yürütülen herhangi bir komutun hemen diğer terminallerin geçmişine okunmasıdır. Bu,

PROMPT_COMMAND="history -a; history -c; history -r"

İki terminalim açık olduğunu düşünelim. Birinde bazı cat /dev/foo > file.outsüreçler var . İkincisinde, ilerlemeyi ile kontrol ediyorum ls -lAhF. Ve (yani tarihteki son komut) lstuşuna basarak tekrarlamaya devam ediyorum . İlk komut biter bitmez, tarihteki son komut artık değil . Dikkatli olmazsam, cat'ı tekrar başlatacağım ve file.out'un üzerine yazacağım.UpENTERlscat /dev/foo > file.out

Ulaşmak istediğim şey, cat komutunun öncesinde bir ile başlanması #ve böylece yürütülmemesi. Ancak, yine de tarihte görmek ve yorumunu kaldırarak (uzun bir komut ise) yeniden kullanabilirsiniz.


Komutunuzu manuel olarak tekrarlamak yerine watch ls -lAhFveya while sleep 1; do ls -lAhf; done; dosya boyutunu izlemek yerine pv /dev/foo > file.out( ivarch.com/programs/pv.shtml ) kullanabilirsiniz .
deltab

Yanıtlar:


9

Şöyle bir şey yapabilirsiniz:

fixhist() {
   local cmd histnum
   cmd=$(HISTTIMEFORMAT=/ history 1)
   histnum=$((${cmd%%[*/]*}))
   cmd=${cmd#*/} # remove the histnum
   case $cmd in
     (rm\ *|mv\ *|...)
       history -d "$histnum" # delete
       history -s "#$cmd"    # add back with a #
   esac
}
PROMPT_COMMAND=fixhist

Fikir, her komut isteminden önce, son geçmiş girişini ( history 1) kontrol ediyoruz ve tehlikeli olanlardan biriyse, sileriz ( history -d) ve bir #ile geri ekleriz history -s.

(açıkçası HISTIGNOREayarınızı kaldırmanız gerekir ).

Buna da bir istenmeyen yan etkisi değiştirir olmasıdır tarih zamanını olanların rm, mv... komutları.

Bunu düzeltmek için bir alternatif olabilir:

fixhist() {
   local cmd time histnum
   cmd=$(HISTTIMEFORMAT='<%s>' history 1)
   histnum=$((${cmd%%[<*]*}))
   time=${cmd%%>*}
   time=${time#*<}
   cmd=${cmd#*>}
   case $cmd in
     (rm\ *|mv\ *|...)
       history -d "$histnum" # delete
       HISTFILE=/dev/stdin history -r <<EOF
#$time
#$cmd
EOF
   esac
}
PROMPT_COMMAND=fixhist

Bu kez, son geçmişin zamanını kaydederiz ve geçmiş satırını geri eklemek için history -r, zaman damgasını içeren geçici bir dosyadan (burada belge) kullanırız.

Sizden fixhistönce yapılmasını istersiniz history -a; history -c; history -r. Maalesef, şu anki sürümünde eklediğimiz ekstra satırı kaydetmeyen bashbir hata var history -a. Bunun etrafında bir çalışma, bunun yerine yazmaktır:

fixhist() {
   local cmd time histnum
   cmd=$(HISTTIMEFORMAT='<%s>' history 1)
   histnum=$((${cmd%%[<*]*}))
   time=${cmd%%>*}
   time=${time#*<}
   cmd=${cmd#*>}
   case $cmd in
     (rm\ *|mv\ *|...)
       history -d "$histnum" # delete
       history -a
       [ -f "$HISTFILE" ] && printf '#%s\n' "$time" "$cmd" >> "$HISTFILE";;
     (*)
       history -a
   esac
   history -c
   history -r
}
PROMPT_COMMAND=fixhist

Bu, yorumlanan komutu izin vermek yerine HISTFILE dosyasına kendimiz eklemektir history -a.


ne yaptığını açıklar cmd=${cmd#*[0-9] }mısınız? Ve tam olarak nerede ben koymalıyız fixhistskinTenimde PROMPT_COMMAND? Şu anda zaten içeriyorPROMPT_COMMAND="history -a; history -c; history -r"
Martin Vegter

rolü HISTTIMEFORMAT=/nedir? Çoktan ayarladım export HISTTIMEFORMAT="%b-%d %H:%M ". Bu arada, kodumu içine eklediğimde $HOME/.bashrchiçbir şey olmuyor.
Martin Vegter

HISTTIMEFORMAT=/cmd'nin çıkarılmasının daha kolay olduğu historybir çıktı 123 /rm xelde etmenin sadece bir çağrısı içindir . Bu bağlamda sahte basholduğu bazı sürümlerle ilgili bir sorun vardı $HISTCMD, yeni sürümü deneyin.
Stéphane Chazelas

hala çalışmıyor. Merak ediyorum, #kodda yorum olarak hareket etmiyor .bashrcmu?
Martin Vegter

1
@MartinVegter, evet, değiştirilmiş geçmiş girişleri için, beklenmeyen geçmiş numarasından sonra bashbir ekler *. Şimdi düzeltilmelidir.
Stéphane Chazelas

11

Sorunuza tam olarak cevap vermeyeceğim, ama belki probleminize alternatif bir çözüm sunacağım.

Doğru bir şekilde anlarsam, yazarak yapabileceğiniz hatalardan endişe edersiniz, örneğin, tarihteki !rmönceki rmkomutun saklamak istediğiniz bir şeyi kaldırması durumunda.

Bu durumda, güzel bir bash seçeneği histverify. Siz shopt -s histverifyve patlama ile bir komutu hatırlarsanız !, hemen yürütülmez, ancak yürütmeye karar verebilmeniz için okuma satırına yüklenir ve bu da size düzenleme olanağı verir.

Dene:

  • Olmadan histverify:

    $ touch some_foo
    $ rm some_foo
    $ touch some_foo
    $ !rm
    rm some_foo
    $ # oooops in fact I'd've like to keep it this time
  • İle histverify:

    $ shopt -s histverify
    $ touch some_foo
    $ rm some_foo
    $ touch some_foo
    $ !rm
    $ rm some_foo <cursor here>

    Bu durumda, imleci satırın sonunda yeniden başlatmaya ya da başlatmaya veya düzenlemeye hazır hale getireceksiniz.

Bu seçeneği beğendiyseniz, şuraya koyun .bashrc:

shopt -s histverify
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.