15%

Économisez 15% sur tous les services d'hébergement

Testez vos compétences et obtenez Réduction sur tout plan d'hébergement

Utilisez le code :

Skills
Commencer
09.10.2024

La commande `history` sous Linux : Guide complet de l’historique Bash

La commande `history` sous Linux est un utilitaire intégré du shell Bash qui enregistre, affiche et gère chaque commande exécutée dans une session de terminal. Elle lit et écrit dans `~/.bash_history`, un fichier texte brut dans le répertoire personnel de chaque utilisateur, vous permettant de rappeler, rechercher, réexécuter et auditer des commandes entre les sessions sans les retaper.

Pour les administrateurs système et les utilisateurs avancés, l’historique Bash n’est pas simplement une fonctionnalité pratique — c’est une piste d’audit opérationnelle, un outil de débogage et un multiplicateur de productivité. Comprendre son fonctionnement interne, ses variables de configuration et ses implications en matière de sécurité distingue les utilisateurs occasionnels des ingénieurs qui tirent le maximum de valeur de la ligne de commande.

Fonctionnement interne de l’historique Bash

Lorsque vous ouvrez une session de terminal, Bash charge le contenu de `~/.bash_history` dans une liste en mémoire. Au fur et à mesure que vous exécutez des commandes, elles sont ajoutées à ce tampon en mémoire. Lorsque la session se ferme normalement (via `exit` ou `logout`), le tampon est réécrit dans `~/.bash_history` selon les règles définies par vos variables d’environnement.

Cette architecture a une implication critique : si votre session se termine anormalement (coupure de courant, déconnexion SSH, `kill -9`), les commandes de cette session peuvent ne jamais être écrites sur le disque. C’est une source fréquente de confusion lorsque les administrateurs perdent la trace des commandes exécutées lors d’une session interrompue.

Deux options du shell modifient ce comportement d’écriture par défaut à la fermeture :

  • `shopt -s histappend` — ajoute le nouvel historique à `~/.bash_history` au lieu de l’écraser. Ceci est essentiel dans les environnements multi-sessions.
  • `PROMPT_COMMAND='history -a'` — force Bash à ajouter la dernière commande au fichier d’historique après chaque invite, permettant une persistance en temps réel et une visibilité entre les terminaux.

Sans `histappend`, le dernier shell à se fermer l’emporte — il écrase le fichier d’historique, supprimant silencieusement les entrées de toutes les autres sessions simultanées.

Utilisation de base de la commande `history`

Afficher l’historique complet des commandes

“`bash

history

“`

Affiche une liste numérotée des commandes enregistrées. Le numéro à gauche est l’index d’historique, utilisé pour les désignateurs d’événements.

Afficher un nombre spécifique de commandes récentes

“`bash

history 20

“`

Affiche les 20 dernières commandes. Utile lorsque vous avez besoin d’un aperçu rapide de l’activité récente sans faire défiler des centaines d’entrées.

Écrire immédiatement l’historique de la session courante dans le fichier

“`bash

history -w

“`

Force une écriture immédiate du tampon d’historique en mémoire vers `~/.bash_history`. Utilisez ceci avant de fermer une session critique pour vous assurer que rien n’est perdu.

Lire l’historique depuis le fichier dans la session courante

“`bash

history -r

“`

Recharge `~/.bash_history` dans la mémoire de la session courante. Utile lorsque vous souhaitez accéder aux commandes saisies dans une autre fenêtre de terminal pendant la même connexion.

Rappel et réexécution des commandes

Désignateurs d’événements avec `!`

La syntaxe des désignateurs d’événements de Bash permet la réexécution directe de commandes historiques par référence :

DésignateurComportement
`!!`Réexécute la commande précédente immédiate
`!n`Exécute la commande à l’index d’historique `n`
`!-n`Exécute la commande `n` positions en arrière depuis la position actuelle
`!string`Exécute la commande la plus récente commençant par `string`
`!?string?`Exécute la commande la plus récente contenant `string` n’importe où
`!$`Substitue le dernier argument de la commande précédente
`!*`Substitue tous les arguments de la commande précédente

Exemple pratique — réutilisation du dernier argument :

“`bash

mkdir /var/www/myproject

cd !$

“`

`!$` se développe en `/var/www/myproject`, vous évitant de retaper le chemin. C’est l’une des fonctionnalités les plus sous-utilisées mais les plus utiles de l’historique Bash.

Prévisualisation avant exécution :

Ajoutez `:p` à n’importe quel désignateur d’événement pour afficher la commande sans l’exécuter :

“`bash

!42:p

“`

C’est une habitude de sécurité critique lorsque vous travaillez sur des serveurs de production. Prévisualisez toujours les commandes destructives avant leur exécution.

Désignateurs de mots pour l’extraction d’arguments

Au-delà de la réexécution de commandes entières, Bash vous permet d’extraire des arguments spécifiques des entrées d’historique :

“`bash

!!:2 # Second word (argument) of the last command

!!:1-3 # Words 1 through 3 of the last command

!ssh:$ # Last argument of the most recent ssh command

“`

Ce niveau de granularité est inestimable lors de la construction de pipelines complexes ou de la répétition d’opérations sur les mêmes chemins de fichiers.

Raccourcis clavier pour la navigation dans l’historique

RaccourciAction
`Up Arrow` / `Ctrl+P`Aller à la commande précédente
`Down Arrow` / `Ctrl+N`Aller à la commande suivante
`Ctrl+R`Recherche incrémentale inversée dans l’historique
`Ctrl+S`Recherche incrémentale vers l’avant (nécessite `stty -ixon`)
`Alt+.`Insérer le dernier argument de la commande précédente
`Ctrl+G`Annuler la recherche dans l’historique en cours

Remarque sur `Ctrl+S` : Par défaut, `Ctrl+S` déclenche le contrôle de flux XON/XOFF et gèle le terminal. Pour activer la recherche vers l’avant dans l’historique, ajoutez `stty -ixon` à votre `~/.bashrc`.

Recherche inversée avec `Ctrl+R`

“`

(reverse-i-search)`git': git commit -am "fix: resolve race condition"

“`

Saisissez une sous-chaîne et Bash fait correspondre de manière incrémentale la commande la plus récente la contenant. Appuyez à nouveau sur `Ctrl+R` pour passer aux correspondances plus anciennes. Appuyez sur `Enter` pour exécuter, ou sur `Ctrl+G` pour annuler sans rien exécuter.

Pour les recherches dans l’historique à volume élevé, redirigez vers `grep` :

“`bash

history | grep "docker run"

history | grep -E "^[[:space:]]+[0-9]+[[:space:]]+ssh"

“`

Modification et gestion des entrées d’historique

Supprimer une entrée spécifique

“`bash

history -d 87

“`

Supprime la commande à l’index 87 de la liste en mémoire. Pour rendre cela permanent, suivez avec `history -w` pour réécrire la liste modifiée sur le disque.

Supprimer une plage d’entrées

“`bash

for i in $(seq 85 90); do history -d 85; done

“`

Comme la suppression décale les indices, supprimez toujours le même numéro d’index dans une boucle plutôt que de l’incrémenter.

Effacer tout l’historique en mémoire

“`bash

history -c

“`

Efface le tampon d’historique de la session courante. Cela ne touche pas `~/.bash_history` sur le disque.

Purger complètement tout l’historique

“`bash

history -c && history -w

“`

Efface le tampon en mémoire puis écrit le tampon vide dans `~/.bash_history`, tronquant effectivement le fichier. C’est la séquence correcte en deux étapes — utiliser `> ~/.bash_history` seul ne vide pas le tampon en mémoire, donc le fichier peut être repeuplé à la fermeture de la session.

Configuration de l’historique Bash : variables d’environnement

Tout le comportement de l’historique est régi par des variables d’environnement, généralement définies dans `~/.bashrc` (shells interactifs non-login) ou `~/.bash_profile` / `~/.profile` (shells login). Les modifications prennent effet après avoir sourcé le fichier :

“`bash

source ~/.bashrc

“`

`HISTSIZE`

Contrôle le nombre de commandes conservées en mémoire pendant une session active.

“`bash

export HISTSIZE=10000

“`

Définir cette valeur à `0` désactive entièrement l’historique en mémoire. La définir à `-1` (dans Bash 4.3+) la rend illimitée.

`HISTFILESIZE`

Contrôle le nombre maximum de lignes stockées dans `~/.bash_history` sur le disque.

“`bash

export HISTFILESIZE=20000

“`

Lorsque le fichier dépasse cette limite, Bash supprime les entrées les plus anciennes. Pour les environnements sensibles à la conformité, définissez cette valeur à un grand nombre et associez-la à la rotation des journaux.

`HISTCONTROL`

Détermine les règles de filtrage pour les commandes qui sont enregistrées.

ValeurComportement
`ignoredups`Ignore les commandes dupliquées consécutives
`ignorespace`Ignore les commandes préfixées par un espace
`ignoreboth`Combine les deux options ci-dessus
`erasedups`Supprime toutes les occurrences précédentes d’une commande avant d’ajouter la nouvelle

“`bash

export HISTCONTROL=ignoreboth

“`

Cas d’utilisation sécuritaire pour `ignorespace` : Préfixez toute commande contenant un mot de passe ou un secret avec un espace pour éviter qu’elle soit enregistrée :

“`bash

mysql -u root -pSuperSecretPassword

“`

C’est une pratique de sécurité opérationnelle largement utilisée sur les systèmes partagés ou multi-utilisateurs.

`HISTTIMEFORMAT`

Ajoute un horodatage à chaque entrée d’historique, stocké sous forme de ligne de commentaire dans `~/.bash_history`.

“`bash

export HISTTIMEFORMAT="%Y-%m-%d %H:%M:%S "

“`

Exemple de sortie :

“`

487 2024-11-14 09:32:17 systemctl restart nginx

488 2024-11-14 09:32:45 tail -f /var/log/nginx/error.log

“`

Les horodatages sont essentiels pour la forensique post-incident sur les environnements d’hébergement VPS et les infrastructures dédiées. Sans eux, vous savez *ce qui* a été exécuté mais pas *quand*.

`HISTIGNORE`

Une liste de motifs glob séparés par des deux-points. Les commandes correspondant à n’importe quel motif ne sont pas sauvegardées dans l’historique.

“`bash

export HISTIGNORE="ls:ll:la:cd:pwd:exit:clear:history"

“`

Cela empêche les commandes triviales de polluer votre historique et de diluer les résultats de recherche. Vous pouvez également utiliser des caractères génériques :

“`bash

export HISTIGNORE="*password*:*secret*:*token*"

“`

C’est une mesure de défense en profondeur — combinez-la avec `ignorespace` pour une hygiène maximale des identifiants.

Tableau de référence complet des variables de configuration de l’historique Bash

VariableValeur par défautObjectif
`HISTSIZE`500–1000Commandes conservées en mémoire par session
`HISTFILESIZE`500–2000Lignes stockées dans `~/.bash_history`
`HISTCONTROL`(non défini)Règles de filtrage pour les commandes enregistrées
`HISTTIMEFORMAT`(non défini)Format d’horodatage ajouté en préfixe aux entrées
`HISTIGNORE`(non défini)Motifs glob pour les commandes à exclure
`HISTFILE``~/.bash_history`Chemin vers le fichier d’historique
`histappend` (shopt)offAjout vs. écrasement à la fermeture de session

Partage de l’historique entre plusieurs sessions de terminal

Par défaut, chaque session Bash maintient son propre tampon d’historique isolé. Les commandes saisies dans le Terminal A sont invisibles pour le Terminal B jusqu’à ce que les deux sessions se ferment et que le fichier soit écrit. Pour les administrateurs gérant plusieurs sessions SSH simultanément sur des serveurs dédiés, cela crée des lacunes dans l’enregistrement opérationnel.

La configuration recommandée pour le partage d’historique en temps réel entre sessions :

“`bash

~/.bashrc

export HISTSIZE=100000

export HISTFILESIZE=100000

export HISTCONTROL=ignoreboth

export HISTTIMEFORMAT="%Y-%m-%d %H:%M:%S "

shopt -s histappend

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

“`

Ce que cela fait :

  • `history -a` — ajoute la dernière commande au fichier
  • `history -c` — efface le tampon en mémoire
  • `history -r` — recharge le fichier en mémoire

Après chaque commande, chaque session de terminal voit l’historique complet et unifié de toutes les sessions actives. La contrepartie est une légère surcharge sur l’exécution de `PROMPT_COMMAND`, ce qui est négligeable en pratique.

Recherche efficace dans l’historique : techniques avancées

`fzf` — Recherche floue dans l’historique

L’outil `fzf` transforme la recherche dans l’historique d’un balayage linéaire en une interface de correspondance floue interactive :

“`bash

Install fzf (Debian/Ubuntu)

sudo apt install fzf

Bind Ctrl+R to fzf-powered history search

Add to ~/.bashrc:

[ -f ~/.fzf.bash ] && source ~/.fzf.bash

“`

Une fois configuré, `Ctrl+R` ouvre une recherche floue en plein écran sur tout votre historique. C’est particulièrement puissant avec de grands fichiers d’historique (plus de 10 000 entrées) où `grep` devient fastidieux.

Extraction de l’historique pour les scripts

“`bash

Export all unique commands containing "iptables" to a script

history | grep iptables | awk '{$1=""; print $0}' | sort -u > iptables_audit.sh

“`

Ce modèle est utile pour reconstruire des runbooks à partir de commandes ad-hoc exécutées lors d’une réponse à un incident.

Considérations de sécurité pour l’historique Bash

L’historique Bash est un outil à double tranchant. Il accélère les flux de travail légitimes mais représente également une surface d’attaque significative.

Principaux risques et mesures d’atténuation :

  • Exposition des identifiants : Les mots de passe passés comme arguments de ligne de commande (par exemple, `curl -u admin:password`) sont stockés en texte brut dans `~/.bash_history`. Utilisez plutôt `ignorespace`, `HISTIGNORE`, ou des variables d’environnement.
  • Forensique d’escalade de privilèges : Les attaquants qui obtiennent un accès shell lisent systématiquement `~/.bash_history` pour comprendre l’environnement, découvrir des identifiants et identifier des cibles de valeur. Définissez des permissions restrictives : `chmod 600 ~/.bash_history`.
  • Falsification de l’historique : Un utilisateur compromis peut exécuter `history -c && history -w` pour effacer toutes les preuves. À des fins d’audit sur les systèmes de production, envisagez une journalisation des commandes basée sur `auditd` ou `syslog`, qui ne peut pas être manipulée par l’utilisateur.
  • Isolation de l’historique root : L’historique de l’utilisateur root est stocké dans `/root/.bash_history`. Assurez-vous que ce fichier n’est pas lisible par tous et qu’il est inclus dans votre périmètre de sauvegarde et d’audit.

Pour les environnements nécessitant un audit strict des commandes — tels que les infrastructures conformes PCI-DSS ou SOC 2 — l’historique Bash seul est insuffisant. Associez-le à un audit au niveau du noyau via `auditd` et à l’expédition centralisée des journaux.

Historique Bash vs. autres systèmes d’historique de shell

FonctionnalitéHistorique BashHistorique ZshHistorique Fish
Fichier d’historique par défaut`~/.bash_history``~/.zsh_history``~/.local/share/fish/fish_history`
Support des horodatagesVia `HISTTIMEFORMAT`IntégréIntégré (format YAML)
Gestion des doublons`HISTCONTROL`Option `HIST_IGNORE_DUPS`Déduplication automatique
Partage entre sessionsManuel (`PROMPT_COMMAND`)Option `INC_APPEND_HISTORY`Automatique (partagé par défaut)
Interface de recherche`Ctrl+R` (linéaire)`Ctrl+R` (linéaire)Mise en évidence syntaxique, contextuelle
Taille maximale de l’historiqueVariable `HISTFILESIZE`Variable `SAVEHIST`Pas de limite stricte
Mécanisme de verrouillageAucun (conditions de concurrence possibles)Verrouillage de fichier supportéBasé sur SQLite (écritures atomiques)

La principale limitation de l’historique Bash est l’absence de verrouillage intégré, ce qui peut provoquer des conditions de concurrence lorsque plusieurs sessions écrivent simultanément. Zsh et Fish gèrent cela plus élégamment au niveau du shell.

Configuration pratique pour les environnements de production

Voici une configuration d’historique `~/.bashrc` éprouvée, adaptée aux serveurs Linux de production, y compris ceux exécutant un VPS avec cPanel ou des panneaux de contrôle personnalisés :

“`bash

— Bash History Configuration —

export HISTSIZE=50000

export HISTFILESIZE=50000

export HISTCONTROL=ignoreboth:erasedups

export HISTTIMEFORMAT="%Y-%m-%d %H:%M:%S "

export HISTIGNORE="ls:ll:la:cd:pwd:exit:clear:bg:fg:jobs"

export HISTFILE=~/.bash_history

Append to history file; don't overwrite

shopt -s histappend

Save and reload history after each command

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

Enable multi-line command history as single entry

shopt -s cmdhist

Store multi-line commands with embedded newlines

shopt -s lithist

“`

`cmdhist` et `lithist` méritent une mention spéciale. Sans `cmdhist`, une commande multi-lignes (comme une boucle `for` saisie de manière interactive) est stockée sous forme de lignes séparées, rendant impossible sa réexécution propre. Avec `cmdhist` activé et `lithist` défini, toute la construction est stockée comme une seule entrée d’historique avec des sauts de ligne littéraux, préservant sa structure.

Automatisation des flux de travail basés sur l’historique

Générer un rapport de fréquence des commandes

“`bash

history | awk '{print $2}' | sort | uniq -c | sort -rn | head -20

“`

Cela révèle vos 20 commandes les plus utilisées — utile pour identifier les candidats aux alias ou aux fonctions shell.

Auditer l’utilisation de `sudo`

“`bash

history | grep sudo | awk '{$1=""; print $0}'

“`

Sur les environnements de panneaux de contrôle VPS partagés, cela fournit un audit rapide des opérations privilégiées effectuées pendant une session.

Reconstruire une chronologie de session

“`bash

HISTTIMEFORMAT="%Y-%m-%d %H:%M:%S " history | grep "2024-11-14"

“`

Filtre toutes les commandes exécutées à une date spécifique — inestimable lors des revues post-incident.

Points techniques clés et liste de contrôle

Avant de déployer une configuration d’historique Bash dans n’importe quel environnement, validez les points suivants :

  • `shopt -s histappend` est défini — empêche la perte d’historique due à des sessions concurrentes qui s’écrasent mutuellement
  • `HISTSIZE` et `HISTFILESIZE` sont tous deux configurés — définir seulement l’un laisse l’autre à sa valeur par défaut, provoquant une troncature inattendue
  • `HISTTIMEFORMAT` est activé — sans horodatages, l’historique n’a aucune valeur forensique
  • `HISTCONTROL=ignoreboth` est défini au minimum — réduit le bruit et empêche l’enregistrement des commandes adjacentes aux identifiants
  • `HISTIGNORE` exclut les commandes triviales — maintient un bon rapport signal/bruit dans l’historique
  • `~/.bash_history` a les permissions `chmod 600` — empêche les autres utilisateurs de lire votre historique de commandes
  • `cmdhist` est activé — garantit que les commandes multi-lignes sont stockées comme des unités cohérentes
  • `PROMPT_COMMAND` synchronise l’historique en temps réel — requis pour les environnements multi-sessions
  • `auditd` est déployé en parallèle — pour les systèmes de production où une journalisation inviolable est requise
  • Les identifiants ne sont jamais passés comme arguments CLI — utilisez des variables d’environnement, `.netrc`, ou des gestionnaires de secrets à la place

Questions fréquemment posées

Pourquoi mon historique Bash disparaît-il après la fermeture d’une session SSH ?

Cela se produit généralement parce que `shopt -s histappend` n’est pas défini. Sans cela, chaque session écrase `~/.bash_history` à la fermeture. Si la session se termine anormalement (coupure réseau, `kill -9`), l’écriture ne se produit jamais du tout. Définissez `histappend` et `PROMPT_COMMAND='history -a'` pour persister les commandes en temps réel.

Comment empêcher l’enregistrement des mots de passe dans l’historique Bash ?

Utilisez deux techniques complémentaires : préfixez la commande avec un espace (nécessite `HISTCONTROL=ignorespace` ou `ignoreboth`), et ajoutez les modèles de commandes sensibles à `HISTIGNORE`. Pour une hygiène à long terme, ne passez jamais de secrets comme arguments CLI — utilisez des variables d’environnement ou des outils dédiés à la gestion des secrets.

Quelle est la différence entre `HISTSIZE` et `HISTFILESIZE` ?

`HISTSIZE` contrôle le nombre de commandes que Bash conserve en mémoire pendant une session active. `HISTFILESIZE` contrôle le nombre de lignes conservées dans `~/.bash_history` sur le disque. Les deux doivent être définis explicitement — un grand `HISTSIZE` avec un petit `HISTFILESIZE` signifie que votre historique en session est riche, mais la majeure partie est supprimée à la fermeture de la session.

Les entrées d’historique supprimées peuvent-elles être récupérées ?

Une fois `history -c && history -w` exécuté, le tampon en mémoire est effacé et le fichier est tronqué — la récupération standard n’est pas possible. Cependant, si votre système utilise des instantanés de système de fichiers ou des solutions de sauvegarde, la version précédente de `~/.bash_history` peut être récupérable depuis un instantané. C’est une raison supplémentaire d’implémenter `auditd` pour une journalisation inviolable sur les infrastructures critiques.

Comment partager l’historique Bash entre plusieurs sessions de terminal simultanées ?

Ajoutez ce qui suit à `~/.bashrc` : `shopt -s histappend` et `PROMPT_COMMAND='history -a; history -c; history -r'`. Cela force chaque session à ajouter sa dernière commande au fichier partagé et à recharger le fichier complet après chaque invite, donnant à tous les terminaux actifs une vue unifiée et en temps réel de l’historique des commandes.

15%

Économisez 15% sur tous les services d'hébergement

Testez vos compétences et obtenez Réduction sur tout plan d'hébergement

Utilisez le code :

Skills
Commencer