Vai al contenuto principale

#bash

Cronologia Bash su Linux: HISTFILE, HISTTIMEFORMAT e scorciatoie per sistemisti

Chiunque amministri sistemi passa gran parte della giornata dentro una shell, e la cronologia dei comandi (history) è probabilmente lo strument

Altro...

Chiunque amministri sistemi 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 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 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 in cronologia:

ignorespace – esclude i comandi che iniziano con uno spazio (utile per non salvare comandi con 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 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

#linux #guide #howto #tutorial #bash

0

Caricamento...

0
1

Caricamento...