Conserva la cronologia di bash in più finestre del terminale


525

Ho costantemente più di un terminale aperto. Ovunque da due a dieci, facendo vari bit e bob. Ora diciamo che riavvio e apro un altro set di terminali. Alcuni ricordano certe cose, altri dimenticano.

Voglio una storia che:

  • Ricorda tutto da ogni terminale
  • È immediatamente accessibile da ogni terminale (ad es. Se io lsin uno, passo a un altro terminale già in esecuzione e poi premo su, si lspresenta)
  • Non dimentica il comando se ci sono spazi nella parte anteriore del comando.

Qualcosa che posso fare per far funzionare Bash in questo modo?


57
Posso vederne il vantaggio, ma personalmente lo oderei nella mia shell. Di solito tengo 3 o 4 schede aperte nel mio terminale per usi molto specifici: una per eseguire 'make', una con vi, una per eseguire roba, ecc. Quindi quando compilo, vado alla scheda 1, accendo e 'make 'arriva, e così via. Questo è estremamente produttivo per me. Quindi se improvvisamente vado alla mia scheda 'make' e colpisco e compare un comando grep casuale, mi farei davvero incazzare! Solo una nota personale
axel_c,

4
@axel_c è abbastanza vero. Non riesco a pensare a un modo intelligente per farlo in cui i terminali esistenti vedono solo la propria storia, ma quelli nuovi vedono un elenco cronologicamente accurato di comandi.
Oli,

8
@Oli ha scritto: "Non riesco a pensare a un modo intelligente per farlo in cui i terminali esistenti vedono solo la propria storia, ma quelli nuovi vedono un elenco cronologicamente accurato di comandi". Che ne dite di (non provato): export PROMPT_COMMAND="history -a; $PROMPT_COMMAND". Le shell esistenti aggiungeranno ogni comando al file della cronologia affinché le nuove shell possano vederle, ma mostreranno solo le proprie storie.
Chris Page

2
Vuoi che la cronologia sia archiviata separatamente o unita in un unico file cronologico?
kbyrd,

3
La risposta breve è: non è pensata dagli sviluppatori bash. Le soluzioni basate sul flushing e sulla rilettura della storia probabilmente funzionano, ma attenzione a Shlemiel The Painter . In parole povere: la quantità di lavoro di elaborazione tra ciascun comando è proporzionale alla dimensione della cronologia.
Stéphane Gourichon,

Risposte:


328

Aggiungi quanto segue a ~ / .bashrc

# Avoid duplicates
export HISTCONTROL=ignoredups:erasedups  
# When the shell exits, append to the history file instead of overwriting it
shopt -s histappend

# After each command, append to the history file and reread it
export PROMPT_COMMAND="${PROMPT_COMMAND:+$PROMPT_COMMAND$'\n'}history -a; history -c; history -r"

20
Il problema con questa soluzione PROMPT_COMMAND è che i numeri per ogni elemento della cronologia cambiano dopo ogni comando :(. Ad esempio se si digita la cronologia e 1) ls 2) rm, quindi si fa! 1 per ripetere 1, il numero di cronologia potrebbe cambiare e potrebbe eseguire il comando rm ...
Chris Kimpton il

2
Quando lo faccio, altri terminali già aperti non hanno l'ultimo comando inserito quando premo 'Su' fino a quando non ho emesso un comando in quel terminale - è previsto? In tal caso, c'è un modo per modificare veramente la storia di altri terminali all'istante?
Suan,

7
@Suan, questo mi sembra giusto in base ai comandi. Ho scoperto che possiamo emettere un comando null (basta premere il tasto Invio) per ottenere l'aggiornamento della cronologia.
salvia,

3
In realtà history -a(...) non si avvia la cancellazione dei duplicati in base a questa risposta alla domanda Bash history: "ignoredups" e "erasedups" creano conflitti con la cronologia comune tra le sessioni . Questa risposta fornisce anche la sequenza di history -<option>comandi che funziona con l' HISTCONTROL=ignoredups:erasedupsimpostazione.
Piotr Dobrogost,

23
Non vi è alcun motivo per exportle variabili HISTCONTROLe PROMPT_COMMAND: le state definendo in .bashrcmodo che vengano definite in ogni shell (anche in quelle non interattive, che è anche dispendiosa).
dolmen,

248

Quindi, questa è tutta la mia .bashrccosa legata alla storia :

export HISTCONTROL=ignoredups:erasedups  # no duplicate entries
export HISTSIZE=100000                   # big big history
export HISTFILESIZE=100000               # big big history
shopt -s histappend                      # append to history, don't overwrite it

# Save and reload the history after each command finishes
export PROMPT_COMMAND="history -a; history -c; history -r; $PROMPT_COMMAND"

Testato con bash 3.2.17 su Mac OS X 10.5, bash 4.1.7 su 10.6.


3
Hmm .. Questo uccide la possibilità di usare $! 34, poiché i numeri dei comandi cambiano ogni prompt. C'è una soluzione alternativa @Davide @Schof @kch?

5
Usa questo per ottenere una storia infinita: colpisci la storia eterna . TUTTAVIA, questo è complementare al codice sopra, poiché non verrà ricaricato automaticamente.

7
Cordiali saluti Nessuna delle soluzioni menzionate qui può risolvere il seguente problema. Ho due finestre shell A e B. Nella finestra shell A, corro sleep 9999e (senza aspettare che finisca il sonno) nella finestra shell B, voglio essere in grado di vedere sleep 9999nella cronologia bash.
punti

1
Anche io puntavo a comportamenti dal vivo, ma poi ho capito che è più conveniente avere storie specifiche per terminali che rendono più semplice lavorare su cose diverse in terminali diversi. Ho trovato questo molto utile: stackoverflow.com/questions/338285/#answer-7449399 Sulla base di questo, mi sono fatto un alias chiamato hrefche aggiorna istantaneamente la cronologia del mio terminale corrente e pulisce il file della cronologia nel processo. Ogni volta che apro un nuovo terminale, la pulizia / sincronizzazione viene eseguita nel mio file bashrc in modo che il nuovo terminale abbia la cronologia più recente. Lo sto usando insieme ahistory -a
trusktr il

6
Non vi è alcun motivo per exportle variabili: le si sta definendo in .bashrcmodo che vengano definite in ogni shell (anche in quelle non interattive, che è anche dispendiosa)
dolmen

117

Ecco il mio tentativo di condivisione della cronologia delle sessioni di Bash. Ciò consentirà la condivisione della cronologia tra le sessioni bash in modo che il contatore della cronologia non venga confuso e l'espansione della cronologia come !numberfunzionerà (con alcuni vincoli).

Utilizzo di Bash versione 4.1.5 in Ubuntu 10.04 LTS (Lucid Lynx).

HISTSIZE=9000
HISTFILESIZE=$HISTSIZE
HISTCONTROL=ignorespace:ignoredups

_bash_history_sync() {
    builtin history -a         #1
    HISTFILESIZE=$HISTSIZE     #2
    builtin history -c         #3
    builtin history -r         #4
}

history() {                  #5
    _bash_history_sync
    builtin history "$@"
}

PROMPT_COMMAND=_bash_history_sync

Spiegazione:

  1. Aggiungi la riga appena inserita al $HISTFILE(impostazione predefinita è .bash_history). Ciò farà $HISTFILEcrescere di una riga.

  2. Impostando la variabile speciale $HISTFILESIZEsu un certo valore, il troncamento $HISTFILEdi Bash non sarà più lungo delle $HISTFILESIZErighe rimuovendo le voci più vecchie.

  3. Cancella la cronologia della sessione in esecuzione. Ciò ridurrà il contatore della cronologia della quantità di $HISTSIZE.

  4. Leggi i contenuti $HISTFILEe inseriscili nella cronologia della sessione corrente. questo aumenterà il contatore della cronologia della quantità di righe in $HISTFILE. Si noti che il conteggio delle righe $HISTFILEnon è necessariamente $HISTFILESIZE.

  5. La history()funzione sovrascrive la cronologia incorporata per assicurarsi che la cronologia sia sincronizzata prima che venga visualizzata. Ciò è necessario per l'espansione della cronologia in base al numero (ne parleremo più avanti).

Più spiegazione:

  • Il passaggio 1 garantisce che il comando della sessione in esecuzione corrente venga scritto nel file della cronologia globale.

  • Il passaggio 4 garantisce che i comandi delle altre sessioni vengano letti nella cronologia della sessione corrente.

  • Poiché il passaggio 4 aumenterà il contatore della cronologia, dobbiamo ridurre il contatore in qualche modo. Questo viene fatto al punto 3.

  • Nel passaggio 3 il contatore della cronologia è ridotto di $HISTSIZE. Nel passaggio 4 il contatore della cronologia viene aumentato del numero di righe in $HISTFILE. Nel passaggio 2 ci assicuriamo che il conteggio delle righe $HISTFILEsia esattamente $HISTSIZE(ciò significa che $HISTFILESIZEdeve essere uguale a $HISTSIZE).

Informazioni sui vincoli dell'espansione della cronologia:

Quando si utilizza l'espansione della cronologia per numero, è necessario cercare sempre il numero immediatamente prima di utilizzarlo. Ciò significa che non viene visualizzato alcun prompt bash tra la ricerca del numero e l'utilizzo. Questo di solito significa no enter e no ctrl + c.

Generalmente, una volta che hai più di una sessione Bash, non vi è alcuna garanzia che un'espansione della cronologia per numero manterrà il suo valore tra due display del prompt di Bash. Perché quando PROMPT_COMMANDviene eseguita la cronologia di tutte le altre sessioni di Bash sono integrate nella cronologia della sessione corrente. Se qualsiasi altra sessione bash ha un nuovo comando, i numeri di cronologia della sessione corrente saranno diversi.

Trovo ragionevole questo vincolo. Devo comunque cercare il numero ogni volta perché non ricordo numeri storici arbitrari.

Di solito uso l'espansione della cronologia per numero come questo

$ history | grep something #note number
$ !number

Consiglio di utilizzare le seguenti opzioni di Bash.

## reedit a history substitution line if it failed
shopt -s histreedit
## edit a recalled history line before executing
shopt -s histverify

Strani bug:

L'esecuzione del comando di cronologia inoltrato a qualsiasi cosa comporterà che tale comando venga elencato due volte nella cronologia. Per esempio:

$ history | head
$ history | tail
$ history | grep foo
$ history | true
$ history | false

Tutto sarà elencato nella storia due volte. Non ho idea del perché.

Idee per miglioramenti:

  • Modificare la funzione in _bash_history_sync()modo che non venga eseguita ogni volta. Ad esempio, non dovrebbe essere eseguito dopo un CTRL+Cprompt. Spesso uso CTRL+Cper scartare una lunga riga di comando quando decido di non voler eseguire quella riga. A volte devo usare CTRL+Cper interrompere uno script di completamento di Bash.

  • I comandi della sessione corrente dovrebbero essere sempre i più recenti nella cronologia della sessione corrente. Ciò avrà anche l'effetto collaterale che un determinato numero di cronologia mantiene il suo valore per le voci di cronologia di questa sessione.


1
Perché non "history -n" (ricaricare le righe non già caricate) invece di "history -c; history -r"?
Graham,

@Graham: non volevo usare history -nperché rovina il contatore della cronologia. Inoltre, ho trovato history -ntroppo inaffidabile.
lesmana,

1
Uno svantaggio: i comandi con stringhe multilinea sono normalmente conservati nella sessione corrente. Con questo trucco, vengono immediatamente divisi in singole righe. L'uso di -n per -c -r non aiuta, né cmdhist o lithist. Non credo che ci sia una soluzione a questo punto.
Jo Liss,

24
Dopo aver provato questo per un po ', ho effettivamente scoperto che correre solo history -a, senza -ce -r, è meglio dal punto di vista dell'usabilità (anche se non è quello che la domanda è stata posta). Significa che i comandi eseguiti sono immediatamente disponibili nelle nuove shell anche prima di uscire dalla shell corrente, ma non nelle shell in esecuzione contemporaneamente. In questo modo Arrow-Up seleziona sempre i comandi dell'ultima esecuzione della sessione corrente , che trovo molto meno confuso.
Jo Liss,

risposta eccezionalmente buona, funziona in modo affidabile a differenza della più comune "storia -a; storia -n"
RichVel

42

Non sono a conoscenza di alcun modo utilizzando bash. Ma è una delle funzionalità più popolari di zsh.
Personalmente preferisco zshsopra bashquindi vi consiglio di provarlo.

Ecco la mia parte .zshrcche tratta della storia:

SAVEHIST=10000 # Number of entries
HISTSIZE=10000
HISTFILE=~/.zsh/history # File
setopt APPEND_HISTORY # Don't erase history
setopt EXTENDED_HISTORY # Add additional data to history like timestamp
setopt INC_APPEND_HISTORY # Add immediately
setopt HIST_FIND_NO_DUPS # Don't show duplicates in search
setopt HIST_IGNORE_SPACE # Don't preserve spaces. You may want to turn it off
setopt NO_HIST_BEEP # Don't beep
setopt SHARE_HISTORY # Share history between session/terminals


16

Per fare ciò, dovrai aggiungere due righe al tuo ~/.bashrc:

shopt -s histappend
PROMPT_COMMAND="history -a;history -c;history -r;$PROMPT_COMMAND"

Da man bash:

Se l'opzione shell histappend è abilitata (vedere la descrizione di shopt sotto COMANDI INCORPORATI SHELL di seguito), le righe vengono aggiunte al file della cronologia, altrimenti il ​​file della cronologia viene sovrascritto.


10

Puoi modificare il tuo prompt BASH per eseguire "history -a" e "history -r" che Muerr ha suggerito:

savePS1=$PS1

(nel caso in cui sbagli qualcosa, che è quasi garantito)

PS1=$savePS1`history -a;history -r`

(nota che si tratta di back-tick; eseguiranno la cronologia -a e la cronologia -r su ogni prompt. Poiché non generano alcun testo, il tuo prompt rimarrà invariato.

Dopo aver impostato la variabile PS1 nel modo desiderato, impostala in modo permanente nel file ~ / .bashrc.

Se si desidera tornare al prompt originale durante il test, eseguire:

PS1=$savePS1

Ho fatto dei test di base su questo per assicurarmi che funzioni, ma non riesco a parlare di alcun effetto collaterale in esecuzione history -a;history -rsu ogni prompt.


2
La soluzione di Kch funziona meglio della mia. Ora sto usando la sua soluzione nel mio .bashrc.

9

Se hai bisogno di una soluzione di sincronizzazione della cronologia bash o zsh che risolva anche il problema di seguito, puoi vederlo su http://ptspts.blogspot.com/2011/03/how-to-automatically-synchronize-shell.html

Il problema è il seguente: ho due finestre shell A e B. Nella finestra shell A, corro sleep 9999e (senza aspettare che finisca il sonno) nella finestra shell B, voglio essere in grado di vedere sleep 9999nella cronologia bash.

Il motivo per cui la maggior parte delle altre soluzioni qui non risolve questo problema è che stanno scrivendo le loro modifiche della cronologia nel file della cronologia utilizzando PROMPT_COMMANDo PS1, entrambe le quali vengono eseguite troppo tardi, solo dopo che il sleep 9999comando è terminato.


1
Questa è una buona soluzione, ma ho alcune domande. 1. Posso usare il file .bash_history originale, non voglio che esistesse un altro file di cronologia bash nel mio $ HOME 2. Forse dovresti considerare di impostare un repository github per questo.
weynhamz,

Sembra che l'hook di debug sia in conflitto con bashdb, l'output seguente ogni volta che inizio una sessione bash. `` bash debugger, bashdb, versione 4.2-0.8 Copyright 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Rocky Bernstein Questo è un software gratuito, coperto dalla GNU General Public License, e sei il benvenuto modificarlo e / o distribuirne copie a determinate condizioni. ** Errore di debug interno _Dbg_is_file (): argomento file null bash: _Dbg_filenames [$ fullname]: pedice array
errato

@Techlive Zheng: 1. L'originale .bash_history non è deliberatamente supportato, perché .merged_bash_history utilizza un formato di file diverso, quindi nel caso in cui .merged_bash_history non si carichi correttamente, bash non bloccherà accidentalmente la storia accumulata. Robustezza dal design, sarà mantenuta così com'è. 2. Un repository github è una buona idea in generale, ma non ho tempo di mantenerlo per questo progetto, quindi non lo sto facendo. - Sì, è in conflitto con bashdb e non esiste una soluzione semplice (usano gli stessi hook). Non ho intenzione di lavorare su una correzione, ma sto accettando le patch.
Punti

Okay grazie. Ho trovato una lozione molto semplice e migliore.
weynhamz,

@TechliveZheng: vorresti condividere la tua soluzione semplice e migliore con noi, così tutti noi possiamo imparare da essa? (In caso affermativo, si prega di aggiungere una risposta alla domanda.)
pts

8

È possibile utilizzare history -aper aggiungere la cronologia della sessione corrente al file hist, quindi utilizzare history -rsugli altri terminali per leggere il file hist. 


8

Bene, quindi alla fine questo mi ha infastidito nel trovare una soluzione decente:

# Write history after each command
_bash_history_append() {
    builtin history -a
}
PROMPT_COMMAND="_bash_history_append; $PROMPT_COMMAND"

Ciò che fa è una sorta di fusione di ciò che è stato detto in questo thread, tranne per il fatto che non capisco perché ricarichi la storia globale dopo ogni comando. Mi preoccupo molto raramente di ciò che accade in altri terminali, ma eseguo sempre serie di comandi, ad esempio in un terminale:

make
ls -lh target/*.foo
scp target/artifact.foo vm:~/

(Esempio semplificato)

E in un altro:

pv ~/test.data | nc vm:5000 >> output
less output
mv output output.backup1

Non vorrei che il comando fosse condiviso


1
Il motivo per cui ricarichi la cronologia dopo ogni comando è che è il comportamento richiesto dalla domanda (e quindi questo non risponde alla domanda come posta).
Michael Homer,

2
@MichaelHomer Fair point. Sentiti libero di sottovalutare in modo che la risposta rimanga in fondo, tuttavia, lo aggiungerei al PO non rendendomi conto del cattivo comportamento richiesto e del fatto che questa è una domanda molto googlable.
Yarek T,

3
Op qui, sì, è un giusto compromesso. La mia lamentela principale è che stavo perdendo la storia. Questo dovrebbe fermarlo, anche se non significa aggiornamenti istantanei attraverso sessioni simultanee.
Oli,

7

Ecco un'alternativa che uso. È ingombrante ma risolve il problema menzionato da @axel_c in cui a volte potresti voler avere un'istanza di cronologia separata in ciascun terminale (uno per make, uno per monitoraggio, uno per vim, ecc.).

Conservo un file cronologico allegato separato che aggiorno costantemente. Ho il seguente mappato su un tasto di scelta rapida:

history | grep -v history >> ~/master_history.txt

Questo aggiunge tutta la cronologia dal terminale corrente a un file chiamato master_history.txt nella tua home directory.

Ho anche un tasto di scelta rapida separato per cercare nel file della cronologia principale:

cat /home/toby/master_history.txt | grep -i

Uso cat | grep perché lascia il cursore alla fine per entrare nella mia regex. Un modo meno brutto per farlo sarebbe quello di aggiungere un paio di script al tuo percorso per eseguire queste attività, ma i tasti di scelta rapida funzionano per i miei scopi. Inoltre periodicamente estrarrò la cronologia dagli altri host su cui ho lavorato e aggiungerò quella cronologia al mio file master_history.txt.

È sempre bello poter cercare rapidamente e trovare quella regex complicata che hai usato o quella strana perl one-liner che ti è venuta in mente 7 mesi fa.


6

Posso offrire una correzione per quest'ultima: assicurati che la variabile env HISTCONTROL non specifichi "ignorespace" (o "ignoreboth").

Ma sento il tuo dolore con più sessioni simultanee. Semplicemente non è gestito bene in Bash.


6

Ecco il mio miglioramento alla risposta di @ lesmana . La differenza principale è che le finestre simultanee non condividono la cronologia. Ciò significa che puoi continuare a lavorare nelle tue finestre, senza che il contesto di altre finestre venga caricato nelle finestre correnti.

Se si digita esplicitamente "cronologia", OPPURE se si apre una nuova finestra, si ottiene la cronologia da tutte le finestre precedenti.

Inoltre, utilizzo questa strategia per archiviare tutti i comandi mai digitati sulla mia macchina.

# Consistent and forever bash history
HISTSIZE=100000
HISTFILESIZE=$HISTSIZE
HISTCONTROL=ignorespace:ignoredups

_bash_history_sync() {
  builtin history -a         #1
  HISTFILESIZE=$HISTSIZE     #2
}

_bash_history_sync_and_reload() {
  builtin history -a         #1
  HISTFILESIZE=$HISTSIZE     #2
  builtin history -c         #3
  builtin history -r         #4
}

history() {                  #5
  _bash_history_sync_and_reload
  builtin history "$@"
}

export HISTTIMEFORMAT="%y/%m/%d %H:%M:%S   "
PROMPT_COMMAND='history 1 >> ${HOME}/.bash_eternal_history'
PROMPT_COMMAND=_bash_history_sync;$PROMPT_COMMAND

5

Ho scelto di inserire la cronologia in un file per cento, poiché più persone possono lavorare sullo stesso server: separare i comandi di ciascuna sessione semplifica il controllo.

# Convert /dev/nnn/X or /dev/nnnX to "nnnX"
HISTSUFFIX=`tty | sed 's/\///g;s/^dev//g'`
# History file is now .bash_history_pts0
HISTFILE=".bash_history_$HISTSUFFIX"
HISTTIMEFORMAT="%y-%m-%d %H:%M:%S "
HISTCONTROL=ignoredups:ignorespace
shopt -s histappend
HISTSIZE=1000
HISTFILESIZE=5000

La storia ora sembra:

user@host:~# test 123
user@host:~# test 5451
user@host:~# history
1  15-08-11 10:09:58 test 123
2  15-08-11 10:10:00 test 5451
3  15-08-11 10:10:02 history

Con i file che sembrano:

user@host:~# ls -la .bash*
-rw------- 1 root root  4275 Aug 11 09:42 .bash_history_pts0
-rw------- 1 root root    75 Aug 11 09:49 .bash_history_pts1
-rw-r--r-- 1 root root  3120 Aug 11 10:09 .bashrc

3

Qui sottolineo un problema con

export PROMPT_COMMAND="${PROMPT_COMMAND:+$PROMPT_COMMAND$'\n'}history -a; history -c; history -r"

e

PROMPT_COMMAND="$PROMPT_COMMAND;history -a; history -n"

Se esegui source ~ / .bashrc, $ PROMPT_COMMAND sarà simile

"history -a; history -c; history -r history -a; history -c; history -r"

e

"history -a; history -n history -a; history -n"

Questa ripetizione si verifica ogni volta che si esegue 'source ~ / .bashrc'. Puoi controllare PROMPT_COMMAND dopo ogni esecuzione di 'source ~ / .bashrc' eseguendo 'echo $ PROMPT_COMMAND'.

Potresti vedere alcuni comandi apparentemente non funzionanti: "history -n history -a". Ma la buona notizia è che funziona ancora, perché altre parti formano ancora una sequenza di comandi valida (comporta solo un costo aggiuntivo dovuto all'esecuzione ripetitiva di alcuni comandi. E non così pulito.)

Personalmente utilizzo la seguente versione semplice:

shopt -s histappend
PROMPT_COMMAND="history -a; history -c; history -r"

che ha la maggior parte delle funzionalità mentre non esiste un problema di questo tipo.

Un altro punto da sottolineare è: non c'è davvero nulla di magico . PROMPT_COMMAND è solo una semplice variabile d'ambiente bash. I comandi in esso vengono eseguiti prima di ottenere il prompt bash (il segno $). Ad esempio, PROMPT_COMMAND è "echo 123" e si esegue "ls" nel terminale. L'effetto è come eseguire "ls; echo 123".

$ PROMPT_COMMAND="echo 123"

output (proprio come eseguendo 'PROMPT_COMMAND = "echo 123"; $ PROMPT_COMMAND'):

123

Eseguire quanto segue:

$ echo 3

produzione:

3
123

"history -a" è usato per scrivere i comandi di cronologia in memoria su ~ / .bash_history

"history -c" è usato per cancellare i comandi di cronologia in memoria

"history -r" è usato per leggere i comandi di cronologia da ~ / .bash_history alla memoria

Vedi la spiegazione dei comandi della cronologia qui: http://ss64.com/bash/history.html

PS: Come altri utenti hanno sottolineato, l' esportazione non è necessaria. Vedi: usando export in .bashrc


2

Ho scritto uno script per impostare un file di cronologia per sessione o attività basato su quanto segue.

        # write existing history to the old file
        history -a

        # set new historyfile
        export HISTFILE="$1"
        export HISET=$1

        # touch the new file to make sure it exists
        touch $HISTFILE
        # load new history file
        history -r $HISTFILE

Non è necessario salvare tutti i comandi della cronologia, ma salva quelli a cui tengo ed è più facile recuperarli e passare attraverso ogni comando. La mia versione elenca anche tutti i file della cronologia e offre la possibilità di cercarli tutti.

Fonte completa: https://github.com/simotek/scripts-config/blob/master/hiset.sh


2

Ecco una soluzione che non confonde le storie delle singole sessioni!

Fondamentalmente si deve archiviare la cronologia di ogni sessione separatamente e ricrearla su ogni prompt. Sì, utilizza più risorse, ma non è così lento come potrebbe sembrare - il ritardo inizia a essere evidente solo se si hanno più di 100000 voci di cronologia.

Ecco la logica principale:

# on every prompt, save new history to dedicated file and recreate full history
# by reading all files, always keeping history from current session on top.
update_history () {
  history -a ${HISTFILE}.$$
  history -c
  history -r
  for f in `ls ${HISTFILE}.[0-9]* | grep -v "${HISTFILE}.$$\$"`; do
    history -r $f
  done
  history -r "${HISTFILE}.$$"
}
export PROMPT_COMMAND='update_history'

# merge session history into main history file on bash exit
merge_session_history () {
  cat ${HISTFILE}.$$ >> $HISTFILE
  rm ${HISTFILE}.$$
}
trap merge_session_history EXIT

Guarda questo riassunto per una soluzione completa, tra cui alcune garanzie e ottimizzazioni delle prestazioni.


1

Questo funziona per ZSH

##############################################################################
# History Configuration for ZSH
##############################################################################
HISTSIZE=10000               #How many lines of history to keep in memory
HISTFILE=~/.zsh_history     #Where to save history to disk
SAVEHIST=10000               #Number of history entries to save to disk
#HISTDUP=erase               #Erase duplicates in the history file
setopt    appendhistory     #Append history to the history file (no overwriting)
setopt    sharehistory      #Share history across terminals
setopt    incappendhistory  #Immediately append to the history file, not just when a term is killed

purtroppo la domanda è rigorosamente per bash :-)
Jaleks

1
è il primo risultato su Google quando cerco anche zsh ... Ho pensato che potesse essere d'aiuto
Mulki,

3
Dovresti porre una nuova domanda, ~ "Conserva la cronologia di zsh in più finestre del terminale", supponendo che uno non esista già. Va benissimo - anche incoraggiato - a rispondere alla tua domanda se è una buona domanda.
Oli,

1

Lo desideravo da molto tempo, in particolare la possibilità di recuperare un comando dal punto in cui era stato eseguito per rieseguirlo in un nuovo progetto (o trovare una directory tramite un comando). Quindi ho messo insieme questo strumento , che combina le precedenti soluzioni per la memorizzazione di una cronologia CLI globale con uno strumento di grepping interattivo chiamato percol (mappato su C ^ R). È ancora perfetto sulla prima macchina che ho iniziato a usarlo, ora con una cronologia della CLI di 2 anni.

Non interferisce con la cronologia CLI locale per quanto riguarda i tasti freccia, ma consente di accedere facilmente alla cronologia globale (che è anche possibile mappare a qualcosa di diverso da C ^ R)


questo è per zsh?
sabato

1
sì, inizialmente l'ho fatto per zsh. Ha funzionato anche per bash e pesce. Fammi sapere se funziona o no. Non l'ho cambiato da un po 'e non sono sicuro di quanto sia stato chiaro nelle mie istruzioni di installazione
Gordon Wells,

1

Perché preferisco la storia infinita che è stata salvata nel file personalizzato. Creo questa configurazione basata su https://stackoverflow.com/a/19533853/4632019 :

export HISTFILESIZE=
export HISTSIZE=
export HISTTIMEFORMAT="[%F %T] "

export HISTFILE=~/.bash_myhistory
PROMPT_COMMAND="history -a; history -r; $PROMPT_COMMAND"

-1

Ecco lo snippet del mio .bashrc e brevi spiegazioni dove necessario:

# The following line ensures that history logs screen commands as well
shopt -s histappend

# This line makes the history file to be rewritten and reread at each bash prompt
PROMPT_COMMAND="$PROMPT_COMMAND;history -a; history -n"
# Have lots of history
HISTSIZE=100000         # remember the last 100000 commands
HISTFILESIZE=100000     # start truncating commands after 100000 lines
HISTCONTROL=ignoreboth  # ignoreboth is shorthand for ignorespace and     ignoredups

HISTFILESIZE e HISTSIZE sono preferenze personali e puoi modificarle secondo i tuoi gusti.

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.