bash_history: commenta comandi pericolosi: `#`


16

Per impedire la registrazione di comandi "pericolosi" nella cronologia di bash, ho aggiunto la seguente riga al mio .bashrcfile:

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

funziona bene, ma ha un effetto collaterale: non riesco a vedere la cronologia completa dei comandi eseguiti su una macchina. Diciamo che ho diverse macchine per esperimenti e voglio essere in grado di vedere tutti i comandi eseguiti. Vorrei usare il bash interno historyper visualizzare i comandi eseguiti, e forse grep per la data di oggi:

history | grep Sep-28

Quello che vorrei avere è di registrare anche comandi "pericolosi", ma mettere un #all'inizio della riga, in modo che se per caso eseguo il comando dalla storia per errore, non verrebbe fatto alcun danno.

Non ho idea se questo sia possibile.

Aggiornamento e chiarimenti:

Il motivo principale per cui questo è un problema per me è che di solito sono collegato alla mia macchina da più terminali e qualsiasi comando eseguito su un terminale viene immediatamente letto nella storia di altri terminali. Questo è raggiunto da

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

Immaginiamo di avere due terminali aperti. In uno ho qualche cat /dev/foo > file.outprocesso in esecuzione. Nel secondo, controllo i progressi con ls -lAhF. Continuo a ripetere lspremendo Upe ENTER(ovvero l'ultimo comando dalla cronologia). Non appena termina il primo comando, l'ultimo comando della cronologia non è più ls, ma cat /dev/foo > file.out. Se non sto attento, ricomincio cat e sovrascrivo file.out.

Quello che vorrei ottenere è che il comando cat sarebbe preceduto da a #, in modo che non venisse eseguito. Tuttavia, lo vedrei ancora nella storia e posso riutilizzarlo (se è un comando lungo) annullandolo dal commento.


Invece di ripetere manualmente il comando, puoi usare watch ls -lAhFo while sleep 1; do ls -lAhf; done; invece di guardare le dimensioni del file, puoi usare pv /dev/foo > file.out( ivarch.com/programs/pv.shtml ).
deltab,

Risposte:


9

Potresti fare qualcosa del tipo:

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

L'idea è che prima di ogni prompt, controlliamo l'ultima voce della cronologia ( history 1) e se è una delle pericolose , la cancelliamo ( history -d) e la aggiungiamo di nuovo con un #con history -s.

(ovviamente, è necessario rimuovere le HISTIGNOREimpostazioni).

Un effetto collaterale indesiderato di ciò è che altera il tempo della storia di questi rm, mv... comandi.

Per risolvere ciò, un'alternativa potrebbe essere:

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

Questa volta, registriamo l'ora dell'ultima cronologia e per aggiungere nuovamente la riga della cronologia, utilizziamo history -rda un file temporaneo (il documento qui) che include il timestamp.

Vorresti che fixhistfosse eseguito prima del tuo history -a; history -c; history -r. Sfortunatamente, la versione corrente di bashha un bug che history -anon salva quella linea aggiuntiva che abbiamo aggiunto. Una soluzione è scrivere invece:

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

Cioè per aggiungere noi stessi il comando commentato al HISTFILE invece di lasciarlo history -afare.


puoi per favore spiegare cosa cmd=${cmd#*[0-9] }fa? E dove dovrei inserire esattamente il fixhistmio PROMPT_COMMAND? Al momento, contiene giàPROMPT_COMMAND="history -a; history -c; history -r"
Martin Vegter,

qual è il ruolo di HISTTIMEFORMAT=/? Ho già impostato export HISTTIMEFORMAT="%b-%d %H:%M ". A proposito, quando aggiungo il tuo codice nel mio $HOME/.bashrc, non succede nulla.
Martin Vegter,

HISTTIMEFORMAT=/è solo per quella invocazione di historyottenere un output come 123 /rm xdove è più facile estrarre il cmd. Si è verificato un problema con alcune versioni di bashdove $HISTCMDera falso in quel contesto, prova la nuova versione.
Stéphane Chazelas,

continua a non funzionare. Mi chiedo, #nel codice non fungono da commenti in .bashrc?
Martin Vegter,

1
@MartinVegter, sì, per le voci della cronologia modificate , bashinserisce un *numero di cronologia non previsto. Ora dovrebbe essere risolto.
Stéphane Chazelas,

11

Non risponderò esattamente alla tua domanda, ma forse ti darò una soluzione alternativa al tuo problema.

Se capisco correttamente, ti preoccupi degli errori che potresti fare digitando, ad esempio, !rmse è accaduto che il rmcomando precedente nella cronologia rimuova qualcosa che vorresti conservare.

In questo caso, è una bella opzione bashhistverify . Se si shopt -s histverify, e se si richiama un comando con il botto !, non verrà eseguito immediatamente, ma verrà caricato nella readline in modo che sia possibile decidere di eseguirlo o meno, e ciò dà anche la possibilità di modificarlo.

Provalo:

  • Senza 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
  • Con histverify:

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

    In questo caso avrai il cursore alla fine della riga, pronto per avviarlo di nuovo - o no - o per modificarlo.

Se ti piace questa opzione, inseriscila nel tuo .bashrc:

shopt -s histverify
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.