Come salvare la cronologia dei terminali in un file da un file bash?


7

Sto cercando di creare uno script bash che salverà la cronologia del terminale in un file chiamato hist.txt. L'uso history > hist.txtnon sembra funzionare nello script bash, ma funziona bene quando eseguito nella riga di comando.

Qualsiasi consiglio è molto apprezzato.

Grazie Judy


3
La tua domanda è un po 'confusa. Cosa intendi con "non sembra funzionare nel file bash, ma funziona bene quando eseguito nella riga di comando"? Vuoi dire che stai cercando di salvare la cronologia dei tuoi comandi all'interno di uno script bash in esecuzione? Come vorresti salvare quali comandi sono stati eseguiti dallo script? La sceneggiatura stessa è una storia in questo caso.
Stephen,

6
O desideri visualizzare la cronologia bash di un determinato utente? Potresti semplicemente leggere il ~/.bash_historyfile dell'utente .
Arronical,

1
@Arronical nota che questo funzionerà solo se l'utente sta usando Bash come shell, il che non è sempre il caso.

1
@ p0llard Certo, ho fatto un salto nel presupposto che, come in uno script Bash, sarebbe Bash come shell dell'utente, ma potrebbe non essere il caso, come hai detto. Buoni dettagli e background nella tua risposta BTW.
Arronical,

Risposte:


11

Risposta breve

Esegui lo script con sourceo .:

source ./script_name.sh

o

. ./script_name.sh

Quest'ultimo è leggermente più compatibile tra diverse shell.

Risposta lunga

Questa domanda evidenzia un punto importante, ovvero che gli script della shell vengono eseguiti nel proprio contesto. Per vedere cosa significa, considera il seguente script di shell:

#!/bin/bash

cd /
ls

Se lo esegui, otterrai un output simile al seguente:

bin  boot  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

Noterai che dopo aver eseguito lo script, sarai ancora in qualunque directory ti trovassi prima di eseguirlo: l' cd /interno dello script non ha effettivamente influenzato la tua sessione - ha influenzato solo il contesto in cui era in esecuzione lo script, che viene creato per l'esecuzione dello script e distrutto una volta restituito.

Il sourcecomando 'leggerà ed eseguirà i comandi dall'argomento nomefile nel contesto della shell corrente', quindi qualsiasi comando come cdal suo interno influenzerà la sessione corrente. Se dovessi eseguire lo script sopra passandolo a sourcete scopriresti che finirai nella directory root dopo che è stato eseguito.

In questo caso, il problema è che il historycomando fornisce la cronologia per l'attuale contesto della shell; il contesto shell in cui viene eseguito lo script senza utilizzare sourcenon ha cronologia, quindi non scrive nulla nel file di output. Se lo usi source, verrà eseguito nel contesto corretto e funzionerà come previsto.

NB: sourceè una shell integrata, non un programma in - in Bash, sourceè sinonimo di ., ma in alcune shell funziona solo .- ho usato sourcein questa risposta perché è più facile da leggere di ., ma per la massima compatibilità, .dovrebbe essere usato.


Lettura molto interessante. Mi sono sempre chiesto quali siano i comandi di cronologia "mancanti", ora so perché. Grazie!
Tico,

10

Prima di tutto, nota che la tua cronologia è già in un file. Se stai eseguendo bash, il suo nome è di solito ~/.bash_history. Più specificamente, è qualunque cosa tu abbia impostato la variabile HISTFILE. Se vuoi copiarlo in un altro file, eseguicat "$HISTFILE" > hist.txt

Ora, il motivo per cui il historycomando non funziona in uno script di shell bash, è perché gli script vengono eseguiti in una shell figlio non interattiva della sessione di shell corrente. Le shell secondarie non ereditano tutto l'ambiente del genitore (quindi non tutte le variabili impostate), ma solo le variabili che sono state esportate. Per illustrare, lo script seguente farà eco al valore della variabile $var:

#!/bin/bash
echo "$var"

Ora, imposta $varsu qualcosa ed esegui lo script:

$ var="foo"
$ foo.sh
VAR: 

Quindi, esportare prima la variabile:

$ var="foo"
$ export var
$ foo.sh
VAR: foo

Come puoi vedere, quando la variabile è stata esportata, è disponibile per le shell secondarie.

Come ho detto prima, la cronologia è memorizzata nel file a cui punta la variabile $HISTFILENAME. Poiché ciò non viene esportato per impostazione predefinita, non è impostato durante l'esecuzione di uno script:

$ cat foo.sh
#!/bin/bash
echo "HISTFILE: $HISTFILE"
$ ./foo.sh
HISTFILE:
$ echo $HISTFILE
/home/terdon/.bash_history

Come puoi vedere nell'esempio sopra, la variabile HISTFILEè impostata nella mia normale sessione di shell, ma è vuota quando eseguo lo script.

Quindi, per ottenere la cronologia, hai alcune opzioni:

  1. Il HISTFILEvalore predefinito è $HOME/.bash_history. Se non l'hai modificato, puoi semplicemente eseguire questo comando nel tuo script:

    cat "$HOME/.bash_history" > history
  2. Puoi passare la $HISTFILEvariabile al tuo script e catche:

    #!/bin/bash
    cat "$1" > history

    Salvare quanto sopra foo.shed eseguire in questo modo:

    ./foo.sh "$HISTORY"
  3. Assicurarsi che la variabile sia esportata. Aggiungi questa riga ai tuoi file ~/.bash_profile(se esiste) o ~/.profile(se ~/.bash_profilenon esiste):

    export HISTFILE

    Quindi, disconnettersi e riconnettersi e si dovrebbe essere in grado di eseguire history > hist.txtda uno script come previsto. Questo perché export VARsignifica "rendere $ VAR disponibile per le shell secondarie". In termini pratici, ciò significa che il valore di HISTFILEsarà ereditato dalla shell non interattiva utilizzata per eseguire lo script.

    Ora, mentre il HISTFILEset sarà impostato, non è stato letto dalla shell che esegue lo script. Quindi, per farlo funzionare, dovresti history -rprima leggerlo . L'intero script sarebbe simile al seguente:

    $!/bin/bash
    history -r
    history > hist.txt

    In alternativa, esportalo manualmente prima di eseguire lo script:

    $ export HISTFILE

    Ma dovrai ancora farlo history -rnella sceneggiatura.

  4. Puoi sourcefarlo come suggerito dalla risposta di @ p0llard .

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.