Cronologia Bash su Linux: HISTFILE, HISTTIMEFORMAT e scorciatoie per sistemisti
Chiunque amministri sistemi #Linux passa gran parte della giornata dentro una shell, e la cronologia dei comandi (history) è probabilmente lo strument
Altro...
Chiunque amministri sistemi #Linux passa gran parte della giornata dentro una shell, e la cronologia dei comandi (history) è probabilmente lo strument
Altro...Chiunque amministri sistemi #Linux passa gran parte della giornata dentro una shell, e la cronologia dei comandi (history) è probabilmente lo strumento più usato e meno conosciuto a fondo. Sappiamo tutti premere la freccia su o lanciare Ctrl+R, ma pochi sfruttano davvero le variabili che controllano cosa viene salvato, come viene formattato e come sincronizzarlo tra più terminali aperti in contemporanea. Vediamo come portare la gestione della cronologia #Bash a un livello professionale, con configurazioni pronte per essere messe in produzione su server multi-utente.
Le variabili che governano la cronologiaBash tiene traccia dei comandi in due posti distinti: la memoria della sessione corrente e il file su disco (di default ~/.bash_history). Questa distinzione è la fonte di gran parte della confusione quando si lavora con più terminali aperti, quindi vale la pena chiarirla subito con le variabili che la controllano.
HISTSIZE e HISTFILESIZEHISTSIZE stabilisce quanti comandi restano in memoria durante la sessione attiva, mentre HISTFILESIZE determina quante righe vengono conservate nel file su disco. Sono due limiti indipendenti: si può avere una sessione “leggera” con poche centinaia di comandi in memoria ma un archivio storico molto più ampio su disco.
export HISTSIZE=10000
export HISTFILESIZE=20000Impostare un valore negativo (o vuoto) rende la cronologia illimitata: sconsigliato su sistemi condivisi, dove un file di history che cresce senza controllo può diventare un problema sia di #spazio che di sicurezza.
HISTFILEHISTFILE indica dove viene scritta la cronologia. Il default è ~/.bash_history, ma è possibile ridirigerla altrove, ad esempio per tenere una history separata per progetto o per sessioni di audit:
export HISTFILE="$HOME/.bash_history_$(date +%Y%m)"HISTTIMEFORMAT: i timestamp che quasi nessuno abilitaPer impostazione predefinita, history non mostra quando un comando è stato eseguito. Abilitare i timestamp con HISTTIMEFORMAT è probabilmente l’impostazione a più alto rapporto beneficio/sforzo di questo articolo, specialmente in fase di troubleshooting: sapere che un comando è stato lanciato tre minuti prima di un incidente è un’informazione preziosa.
export HISTTIMEFORMAT="%F %T "Con questa impostazione, history | grep nginx restituirà righe del tipo:
1042 2026-09-03 10:14:02 systemctl reload nginxUn dettaglio tecnico da tenere a mente: il timestamp viene registrato internamente come epoch Unix ad ogni comando, ma diventa visibile solo se HISTTIMEFORMAT è impostato prima che i comandi vengano eseguiti. Se lo si abilita a metà sessione, i comandi precedenti non avranno un timestamp recuperabile.
HISTCONTROL: cosa non salvareHISTCONTROL filtra cosa #entra in cronologia:
ignorespace – esclude i comandi che iniziano con uno spazio (utile per non salvare comandi con #password o token inline)
ignoredups – salta i duplicati consecutivi
ignoreboth – combina entrambi i comportamenti precedenti
erasedups – rimuove tutte le occorrenze precedenti di un comando ripetuto, non solo quelle consecutive
export HISTCONTROL=ignorebothIl trucco di ignorespace è particolarmente utile: basta digitare un comando con uno spazio iniziale (es. curl -H "Authorization: Bearer xyz..." ...) per evitare che token o credenziali finiscano nel file di history in chiaro.
HISTIGNORE: filtrare per patternHISTIGNORE permette di escludere dalla cronologia comandi ricorrenti e poco utili come ls, cd o pwd. Attenzione: i pattern ancorano l’inizio della riga e devono corrispondere all’intero comando, quindi vanno elencati esplicitamente anche gli argomenti comuni.
export HISTIGNORE="ls:ll:la:cd:cd -:pwd:exit:date:clear:history"Le opzioni della shell: histappend e histverifyDue shopt completano la configurazione di base. La prima è quasi obbligatoria su qualunque sistema con più terminali:
shopt -s histappendSenza histappend, Bash sovrascrive il file HISTFILE alla chiusura della shell con il contenuto della sessione corrente, perdendo i comandi salvati da altri terminali chiusi nel frattempo. Con histappend attivo, ogni sessione aggiunge in coda invece di sovrascrivere.
La seconda opzione utile è histverify, che intercetta le espansioni di history (come !! o !497) e le mostra sul prompt per una conferma, invece di eseguirle immediatamente:
shopt -s histverifyQuesto piccolo accorgimento evita un classico incidente: digitare !42 pensando che sia un comando innocuo e scoprire, dopo l’esecuzione, che il comando numero 42 era un rm -rf lanciato ore prima in un altro contesto.
Sincronizzare la cronologia tra terminali multipliPer chi lavora con molte finestre o sessioni tmux/screen aperte in parallelo, il comportamento di default di Bash è frustrante: ogni shell scrive la propria history solo alla chiusura, quindi i comandi digitati in un terminale non sono visibili negli altri finché non li si chiude esplicitamente.
La soluzione è agganciare la scrittura e la ricarica della history a PROMPT_COMMAND, che Bash esegue prima di ogni visualizzazione del prompt:
PROMPT_COMMAND="history -a; history -c; history -r${PROMPT_COMMAND:+; $PROMPT_COMMAND}"Scomponendo la sequenza:
history -a – accoda immediatamente su disco i nuovi comandi della sessione
history -c – svuota la lista in memoria della sessione corrente
history -r – ricarica in memoria l’intero file, inclusi i comandi scritti da altre sessioni
Il risultato: la freccia su e Ctrl+R attingono a una cronologia condivisa e aggiornata quasi in tempo reale tra tutti i terminali aperti. Il costo è un piccolo overhead ad ogni prompt, generalmente trascurabile salvo file di history molto grandi; in quel caso è preferibile una variante più leggera con history -n, che #legge solo le righe nuove invece di ricaricare l’intero file:
PROMPT_COMMAND="history -a; history -n${PROMPT_COMMAND:+; $PROMPT_COMMAND}"Comandi di gestione della historyOltre alle variabili di ambiente, il builtin history offre diverse operazioni utili in amministrazione quotidiana:
Mostra tutta la cronologia con numerazione
history
Ultimi 20 comandi
history 20
Cerca nella cronologia
history | grep nginx
Scrive subito su disco la sessione corrente
history -a
Elimina una riga specifica dalla memoria (es. riga 497)
history -d 497
Elimina e persiste la rimozione sul file
history -d 497 && history -w
Svuota completamente memoria e file
history -c && history -wPer disabilitare temporaneamente la registrazione, ad esempio prima di digitare una password su un comando che non supporta variabili d’ambiente:
set +o history
comandi non registrati qui
set -o historyLe scorciatoie da tastiera che valgono la pena imparareOltre al classico Ctrl+R per la ricerca incrementale, Bash espone un intero linguaggio di espansione della history, largamente sotto-utilizzato:
ScorciatoiaFunzione!!Ripete l’ultimo comando!$Ultimo argomento del comando precedente!^Primo argomento del comando precedente!*Tutti gli argomenti del comando precedente!NEsegue il comando numero N!stringaUltimo comando che inizia con “stringa”!stringa:pMostra il comando senza eseguirlo (preview)^vecchio^nuovoSostituisce e rilancia l’ultimo comandoAlt+.Richiama ciclicamente l’ultimo argomento dei comandi precedenti!$ in particolare è utile più spesso di quanto sembri: dopo mkdir /var/log/miaapp, digitare cd !$ evita di riscrivere il percorso.
Ricerca interattiva avanzata con fzfPer chi trova Ctrl+R limitante, fzf lo sostituisce con un fuzzy finder interattivo molto più potente:
sudo apt install fzf # Debian/Ubuntu
eval "$(fzf --bash)" # da aggiungere a ~/.bashrcUna volta configurato, Ctrl+R apre un filtro interattivo con evidenziazione live: premendo Invio la prima volta il comando viene incollato sul prompt (non eseguito), permettendo di modificarlo prima del lancio effettivo.
Sicurezza: la history non è un controllo, è un logAlcuni punti da tenere presenti quando si gestiscono cronologie su sistemi condivisi o in produzione:
Il file di history dovrebbe avere permessi restrittivi: chmod 600 ~/.bash_history
ignorespace nasconde un comando dalla history solo se lo spazio iniziale viene digitato manualmente: non è un meccanismo automatico
File di history su NFS o directory sincronizzate (Dropbox, syncthing, ecc.) possono esporre comandi sensibili a più host
La cronologia è auditabile dall’utente stesso ma non è un controllo di sicurezza: chiunque abbia accesso alla shell può disabilitarla con set +o history o cancellarla
Per un audit trail affidabile in produzione, la history di Bash va affiancata (non sostituita) da strumenti dedicati come auditd o da logging centralizzato della sessione shell
Configurazione completa consigliataRiassumendo tutto quanto visto in un blocco pronto per ~/.bashrc:
Configurazione History Bash
HISTSIZE=10000
HISTFILESIZE=20000
HISTTIMEFORMAT="%F %T "
HISTCONTROL=ignoreboth
HISTIGNORE="ls:ll:la:cd:cd -:pwd:exit:date:clear:history"
shopt -s histappend
shopt -s histverify
Sincronizza la cronologia tra terminali dopo ogni comando
PROMPT_COMMAND="history -a; history -c; history -r${PROMPT_COMMAND:+; $PROMPT_COMMAND}"Dopo averla incollata, applicarla con:
source ~/.bashrcConclusioneLa cronologia di Bash è uno di quegli strumenti che si usano per anni senza mai configurarli davvero. Pochi minuti spesi su HISTTIMEFORMAT, HISTCONTROL e la sincronizzazione via PROMPT_COMMAND trasformano un log grezzo e volatile in uno strumento di troubleshooting affidabile, specialmente su server dove si lavora regolarmente da più sessioni contemporanee. Per chi gestisce ambienti multi-utente, vale la pena ricordare che la history resta comunque uno strumento lato client: per l’audit reale servono log centralizzati indipendenti dalla volontà dell’utente.
Fonte originale: Master Linux Bash History with historyctl, HISTFILE, and Shortcuts – LinuxBlog.io