Comment obtenir un historique bashed partagé entre différents onglets

19

J'ai utilisé la réponse dans /unix//a/1292/41729 pour activer l'historique partagé en temps réel entre des terminaux bash distincts. Comme expliqué dans la réponse ci-dessus, ceci est réalisé en ajoutant:

# avoid duplicates..
export HISTCONTROL=ignoredups:erasedups  
# append history entries..
shopt -s histappend

# After each command, save and reload history
export PROMPT_COMMAND="history -a; history -c; history -r; $PROMPT_COMMAND"

Cela fonctionne bien si les shells bash sont séparés (par exemple, en ouvrant différents terminaux bash en utilisant CTRL+ALT+T. Cependant, cela ne fonctionne pas si j'utilise tabs(à partir d'un terminal ouvert `CTRL + SHIFT + T) plutôt que de nouvelles fenêtres. Pourquoi cette différence de comportement? Comment puis-je partager l'historique de bash également entre différents onglets?

MISE À JOUR: J'ai remarqué un comportement inhabituel: si je tape, CTRL+Cla dernière commande tapée dans l'un des autres terminaux (à la fois un onglet ou non) s'affiche correctement. C'est comme si le CTRL + C force un vidage de l'historique pour qu'il soit correctement partagé.

A titre d'exemple les sorties (T1 désigne la borne 1 et la borne T2 2):

T1:
ls -lah <enter>
# the list of files and directory is shown

T2:
cd Documents <enter>

T1:
<up> (i.e. I press the up arrow)
ls -lah #i.e the last command in terminal 1 is shown rather than the last of terminal 2
^C (i.e. I press CTRL+C)
<up>
cd Documents #the last command issued in terminal 2 is correctly displayed

J'espère que cela peut offrir un indice!

lucacerone
la source
Vous l'avez ajouté à votre ~.bashrcdossier? D'un côté, exporter ces variables est inutile; gaspille juste l'espace de l'environnement.
geirha
@geirha oui, j'ai ajouté à mon fichier .bashrc. Merci pour le commentaire sur l'export.
lucacerone

Réponses:

2

Il semble que vous tentiez d'accéder à l'historique de l'autre terminal avant la synchronisation. PROMPT_COMMANDest exécutée juste avant l'impression d'une nouvelle invite, c'est-à-dire après avoir exécuté une commande et avant de taper la commande suivante. Cela ne se produira donc pas tout de suite en T1; vous devez provoquer l'affichage d'une nouvelle invite.

Pour tester cela, essayez cette variante sur vos étapes (j'ai ajouté un extra <enter>en T1):

T1:
ls -lah <enter>
# the list of files and directory is shown

T2:
cd Documents <enter>

T1:
<enter>
<up> (i.e. I press the up arrow)

Avec cette pression supplémentaire sur Entrée, vous obtenez une nouvelle invite, qui exécute PROMPT_COMMANDet synchronise votre historique, et je m'attends donc à ce que cette flèche vers le haut récupère le cdau lieu du ls, comme vous le vouliez. Malheureusement, je ne pense pas qu'il existe un moyen de faire en sorte que la synchronisation se fasse instantanément sur tous les terminaux sans exécuter aucune commande comme vous semblez le vouloir; efficacement, cela nécessiterait que toutes vos sessions de connexion synchronisent en permanence leurs listes d'historique, ce qui représenterait un énorme gaspillage de CPU et de débit de disque.

Paul
la source
vous avez raison, en appuyant sur Entrée, il est synchronisé après. Même s'il y a un gaspillage de mémoire ou de CPU, comment pourrais-je forcer la synchronisation? (Si c'est trop, je peux toujours le désactiver, mais je voudrais essayer)
lucacerone
1

J'ai posé la même question et voici la réponse que j'ai trouvée ...

HISTSIZE=9000
HISTFILESIZE=$HISTSIZE
HISTCONTROL=ignorespace:ignoredups

history() {
  _bash_history_sync
  builtin history "$@"
}

_bash_history_sync() {
  builtin history -a         #1
  HISTFILESIZE=$HISTSIZE     #2
  builtin history -c         #3
  builtin history -r         #4
}

PROMPT_COMMAND=_bash_history_sync
Scott Goodgame
la source
Source: unix.stackexchange.com/a/48116/37944
Radu Rădeanu
deux clarfications avant d'essayer: dois-je supprimer les autres options d'hystory alors? cela va dans .bashrc à droite?
lucacerone
malheureusement ça ne marche pas ...
lucacerone
Chaque fois qu'il HISTFILESIZEest modifié, il tente automatiquement de tronquer le fichier historique existant. La modification HISTSIZEa un effet similaire sur l'historique actuel. Pour référence, voir le commentaire dans variables.cdans le bash src juste avant sv_histsize.
Brian Vandenberg
1

ajoutez ces lignes à votre .bashrcfichier

# avoid duplicates..
export HISTCONTROL=ignoredups:erasedups  
# append history entries..
shopt -s histappend

trap 'history -r' USR1 
export PROMPT_COMMAND="history -a ; history -c; ps a | awk '/ bash$/ {system (\"kill -USR1 \" \$1)}'; $PROMPT_COMMAND"

Remarque:

Au départ, j'ai fait ma baie de test en envoyant un signal USR1 à bash avec killall, plus tard j'ai pensé à utiliser un nom de shell unique, une copie bash nommée testshell, pour éviter de tuer mes propres shells qui pouvaient fonctionner (processus cron par exemple) mais étrangement ce n'était pas le cas travail.

Le killall n'était pas assez sélectif, je l'ai remplacé par un script qui ne tue que les processus bash serrés sur un tty ( ps ane signale que les processus liés à un tty)

N'oubliez pas de redémarrer votre session pour avoir un nouveau PROMPT_COMMAND, lorsque je testais, j'ai vu plusieurs de mes tests précédents empilés dans PROMPT_COMMAND.

Emmanuel
la source
Vous n'avez pas besoin du nouvel utilisateur et de l'autre shell, vous pouvez simplement dire killalld'envoyer le signal uniquement aux processus du même utilisateur avec un -uargument supplémentaire , e.g. -u $ (whoami) `.
Philipp Wendler
Je pense que la syntaxe de csh est fausse ... @PhilippWendler pourriez-vous s'il vous plaît élaborer un peu?
lucacerone
La question concerne bash, j'ai donc utilisé la syntaxe bash. Je ne sais pas csh. Pour bash, killall -q -USR1 -u $(whoami) bashenvoie un signal USR1 à tous les processus bash de l'utilisateur actuel.
Philipp Wendler du
@Philipp ty btw Je n'ai pas testé la solution shell dédiée, c'était pour corriger un cas où le script cron bash s'exécuterait.
Emmanuel
@LucaCerone que j'ai réécrit semble fonctionner
Emmanuel
0

J'ai eu le même comportement étrange dans Yakuake lorsque j'ai essayé de créer une invite bash élaborée qui afficherait le nombre d'autres connexions. Le nombre n'a pas augmenté pour les onglets. Ma solution de contournement consistait à dire à Yakuake de s'exécuter à bashnouveau dans chaque nouvel onglet, en commençant essentiellement bash in bash. Cela a commencé à fonctionner parfaitement. Peut-être que cela vous aiderait aussi. Ma conjecture aveugle est que l'interface graphique pour la console charge bash se configure et les alimente ensuite aux instances bash. C'est peut-être de pouvoir jouer avec eux.

Barafu Albino
la source
J'ai essayé de charger bash en bash, mais sans succès :(
lucacerone