Commande history : synchro entre terminaux + sauvegarde

Tags: #<Tag:0x00007f509f8ec3c0> #<Tag:0x00007f509f8ec168> #<Tag:0x00007f509f8f7cc0>

Bonjour

Depuis 2015 je garde une trace de toutes les lignes de commandes que j’ai entrées.

La date/heure de lancement de chaque ligne de commande(s) est enregistrée.

Le fichier historique est commun à tous les terminaux qui seront ouverts.

J’ai créé une fonction que j’ai nommée hg (history grep)
qui me permet de faire s’afficher toutes les lignes de tous les fichiers historiques qui contiendraient un motif.

=======
Je fais sourcer par mon ~/.bashrc un fichier que j’ai nommé ~/.bash_logHistory
et dont le contenu est :

# Lignes de commande(s) bash pour log des fichiers bash_history
#  À faire sourcer par ~/.bashrc

#  Voir :
#   http://askubuntu.com/questions/67283/is-it-possible-to-make-writing-to-bash-history-immediate
#   http://unix.stackexchange.com/questions/1288/preserve-bash-history-in-multiple-terminal-windows
#   https://unix.stackexchange.com/questions/18212/bash-history-ignoredups-and-erasedups-setting-conflict-with-common-history
#   https://www.digitalocean.com/community/tutorials/how-to-use-bash-history-commands-and-expansions-on-a-linux-vps

#  ~/.bash_history commun à tous les terminaux de la session graphique courante.
PROMPT_COMMAND="history -a; history -c; history -r; $PROMPT_COMMAND" # À chaque fois que le prompt sera affiché : -a append; -c clear; -r read

shopt -s histappend histverify # append to history, don't overwrite it + Allow to review a history substitution result by loading the resulting line into the editing buffer, rather than directly executing it.
HISTSIZE=4000                  # The number of commands to remember in the command history. The default value is 500.
HISTFILESIZE=2000              # The maximum number of lines contained in the history file.
HISTCONTROL=ignoreboth         # ignoreboth <=> Pas de doublons consécutifs et ignore les lignes dont le premier caractère est un caractère espace.
HISTTIMEFORMAT='%d/%m/%Y %T '  # Format d'affichage date/heure des lignes de commande(s) enregistrées.

rep="~/.logsBashHistory"                           # Nom du répertoire dans lequel seront sauvegardés les fichiers ~/.bash_history archivés.
backupPrefix="$rep/bash_hist_${USER}_${HOSTNAME}"  # Préfixe du nom du nouveau fichier log à créer.
backupLog="${backupPrefix}.$(date +%Y%m)"          # Nom du nouveau fichier log à créer en fonction de la date courante.
keep=200                                           # Garder les 200 dernières lignes de commandes dans ~/.bash_history après archivage.

[ -d "$rep" ] || mkdir "$rep"             # Si inexistant, créer le répertoire qui va contenir les fichiers ~/.bash_history archivés.
[ -f "$backupLog" ] || {                  # Si le fichier backup à créer n'existe PAS encore dans le répertoire perso des logs archivés <=> un par mois.
    mv -f "$HISTFILE" "$backupLog"           # Déplacer en renommant ~/.bash_history dans le répertoire ~/.logsBashHistory/
    tail -n$keep "$backupLog" > "$HISTFILE"  # Créer un nouveau fichier ~/.bash_history en y copiant les 200 dernières lignes de l'ancien ~/.bash_history
    history -r                               # Actualiser le tampon mémoire de la commande history avec le contenu du nouveau fichier ~/.bash_history
}

# Fonction de recherche de motif autant dans le fichier history en cours
#   que dans les fichiers archivés dans le répertoire ~/.logsBashHistory
#

### TOUDOUX :
#     - Revoir la ligne de commande awk pour se passer du grep final.
#     - Tester la présence de gawk
#        [ $(basename $(readlink --canonicalize $(which awk))) == gawk ] && exit

hg ()
{
    # ATTENTION : Cette fonction de recherche utilise gawk

    msg="\n\tDescription\t: hg est un raccourci pour 'history | grep motifRecherché'\n\n"
    msg+="\tSyntaxe\t\t: hg motif_recherché\n\n"
    msg+="\tLa recherche sera aussi effectuée dans les fichiers history archivés.\n\n"

    case $@ in
        ?|/?|-?|-h|--help|'')
            printf "$msg"
            ;;
        *)
            awk -v timeFormat="$HISTTIMEFORMAT" '{ if($0 ~/^#[[:digit:]]{10}$/) printf strftime(" arch. "timeFormat, substr($0,2,10)); else print $0; }' "${backupPrefix}".* | grep "$1"
            history | grep "$1"
            ;;
    esac
}

=======
REMARQUE :
Ma fonction de recherche utilise gawk et ne fonctionne pas avec awk
mais même si elle fonctionne correctement avec gawk + grep
elle aurait bien besoin d’être revue et corrigée (depuis 2015 elle est restée dans mes TOUDOUX)

=======
Voilà ce que ça donne :

michel@debbull:~$ hg

  Description	: hg est un raccourci pour 'history | grep motifRecherché'

  Syntaxe		: hg motif_recherché

  La recherche sera aussi effectuée dans les fichiers history archivés.

michel@debbull:~$ 

Et un retour (que j’ai tronqué parce que trop long) d’une recherche :

michel@debbull:~$ hg fdisk
 arch. 25/12/2015 01:22:38 man fdisk
 arch. 26/12/2015 22:36:39 fdisk -l
 arch. 23/01/2016 09:49:05 fdisk -l /home/michel/virtMachines/ISOsFr/debian-live-8.2.0-amd64-cinnamon-desktop.iso
 arch. 29/01/2016 02:59:27 fdisk aaeeff.data
…
…
 arch. 24/06/2021 06:50:23 sudo fdisk /dev/sda
 arch. 24/06/2021 06:54:54 /usr/sbin/fdisk /dev/loop0
  241  05/08/2021 14:42:31 /usr/sbin/fdisk -l Téléchargements/ISOsInstall/ubuntu-20.04.2.0-desktop-amd64.iso
  243  05/08/2021 14:43:51 /usr/sbin/fdisk -l ubuntu-20.04.2.0-desktop-amd64.iso
  245  05/08/2021 14:45:29 /usr/sbin/fdisk -l debian-10.10.0-amd64-netinst.iso
  854  13/08/2021 04:48:18 hg fdisk
michel@debbull:~$ hg

Dans ce retour, le motif de recherche (fdisk) est affiché en rouge
les lignes qui commencent par arch. sont extraites des fichiers historique archivés,
et les lignes commençant par un numéro ont été retournées par la commande history

=======
Quand je suis sur une machine dont le nom (HOSTNAME) est différent,
j’ai parfois envie d’utiliser mes anciens fichiers archive bash_hist_*

Alors, je renomme mes fichiers bash_hist_* en adaptant le nom de machine :

ancienNom="debbull"; nouveauNom="$HOSTNAME"
for f in ~/.logsBashHistory/bash_hist_*; do mv $f ${f/_$ancienNom/_$nouveauNom}; done
1 J'aime