bash_history: komentar perintah berbahaya: `#`


16

Untuk mencegah masuknya perintah "berbahaya" dalam sejarah bash, saya telah menambahkan baris berikut ke .bashrcfile saya :

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

ini bekerja dengan baik, tetapi memiliki efek samping: Saya tidak dapat melihat riwayat lengkap perintah yang dijalankan pada mesin. Katakanlah saya memiliki beberapa mesin untuk percobaan, dan saya ingin dapat melihat semua perintah dieksekusi. Saya akan menggunakan bash internal historyuntuk menampilkan perintah yang dieksekusi, dan mungkin grep untuk tanggal hari ini:

history | grep Sep-28

Apa yang ingin saya miliki adalah mencatat perintah "berbahaya" juga, tetapi letakkan #di awal baris, sehingga jika saya mengeksekusi perintah secara tidak sengaja, tidak ada kerusakan yang akan terjadi.

Saya tidak tahu apakah ini mungkin.

Pembaruan dan klarifikasi:

Alasan utama mengapa ini menjadi masalah bagi saya adalah bahwa saya biasanya terhubung ke mesin saya dari beberapa terminal, dan perintah apa pun yang dijalankan pada satu terminal segera dibaca ke dalam sejarah terminal lain. Ini dicapai oleh

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

Bayangkan saya memiliki dua terminal terbuka. Dalam satu saya menjalankan beberapa cat /dev/foo > file.outproses. Di bagian kedua, saya memeriksa perkembangannya ls -lAhF. Saya terus mengulangi lsdengan menekan Updan ENTER(yaitu, perintah terakhir dari sejarah). Segera setelah perintah pertama selesai, perintah terakhir dari history tidak lagi ls, tetapi cat /dev/foo > file.out. Jika saya tidak hati-hati, saya akan mulai cat lagi dan menimpa file.out.

Yang ingin saya capai adalah bahwa perintah cat akan didahului dengan #, sehingga tidak akan dieksekusi. Saya akan, bagaimanapun, masih melihatnya dalam sejarah dan dapat menggunakannya kembali (jika itu adalah perintah yang panjang) dengan tidak berkomentar.


Alih-alih mengulangi perintah Anda secara manual, Anda dapat menggunakan watch ls -lAhFatau while sleep 1; do ls -lAhf; done; alih-alih menonton ukuran file, Anda dapat menggunakan pv /dev/foo > file.out( ivarch.com/programs/pv.shtml ).
deltab

Jawaban:


9

Anda dapat melakukan sesuatu seperti:

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

Idenya adalah bahwa sebelum setiap prompt, kami memeriksa entri riwayat terakhir ( history 1) dan jika itu salah satu yang berbahaya , kami menghapusnya ( history -d) dan menambahkannya kembali dengan #with history -s.

(jelas, Anda perlu menghapus HISTIGNOREpengaturan Anda ).

Efek samping yang tidak diinginkan dari itu adalah bahwa itu mengubah waktu sejarah mereka rm, mv... perintah.

Untuk memperbaikinya, sebuah alternatif bisa berupa:

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

Kali ini, kami mencatat waktu riwayat terakhir, dan untuk menambah kembali baris riwayat, kami menggunakan history -rdari file sementara (dokumen di sini) yang menyertakan stempel waktu.

Anda ingin fixhisttampil sebelum Anda history -a; history -c; history -r. Sayangnya, versi bashbug saat history -aini tidak menyimpan baris tambahan yang telah kami tambahkan. Sebagai gantinya adalah menulisnya:

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

Itu adalah untuk menambahkan sendiri perintah yang sudah dikomentari ke HISTFILE daripada membiarkannya history -amelakukannya.


dapatkah Anda jelaskan apa cmd=${cmd#*[0-9] }fungsinya? Dan di mana tepatnya saya harus meletakkan fixhistdi PROMPT_COMMAND? Saat ini, sudah berisiPROMPT_COMMAND="history -a; history -c; history -r"
Martin Vegter

apa perannya HISTTIMEFORMAT=/? Saya sudah mengatur export HISTTIMEFORMAT="%b-%d %H:%M ". By the way, ketika saya menambahkan kode Anda ke saya $HOME/.bashrc, tidak ada yang terjadi.
Martin Vegter

HISTTIMEFORMAT=/hanya untuk satu permintaan historyuntuk mendapatkan output seperti di 123 /rm xmana lebih mudah untuk mengekstrak cmd. Ada masalah dengan beberapa versi di bashmana $HISTCMDpalsu dalam konteks itu, coba versi baru.
Stéphane Chazelas

masih tidak berfungsi. Saya bertanya-tanya, apakah #kode tidak bertindak sebagai komentar .bashrc?
Martin Vegter

1
@MartinVegter, ya, untuk dimodifikasi entri sejarah, bashmenyisipkan *setelah jumlah sejarah yang tidak diharapkan. Harus diperbaiki sekarang.
Stéphane Chazelas

11

Saya tidak akan menjawab pertanyaan Anda dengan tepat, tetapi mungkin memberi Anda solusi alternatif untuk masalah Anda.

Jika saya mengerti benar Anda khawatir tentang kesalahan yang bisa Anda buat dengan mengetik, misalnya, !rmjika itu terjadi bahwa rmperintah sebelumnya dalam sejarah menghapus sesuatu yang ingin Anda simpan.

Dalam hal ini, opsi bash yang bagus adalah histverify. Jika Anda shopt -s histverify, dan jika Anda ingat perintah dengan bang! , itu tidak akan segera dieksekusi, tetapi dimuat di readline sehingga Anda dapat memutuskan untuk mengeksekusinya atau tidak, dan ini juga memberi Anda kemungkinan untuk mengeditnya.

Cobalah:

  • Tanpa 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
  • Dengan histverify:

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

    Dalam hal ini Anda akan memiliki kursor di akhir baris, siap untuk meluncurkannya lagi - atau tidak - atau mengeditnya.

Jika Anda menyukai opsi ini, letakkan di .bashrc:

shopt -s histverify
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.