Comportement étrange de l'historique de bash lors de l'exécution de plusieurs sessions

15

Comment l'historique des lignes de commande est-il stocké lorsque j'utilise plusieurs fenêtres de terminal? Je sais qu'il est stocké dans .bash_historymais je ne peux pas voir la logique sur quel historique est utilisé si j'ouvre une nouvelle fenêtre. Cela semble presque non déterministe dans un sens que je ne sais jamais quelle commande je verrai si j'essaie d'utiliser la flèche vers le haut dans une nouvelle fenêtre.

Quelqu'un peut-il expliquer cela?

Existe-t-il un moyen de contrôler l'historique de telle manière que je puisse réutiliser l'historique d'une fenêtre particulière?

Alex Gitelman
la source

Réponses:

14

Pour comprendre le comportement de l'historique bash, vous devez d'abord savoir ce qui suit:

  1. Il y a l'historique dans le fichier historique.
  2. Il y a l'histoire dans la mémoire d'un processus bash.
  3. L'historique dans la mémoire d'un processus bash n'est pas synchronisé avec l'historique dans la mémoire d'un autre processus bash.
  4. L'historique dans la mémoire d'un processus bash n'est pas synchronisé avec l'historique dans le fichier, sauf demande explicite à ou pendant un événement spécifique (voir ci-dessous).

En utilisant les paramètres par défaut, le cycle de vie d'une session bash en ce qui concerne l'historique est le suivant:

  1. Au démarrage, bash lira le fichier historique. Le contenu du fichier d'historique est maintenant dans la mémoire du processus bash.
  2. Lors d'une utilisation normale, seul l'historique en mémoire est manipulé.
  3. Pendant l'arrêt, l'historique en mémoire est écrit dans le fichier historique, écrasant tout contenu précédent du fichier historique.

Le comportement apparemment non déterministe que vous avez observé est principalement dû au fait que le contenu du fichier historique est toujours l'historique de la dernière session bash fermée, et bash ne lit le fichier historique qu'au démarrage.

Lire le manuel bash pour une explication plus détaillée du processus de démarrage et d'arrêt.

Notez qu'avec les paramètres par défaut, je veux dire les paramètres par défaut de bash. Votre distribution a peut-être fourni un .bashrc(ou/etc/bash.bashrc ) qui modifie ce comportement.

En activant l'option shell, histappendvous pouvez dire à bash de s'ajouter au lieu d'écraser le fichier d'historique. Vous pouvez activer histappendà l'aide de la commande shopt -s histappend. Pour que cette option soit toujours activée, vous devez placer la commande dans votre .bashrc(ou dans un autre fichier d'initialisation). En savoir plus sur la shoptcommande dans le manuel bash

Notez que l'activation histappendne réduira pas beaucoup le comportement apparemment non déterministe. C'est parce que chaque session bash a toujours sa propre histoire en mémoire. Il est possible d'avoir un historique bash principalement synchronisé. Il y a un guide pour que chaque processus bash ait un historique principalement synchronisé dans un thread en cas de débordement de pile .

en utilisant la commande intégrée, historyvous pouvez explicitement dire à bash de lire l'historique du fichier dans la mémoire ou l'écriture de la mémoire dans le fichier. Par exemple: history -rva lire le contenu du fichier et l'ajouter à l'historique en mémoire. history -wva écrire l'historique actuel de la mémoire dans un fichier, écrasant le contenu précédent. C'est essentiellement ce qui se passe lors de l'arrêt. En savoir plus sur la historycommande dans le manuel bash

Pour être complet, voici une liste des variables internes qui modifient le comportement de l'historique:

  • HISTFILE: le fichier dans lequel lire et écrire l'historique.
  • HISTFILESIZE: le nombre maximal de lignes pour le fichier historique.
  • HISTSIZE: le nombre maximal de lignes pour l'historique en mémoire.
  • HISTCONTROL, HISTIGNORE, HISTTIMEFORMAT: Pas pertinent pour cette discussion. Lisez le manuel bash pour plus de détails.
lesmana
la source
Bonne explication. Vous avez mentionné l'arrêt, mais qu'en est-il de la fermeture de la session de terminal? La session peut être supprimée via la déconnexion ou via l'interface utilisateur ou via d'autres moyens tels que l'interruption de la connexion réseau. Si le fichier d'historique entier est remplacé et que vous avez plusieurs sessions, dites-vous que l'historique du dernier fichier fermé sera utilisé dans le fichier d'historique? Cela pourrait expliquer un comportement non déterministe.
Alex Gitelman
le point de cycle de vie (3) n'est pas correct. Il semble que seule la première session bash écrit dans le fichier historique. Test: Ouvrez 2 sessions dans l'ordre- a, b. Faites écho bonjour en b . Sortez ensuite en b . Ouvrez ensuite une nouvelle session c . Cette session n'aura pas d'écho bonjour dans son histoire.
user606723
@AlexGitelman: si un processus bash est tué, il n'aura pas la possibilité d'écraser le fichier d'historique. et oui, l'historique de la dernière session fermée est celui qui sera dans le fichier historique.
lesmana
@ user606723: le point 3 est correct. lire le manuel bash. essayez à nouveau en utilisant un .bashrcfichier minimal . notez que votre distribution a peut-être modifié certains paramètres dans /etc/bash.bashrc. vérifier spécifiquement pour l'option shell histappend.
lesmana
2

http://www.gnu.org/software/bash/manual/bashref.html#Using-History-Interactively

Vous pourriez être en mesure de manipuler la façon dont le fichier d'historique est écrit avec l'un des terminaux, c'est-à-dire d'exécuter "history -a" ou "history -w" dans le terminal dans lequel vous souhaitez enregistrer l'historique, puis "history -r" dans les autres terminaux. ça dépend de ce que tu veux faire.

cjc
la source
0

AFAIK, les commandes bash sont enregistrées après la fin de la session SSH. Ainsi, les commandes ne sont pas enregistrées lorsqu'une session se termine anormalement (par exemple, en raison d'une panne de réseau). Je parle ici des sessions SSH. Les terminaux locaux peuvent utiliser une approche similaire.

Lors de l'ouverture de plusieurs sessions en même temps, les commandes saisies sur une session ne sont pas visibles sur l'autre alors qu'elles sont toutes deux actives. Cependant, vous verrez ces commandes lorsque vous mettrez fin à votre session, la rouvrir.

Khaled
la source
Ce n'est pas le comportement que j'ai vécu. Je peux le confirmer en faisant un test rapide où j'ouvre une session ssh, fais une commande et fais une sortie gracieuse. Dans ce cas, j'ai eu une autre session ssh précédemment active. Dans cette session bash préexistante, je vérifie .bash_history et ne trouve rien enregistré. Je trouve probable que la première session bash en cours d'exécution est la seule qui finisse par enregistrer sur .bash_history.
user606723
Mettre fin à votre session n'affectera pas les sessions en cours d'exécution, mais cela affectera les nouvelles sessions!
Khaled
Et si ce n'est pas la fenêtre du terminal SSH mais Gnome que je ferme via l'interface utilisateur?
Alex Gitelman
Cela doit être vérifié. Actuellement, je n'ai pas accès à un terminal Gnome!
Khaled
@Khaled, l'a testé, n'affecte pas les nouvelles sessions. (J'ai vérifié .bash_history avant de toute façon, c'est là que bash obtient l'historique des commandes pour les nouvelles sessions, je savais donc que cela ne fonctionnerait pas, mais je vous ai quand même humouré.)
user606723