Comment configurer et utiliser efficacement l’historique bash

Dans cet article, nous allons voir comment améliorer notre productivité en s’intéressant à l’historique bash. L’historique permet de conserver les dernières commandes tapées dans un shell bash. C’est très utile pour retrouver certaines commandes oubliées, éviter de devoir les ré-écrire ou regarder rapidement ce qu’un autre administrateur a fait sur le système.

Dans un premier temps, nous allons voir qu’il est possible de configurer cet historique, c’est-à-dire ce qui s’affiche lorsqu’on tape la commande history. Dans un second temps, nous allons voir comment utiliser cet historique de manière efficace.

Configuration de l’historique bash

Vous ne le saviez peut être pas, mais il est possible de modifier le comportement de l’historique bash à l’aide de variables d’environnement. Ces variables d’environnement peuvent être ajoutées dans le fichier ~/.bashrc.

Ignorer les commandes dupliquées et les espaces

La première variable d’environnement intéressante est HISTCONTROL. Grâce à cette variable, on peut indiquer à l’historique de bash de :

  • Ne pas afficher ou ne pas enregistrer les commandes dupliquées. Autrement dit, cela évite d’avoir 400 entrées cd .. dans l’historique de bash.
  • D’ignorer les commandes qui commence par un espace. Par exemple, la commande [espace]cd .. ne sera pas enregistré dans l’historique. Cela peut être pratique pour des commandes sensibles, par exemple, celles qui contiennent des mots de passes.
# Ne pas enregistrer les commandes qui commencent par un espace
export HISTCONTROL="ignorespace"
# Ne pas afficher les commandes dupliquées qui se suivent
export HISTCONTROL="ignoredups"
# A le même effet que les deux commandes précédente
export HISTCONTROL="ignoreboth"
# Supprime toutes les commandes dupliquées (même celles qui ne se suivent pas)
export HISTCONTROL="erasedups"
# Efface les commandes dupliquées, n'enregistre pas les commandes qui commencent par un espace
export HISTCONTROL="erasedups:ignorespace"
Les valeurs possibles de HISTCONTROL dans ~/.bashrc

Il y a une petite différence entre ignoredups et erasedups. Avec ignoredups, ce sont les commandes dupliquées qui se suivent qui sont ignorées. Avec erasedups, c’est toutes les commandes dupliquées (même si elles ne se suivent pas) qui sont supprimées.

Contrôler la taille de l’historique bash

Deux variables d’environnement permettent de contrôler la taille de l’historique. Il s’agit des variables suivantes :

  • HISTSIZE : en résumé, cela permet de définir le nombre de ligne qui sera affiché lorsqu’on tape la commande history
  • HISTFILESIZE : permet de définir la taille maximale (en nombre de ligne) du fichier d’historique.

Le fichier d’historique peut être plus gros que le nombre de lignes affichées via la commande historique.

export HISTSIZE = 1000
export HISTFILESIZE = 10000
Contrôle de la taille de l'historique bash

Ignorer certaines commandes

La variable HISTIGNORE permet de définir une liste de commande à ignorer dans l’historique. On peut par exemple ignorer les commandes basiques comme cd, ls etc… qui encombre l’historique.

# On ignore les commandes ls et cd de l'historique
export HISTIGNORE="ls*:cd*"
Ignorer certaines commandes de l'historique bash

Ajouter la date à l’historique bash

La variable HISTTIMEFORMAT permet de changer le format d’affichage de la commande history. Cela permet d’afficher la date en face des commandes lancées :

export HISTTIMEFORMAT="%d/%m/%Y %H:%M:%S "
# Un exemple de retour :
history
  746  14/08/2018 21:43:14 cd
  747  14/08/2018 21:43:15 ls
  748  14/08/2018 21:43:17 pwd
  749  14/08/2018 21:43:20 free -m
  750  14/08/2018 21:43:23 history
Ajouter la date à l'historique bash

Garder l’historique de plusieurs sessions shell simultanées

Parfois, l’historique ne se conserve pas et c’est le cas lorsque plusieurs sessions shell sont ouvertes simultanément. Généralement, c’est l’historique du shell fermé en dernier qui reste conservé. Pour éviter cela, on peut ajouter la commande suivante dans le ~/.bashrcshopt -s histappend

  • shopt : signifie « shell option » permet de modifier le comportement du shell en lui passant certaines options
  • histappend : indique au shell que lorsqu’on ferme une option, l’historique doit être ajouté à la fin du fichier d’historique (append), ce qui permet de conserver les commandes lancées dans tous les shell et non celui fermé en dernier.

Astuces pour utiliser efficacement l’historique bash

Maintenant que nous avons vu qu’il était possible de modifier la configuration de l’historique, nous allons voir quelques astuces pour l’utiliser de manière efficace.

Rechercher une commande dans l’historique bash

Première méthode pour faire une recherche dans l’historique, celle qui reste ma favorite : grep.

# Affiche les commandes contenant le 'mot clé'
history | grep 'mot clé'
# Affiche les commandes contenant 'mot cle 1' ou 'mot cle 2'
history | grep -e 'mot cle 1' -e 'mot cle 2'
# Affiche les commandes contenant 'mot cle' et 'autre mot cle'
history | grep 'mot cle' | grep 'autre mot cle'
Rechercher dans l'historique bash avec grep

La deuxième méthode consiste à utiliser le raccourcis CTRL + R de bash, qui lance le mode reverse search. Dés que le raccourcis est activé, il est possible de faire une recherche sur un mot clé. Dés que la commande recherchée est trouvé, il suffit de la lancer avec le raccourcis CTRL + O ou plus simplement la touche Entrer. Pour sortie de ce mode de recherche, il faut utiliser le raccourcis CTRL + G.

bash history reverse search

Reverse inversé dans l’historique bash

Lancer une commande de l’historique bash

Bash est capable de lancer des commandes qui sont présentes dans l’historique. Le fonctionnement se base sur l’utilisation du caractère !. Cela effectue une substitution donc cela signifie que cela fonctionne comme une variable. Concrètement, cela veut dire que nous pouvons chaîner les commandes, utiliser le ! n’importe où et y ajouter des arguments. Il existe plusieurs variantes :

  • !42 : lance la commande ayant le numéro 42 dans l’historique. Comment trouver ce numéro ? Simplement en tapant la commande history. Chaque commande de l’historique est préfixé d’un numéro.
  • !! : relance la dernière commande présente dans l’historique. Revient au même que de faire un « flèche supérieur » puis « entrer ».
  • !motCle : relance la dernière commande qui correspond au premier résultat de la recherche inversé sur « motCle ». Autrement dit, cela recherche le mot clé (en partant des dernières commandes lancées) puis lance la commande trouvé.
  • !42:p, !!:p, !motCle:p : l’ajout du :p permet d’afficher la commande plutôt que de la lancer.
  • ^mtCl^motCle : relance la dernière commande mais en remplaçant « mtCl » par « motCle« . Autrement dit, cela permet de relancer la dernière commande en corrigeant une faute qu’on aurait pu faire.
# Affiche les 15 dernières lignes de l'historique
history | tail -n 15
  786  15/08/2018 15:47:28 ls
  787  15/08/2018 15:47:30 history
  788  16/08/2018 10:10:47 clear
  789  16/08/2018 10:10:47 ls
  790  16/08/2018 10:10:54 ls -lh quelqueChoseDeLongAEcrire/
  791  16/08/2018 10:10:56 uname -a
  792  16/08/2018 10:10:59 free -m
  793  16/08/2018 10:11:07 df -h
  794  16/08/2018 10:13:11 ping google.com
  795  16/08/2018 10:13:39 touch quelqueChoseDeLongAEcrire/un_long_fichier.txt
  796  16/08/2018 10:13:43 history
  797  16/08/2018 10:14:44 history
  798  16/08/2018 10:15:05 source ~/.bashrc
  799  16/08/2018 10:15:47 source ~/.bashrc
  800* 16/08/2018 10:15:56 vi ~/.bashrc
# Relance la commande 794 mais en y ajoutant l'argument -c 4
!794 -c 4
ping google.com -c 4
PING google.com (172.217.18.238) 56(84) bytes of data.
64 bytes from mrs08s02-in-f14.1e100.net (172.217.18.238): icmp_seq=1 ttl=53 time=19.8 ms
64 bytes from mrs08s02-in-f14.1e100.net (172.217.18.238): icmp_seq=2 ttl=53 time=19.7 ms
64 bytes from mrs08s02-in-f14.1e100.net (172.217.18.238): icmp_seq=3 ttl=53 time=21.7 ms
64 bytes from mrs08s02-in-f14.1e100.net (172.217.18.238): icmp_seq=4 ttl=53 time=19.5 ms
--- google.com ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3004ms
rtt min/avg/max/mdev = 19.520/20.221/21.769/0.901 ms
# Relance la dernière commande correspondant à la recherche inversé sur le terme "ls"
!ls
ls -lh quelqueChoseDeLongAEcrire/
total 0
-rw-rw-r--. 1 alexis alexis 0 15 août  15:02 fic1.txt
-rw-rw-r--. 1 alexis alexis 0 16 août  10:13 un_long_fichier.txt
# Affiche la dernière commande trouvé correspondant à la recherche inversé sur le terme "ls"
!ls:p
ls -lh quelqueChoseDeLongAEcrire/
# On lance la commande uname -a
uname -a
Linux Host-001 3.10.0-514.el7.x86_64 #1 SMP Tue Nov 22 16:42:41 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
# On relance la dernière commande lancée, donc uname -a
!!
uname -a
Linux Host-001 3.10.0-514.el7.x86_64 #1 SMP Tue Nov 22 16:42:41 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
# Il est possible de chainer les commandes
!ping | grep 'from'
ping google.com -c 4 | grep 'from'
64 bytes from mrs08s03-in-f14.1e100.net (172.217.19.46): icmp_seq=1 ttl=53 time=19.4 ms
64 bytes from mrs08s03-in-f14.1e100.net (172.217.19.46): icmp_seq=2 ttl=53 time=20.1 ms
64 bytes from mrs08s03-in-f14.1e100.net (172.217.19.46): icmp_seq=3 ttl=53 time=19.6 ms
64 bytes from mrs08s03-in-f14.1e100.net (172.217.19.46): icmp_seq=4 ttl=53 time=19.8 ms
# Cela fonctionne comme une substitution donc on peut l'utiliser n'importe où
echo "Résultat du ping : " $(!799 | grep 'packets transmitted')
echo "Résultat du ping : " $(ping google.com -c 4 | grep 'packets transmitted')
Résultat du ping :  4 packets transmitted, 4 received, 0% packet loss, time 3007m
# Oups
pig google.com -c 1
bash: pig: commande inconnue...
# On relance la dernière commande mais en corrigeant l'erreur
^pig^ping
ping google.com -c 1
PING google.com (172.217.18.238) 56(84) bytes of data.
64 bytes from mrs08s02-in-f14.1e100.net (172.217.18.238): icmp_seq=1 ttl=53 time=19.0 ms
--- google.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 19.074/19.074/19.074/0.000 ms
Quelques exemples de l'utilisation du ! en bash pour la gestion de l'historique

Réutilisation des arguments

A défaut de relancer intégralement une commande présente dans l’historique, on peut réutiliser les arguments passés dans des commandes précédentes. Pour cela, on va toujours utiliser le ! :

  • !$ : sera substitué par le dernier argument de la dernière commande lancée.
  • !^ : premier argument de la dernière commandé exécutée.
  • !* : tous les arguments de la dernière commande lancée.
  • !cmd:2 : fait une recherche inversé sur le terme « cmd » dans l’historique et retourne le deuxième arguments de cette commande.
  • :cmd:* : fait une recherche inversé sur le terme « cmd » et retour tous les arguments de cette commande.
ls -lh quelqueChoseDeLongAEcrire
total 0
drwxrwxr-x. 2 alexis alexis 49 16 août  10:13 _bkp
-rw-rw-r--. 1 alexis alexis  0 15 août  15:02 fic1.txt
-rw-rw-r--. 1 alexis alexis  0 16 août  10:13 un_long_fichier.txt
# $! correspond au dernier argument de la commande précédente
cp -vaR !$ !$_bkp
cp -vaR quelqueChoseDeLongAEcrire quelqueChoseDeLongAEcrire_bkp
« quelqueChoseDeLongAEcrire » -> « quelqueChoseDeLongAEcrire_bkp »
« quelqueChoseDeLongAEcrire/fic1.txt » -> « quelqueChoseDeLongAEcrire_bkp/fic1.txt »
« quelqueChoseDeLongAEcrire/un_long_fichier.txt » -> « quelqueChoseDeLongAEcrire_bkp/un_long_fichier.txt »
« quelqueChoseDeLongAEcrire/_bkp » -> « quelqueChoseDeLongAEcrire_bkp/_bkp »
« quelqueChoseDeLongAEcrire/_bkp/fic1.txt » -> « quelqueChoseDeLongAEcrire_bkp/_bkp/fic1.txt »
« quelqueChoseDeLongAEcrire/_bkp/un_long_fichier.txt » -> « quelqueChoseDeLongAEcrire_bkp/_bkp/un_long_fichier.txt »
# $* correspond à tous les arugments de la commande précédente
echo "Les arguments de la commande précédente sont : " !*
echo "Les arguments de la commande précédente sont : " -vaR quelqueChoseDeLongAEcrire quelqueChoseDeLongAEcrire_bkp
Les arguments de la commande précédente sont :  -vaR quelqueChoseDeLongAEcrire quelqueChoseDeLongAEcrire_bkp
# Récupère le deuxième argument de la dernière commande cp lancée
ls -lh !cp:2
ls -lh quelqueChoseDeLongAEcrire
total 0
drwxrwxr-x. 2 alexis alexis 49 16 août  10:13 _bkp
-rw-rw-r--. 1 alexis alexis  0 15 août  15:02 fic1.txt
-rw-rw-r--. 1 alexis alexis  0 16 août  10:13 un_long_fichier.txt
Quelques exemples de ré-utilisation des arguments via l'historique bash

Supprimer une commande ou tout l’historique bash

Parfois l’historique contient des informations secrètes, comme un mot de passe par exemple. Pour supprimer une ligne particulière de l’historique, il faut commencer par récupérer le numéro de la ligne correspondante. Cela est récupérable avec la commande history. Ensuite, il faut lancer la commande history -d {numéro de la ligne} pour supprimer l’entrée.

Pour supprimer l’intégralité de l’historique, il faut lancer la commande suivante dans tous les shells qui sont ouvert : history -cw

Conclusion

J’espère que cet article vous aura donné quelques astuces sur l’historique de bash ! Nous avons vu qu’il était possible de le configurer et qu’il existe pleins d’astuces pour l’utiliser quotidiennement. Si vous avez d’autres astuces ou remarques à ce sujet, n’hésitez pas à en faire part dans les commentaires !

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée.

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.