Préserver l'historique bash dans plusieurs fenêtres de terminal

525

J'ai toujours plus d'un terminal ouvert. N'importe où de deux à dix, faisant divers morceaux et bobs. Maintenant, disons que je redémarre et ouvre un autre ensemble de terminaux. Certains se souviennent de certaines choses, d'autres oublient.

Je veux une histoire qui:

  • Se souvient de tout de chaque terminal
  • Est instantanément accessible à partir de chaque terminal (par exemple, si je suis lsdans un, passez à un autre terminal déjà en marche puis appuyez sur le haut, lss'affiche)
  • N'oubliez pas la commande s'il y a des espaces à l'avant de la commande.

Tout ce que je peux faire pour que Bash fonctionne plus comme ça?

Oli
la source
57
Je peux voir l'avantage de cela, mais personnellement, je détesterais cela dans ma coquille. Je laisse généralement 3 ou 4 onglets ouverts dans mon terminal pour des utilisations très spécifiques: un pour exécuter 'make', un avec vi, un pour exécuter des choses, etc. Ainsi, lorsque je compile, je vais à l'onglet 1, je tape 'arrive, et ainsi de suite. Ceci est extrêmement productif pour moi. Donc, si, tout à coup, je vais dans l'onglet "make" et que je tape et qu'une commande grep aléatoire apparaît, je serais vraiment énervé! Juste une note personnelle cependant
axel_c
4
@axel_c c'est assez vrai. Je ne peux pas penser à un moyen intelligent de le faire lorsque les terminaux existants ne voient que leur propre histoire mais que les nouveaux voient une liste chronologiquement précise de commandes.
Oli
8
@Oli a écrit: "Je ne peux pas penser à un moyen intelligent de le faire lorsque les terminaux existants ne voient que leur propre histoire mais que les nouveaux voient une liste chronologiquement précise de commandes." Que diriez - vous (non essayé): export PROMPT_COMMAND="history -a; $PROMPT_COMMAND". Les shells existants ajouteront chaque commande au fichier historique pour que les nouveaux shells puissent le voir, mais ne montreront que leurs propres historiques.
Chris Page
2
Souhaitez-vous que l'historique soit stocké séparément ou fusionné dans un seul fichier d'historique?
kbyrd
3
La réponse courte est: ce n'est pas prévu par les développeurs bash. Les solutions basées sur le rinçage puis la relecture de l’histoire fonctionnent probablement, mais méfiez-vous de Shlemiel le peintre . En termes simples: la quantité de travail de traitement entre chaque commande est proportionnelle à la taille de l'historique.
Stéphane Gourichon

Réponses:

328

Ajouter ce qui suit à ~ / .bashrc

# Avoid duplicates
export HISTCONTROL=ignoredups:erasedups  
# When the shell exits, append to the history file instead of overwriting it
shopt -s histappend

# After each command, append to the history file and reread it
export PROMPT_COMMAND="${PROMPT_COMMAND:+$PROMPT_COMMAND$'\n'}history -a; history -c; history -r"
Pablo R.
la source
20
Le problème avec cette solution PROMPT_COMMAND est que les numéros de chaque élément d’historique changent après chaque commande :(. Par exemple, si vous tapez history et 1) ls 2) rm, vous devez! 1 pour répéter 1, le numéro d’historique peut changer et pourrait exécuter la commande rm ...
Chris Kimpton
2
Lorsque je le fais, les autres commandes déjà ouvertes n'ont pas la dernière commande entrée lorsque j'appuie sur «Haut» jusqu'à ce que j'émette une commande dans ce terminal. Est-ce attendu? Si tel est le cas, existe-t-il un moyen de modifier réellement l'historique des autres terminaux instantanément?
Suan
7
@ Suan, cela me semble juste en fonction des commandes. J'ai constaté que nous pouvons émettre une commande null (il suffit d'appuyer sur la touche Entrée) pour que l'historique soit mis à jour.
Sage
3
En réalité history -a(...) ne provoque pas l’effacement des doublons selon cette réponse à la question Bash history: «ignoredups» et «erasedups» mettant en conflit l’historique des différentes sessions . Cette réponse donne également la séquence de history -<option>commandes qui fonctionne avec le HISTCONTROL=ignoredups:erasedupsréglage.
Piotr Dobrogost
23
Il n'y a aucune raison pour exportles variables HISTCONTROLet PROMPT_COMMAND: vous les définissez dans .bashrcafin qu'elles soient définies dans chaque shell (même dans les non-interactives, ce qui est également inutile).
dolmen
248

Donc, tout cela est lié à mon histoire .bashrc:

export HISTCONTROL=ignoredups:erasedups  # no duplicate entries
export HISTSIZE=100000                   # big big history
export HISTFILESIZE=100000               # big big history
shopt -s histappend                      # append to history, don't overwrite it

# Save and reload the history after each command finishes
export PROMPT_COMMAND="history -a; history -c; history -r; $PROMPT_COMMAND"

Testé avec bash 3.2.17 sur Mac OS X 10.5, bash 4.1.7 sur 10.6.

kch
la source
3
Hum .. Cela annule la possibilité d'utiliser $! 34, car les numéros de commande changent à chaque invite. Existe-t-il une solution de contournement @Davide @Schof @kch?
5
Utilisez ceci pour obtenir une histoire infinie: bash histoire éternelle . CEPENDANT, il est complémentaire du code ci-dessus, car il ne sera pas rechargé automatiquement.
7
FYI Aucune des solutions mentionnées ici ne peut résoudre le problème suivant. J'ai deux fenêtres shell A et B. Dans la fenêtre shell A, je cours sleep 9999et (sans attendre la fin du sommeil) dans la fenêtre shell B, je veux pouvoir voir sleep 9999l'historique Bash.
Pts
1
@pts moi aussi visait un comportement réel, mais j'ai alors réalisé qu'il était plus pratique de disposer d'histoires spécifiques à un terminal qui facilitent le travail sur différentes tâches dans différents terminaux. J'ai trouvé cela très utile: stackoverflow.com/questions/338285/#answer-7449399 Sur cette base, je me suis fabriqué un alias appelé hrefqui actualise instantanément l'historique de mon terminal actuel et nettoie le fichier d'historique. Chaque fois que j'ouvre un nouveau terminal, ce nettoyage / synchronisation est exécuté dans mon fichier bashrc afin que le nouveau terminal possède l'historique le plus récent. J'utilise cela avechistory -a
trusktr
6
Il n'y a pas de raison aux exportvariables: vous les définissez de .bashrcmanière à ce qu'elles soient définies dans chaque shell (même dans les non-interactives, ce qui représente également un gaspillage de ressources)
dolmen
117

Voici ma tentative de partage de l'historique de session Bash. Cela permettra le partage de l'historique entre les sessions bash de manière à ce que le compteur d'historique ne soit pas mélangé et que l'expansion de l'historique !numberne fonctionne pas (avec certaines contraintes).

Utilisation de Bash version 4.1.5 sous Ubuntu 10.04 LTS (Lucid Lynx).

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

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

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

PROMPT_COMMAND=_bash_history_sync

Explication:

  1. Ajoute la ligne qui vient d'être entrée à la $HISTFILE(valeur par défaut .bash_history). Cela fera $HISTFILEcroître d'une ligne.

  2. Si vous définissez la variable spéciale $HISTFILESIZEsur une valeur quelconque, Bash ne tronquera $HISTFILEpas plus de $HISTFILESIZElignes en supprimant les entrées les plus anciennes.

  3. Effacer l'historique de la session en cours. Cela réduira le compteur d'historique du montant de $HISTSIZE.

  4. Lisez le contenu de $HISTFILEet insérez-le dans l'historique de la session en cours. cela relèvera le compteur d’histoire du nombre de lignes contenues $HISTFILE. Notez que le nombre de lignes de $HISTFILEn'est pas nécessairement $HISTFILESIZE.

  5. La history()fonction remplace l'historique intégré pour s'assurer que l'historique est synchronisé avant qu'il ne soit affiché. Ceci est nécessaire pour l’extension de l’historique par numéro (plus à ce sujet plus tard).

Plus d'explication:

  • L'étape 1 garantit que la commande de la session en cours d'exécution est écrite dans le fichier historique global.

  • L'étape 4 garantit que les commandes des autres sessions sont lues dans l'historique de la session en cours.

  • L'étape 4 augmentant le compteur d'historique, nous devons le réduire d'une manière ou d'une autre. Ceci est fait à l'étape 3.

  • À l'étape 3, le compteur d'historique est réduit de $HISTSIZE. À l'étape 4, le compteur d'historique est généré par le nombre de lignes insérées $HISTFILE. À l'étape 2, nous nous assurons que le nombre de lignes de $HISTFILEest exactement $HISTSIZE(cela signifie que cela $HISTFILESIZEdoit être identique à $HISTSIZE).

A propos des contraintes de l'expansion de l'histoire:

Lorsque vous utilisez l’extension d’historique par numéro, vous devez toujours rechercher le numéro immédiatement avant de l’utiliser. Cela signifie qu'aucune invite bash ne s'affiche entre la recherche du numéro et son utilisation. Cela signifie généralement pas d'entrée et pas de ctrl + c.

En règle générale, une fois que vous avez plus d'une session Bash, rien ne garantit qu'une extension d'historique numérotée conserve sa valeur entre deux affichages d'invite Bash. Parce que quand PROMPT_COMMANDest exécuté, l'historique de toutes les autres sessions Bash est intégré à l'historique de la session en cours. Si une autre session bash a une nouvelle commande, les numéros d'historique de la session en cours seront différents.

Je trouve cette contrainte raisonnable. Quoi qu'il en soit, je dois regarder le numéro chaque fois parce que je ne me souviens pas de chiffres historiques arbitraires.

D'habitude j'utilise l'extension d'historique par numéro comme ceci

$ history | grep something #note number
$ !number

Je recommande d'utiliser les options suivantes de Bash.

## reedit a history substitution line if it failed
shopt -s histreedit
## edit a recalled history line before executing
shopt -s histverify

Bugs étranges:

L'exécution de la commande d'historique associée à quoi que ce soit aura pour résultat que cette commande sera répertoriée deux fois dans l'historique. Par exemple:

$ history | head
$ history | tail
$ history | grep foo
$ history | true
$ history | false

Tous seront répertoriés dans l'historique deux fois. Je ne sais pas pourquoi.

Idées d'améliorations:

  • Modifiez la fonction _bash_history_sync()pour qu’elle ne s’exécute pas à chaque fois. Par exemple, il ne devrait pas s'exécuter après CTRL+Cl'invite. J'utilise souvent CTRL+Cde supprimer une longue ligne de commande quand je décide que je ne veux pas exécuter cette ligne. Parfois, je dois utiliser CTRL+Cpour arrêter un script d'achèvement Bash.

  • Les commandes de la session en cours doivent toujours être les plus récentes de l'historique de la session en cours. Cela aura également pour effet secondaire qu'un numéro d'historique donné conserve sa valeur pour les entrées d'historique de cette session.

lesmana
la source
1
Pourquoi pas "history -n" (lignes de rechargement pas encore chargées) au lieu de "history -c; history -r"?
Graham
@ Graham: Je ne voulais pas utiliser history -nparce que ça dérange le compteur d'historique. En outre, j'ai trouvé history -ntrop peu fiable.
Lesmana
1
Un inconvénient: les commandes avec des chaînes multilignes sont normalement toujours conservées dans la session en cours. Avec cette astuce, ils sont instantanément divisés en lignes individuelles. L'utilisation de -n pour -c -r n'aide pas, ni cmdhiste ni lithiste. Je ne pense pas qu'il y ait une solution de contournement à ce stade.
Jo Liss
24
Après avoir essayé cela pendant un moment, j'ai en fait constaté qu'exécuter seulement history -a, sans -cet -r, était plus convivial du point de vue de la convivialité (bien que ce ne soit pas ce que la question demandait). Cela signifie que les commandes que vous exécutez sont disponibles instantanément dans les nouveaux shells avant même de quitter le shell en cours, mais pas dans les shells exécutés simultanément. De cette façon, Arrow-Up sélectionne toujours toujours les commandes de la dernière session de la session en cours , ce que je trouve beaucoup moins déroutant.
Jo Liss
remarquablement bonne réponse, cela fonctionne de manière fiable contrairement à la plus commune "histoire - une; histoire - n"
RichVel
42

Je ne suis au courant d'aucune façon d'utiliser bash. Mais c'est l'une des fonctionnalités les plus populaires de zsh.
Personnellement, je préfère zshplus, bashalors je recommande de l'essayer.

Voici la partie de mon .zshrcqui traite de l'histoire:

SAVEHIST=10000 # Number of entries
HISTSIZE=10000
HISTFILE=~/.zsh/history # File
setopt APPEND_HISTORY # Don't erase history
setopt EXTENDED_HISTORY # Add additional data to history like timestamp
setopt INC_APPEND_HISTORY # Add immediately
setopt HIST_FIND_NO_DUPS # Don't show duplicates in search
setopt HIST_IGNORE_SPACE # Don't preserve spaces. You may want to turn it off
setopt NO_HIST_BEEP # Don't beep
setopt SHARE_HISTORY # Share history between session/terminals
Maciej Piechotka
la source
16

Pour ce faire, vous devrez ajouter deux lignes à votre ~/.bashrc:

shopt -s histappend
PROMPT_COMMAND="history -a;history -c;history -r;$PROMPT_COMMAND"

De man bash:

Si l'option de shell histappend est activée (voir la description de shopt sous SHELL BUILTIN COMMANDS ci-dessous), les lignes sont ajoutées au fichier d'historique, sinon le fichier d'historique est écrasé.

Chris Down
la source
10

Vous pouvez modifier votre invite BASH pour exécuter les "history -a" et "history -r" proposés par Muerr:

savePS1=$PS1

(au cas où vous gâcher quelque chose, ce qui est presque garanti)

PS1=$savePS1`history -a;history -r`

(notez qu'il s'agit de contrôles en arrière-plan; ils exécuteront l'historique -a et l'historique -r à chaque invite. Comme ils ne génèrent aucun texte, votre invite ne sera pas modifiée.

Une fois que vous avez configuré votre variable PS1 comme vous le souhaitez, définissez-la définitivement dans votre fichier ~ / .bashrc.

Si vous souhaitez revenir à votre invite d'origine lors du test, procédez comme suit:

PS1=$savePS1

J'ai effectué des tests de base sur cette opération pour vérifier son efficacité, mais je ne peux parler d'aucun effet secondaire résultant de son exécution history -a;history -rà chaque invite.

Schof
la source
2
La solution de kch fonctionne mieux que la mienne. J'utilise maintenant sa solution dans mon .bashrc.
9

Si vous avez besoin d'une solution de synchronisation de l'historique bash ou zsh qui résout également le problème ci-dessous, consultez-la à l' adresse http://ptspts.blogspot.com/2011/03/how-to-automatically-synchronize-shell.html.

Le problème est le suivant: J'ai deux fenêtres de shell A et B. Dans la fenêtre de shell A, je cours sleep 9999et (sans attendre la fin du sommeil) dans la fenêtre de shell B, je veux pouvoir voir sleep 9999l'historique de bash.

La plupart des solutions proposées ici ne résoudront pas ce problème car elles écrivent leurs modifications d'historique dans le fichier d'historique en utilisant PROMPT_COMMANDou PS1, les deux s'exécutant trop tard, uniquement après la fin de la sleep 9999commande.

pts
la source
1
C'est une bonne solution, mais j'ai cependant quelques questions. 1. Puis-je utiliser le fichier .bash_history d'origine, je ne souhaite pas qu'un autre fichier d'historique de bash existe dans mon $ HOME 2. Peut-être devriez-vous envisager de définir un dépôt github pour cela.
Weynhamz
Il semble que le hook de débogage soit en conflit avec bashdb, la sortie suivante chaque fois que je démarre une session bash. `` `bash debugger, bashdb, version 4.2-0.8 Copyright © 2002, 2003, 2004, 2006, 2006, 2007, 2008, 2009, 2010, 2011 Rocky Bernstein Ceci est un logiciel libre couvert par la licence publique générale GNU. changez-le et / ou distribuez-en des copies sous certaines conditions. ** Erreur de débogage interne _Dbg_is_file (): argument de fichier null bash: _Dbg_filenames [$ nom complet]: indice de tableau incorrect `` `
weynhamz
@Techlive Zheng: 1. Le fichier .bash_history d'origine n'est délibérément pas pris en charge, car .merged_bash_history utilise un format de fichier différent. Par conséquent, si le fichier .merged_bash_history ne se charge pas correctement, bash ne gênera pas accidentellement l'historique accumulé. La robustesse, par conception, sera conservée telle quelle. 2. Un repo github est une bonne idée en général, mais je n’ai pas le temps de le garder pour ce projet, donc je ne le fais pas. - Oui, cela entre en conflit avec bashdb et il n’ya pas de solution simple (ils utilisent les mêmes hooks). Je n'ai pas l'intention de travailler sur un correctif, mais j'accepte les correctifs.
pts
D'accord, merci. Je suis venu avec une sulotion beaucoup plus simple et meilleure.
Weynhamz
@TechliveZheng: Souhaitez-vous partager votre solution simple et meilleure avec nous, afin que nous puissions tous en tirer profit? (Dans l'affirmative, veuillez ajouter une réponse à la question.)
pts
8

Vous pouvez utiliser history -apour ajouter l'historique de la session en cours à l'historique, puis utiliser history -rsur les autres terminaux pour lire l'historique. 

jtimberman
la source
8

Bon, finalement, cela m'a agacé de trouver une solution décente:

# Write history after each command
_bash_history_append() {
    builtin history -a
}
PROMPT_COMMAND="_bash_history_append; $PROMPT_COMMAND"

Ce que cela fait est en quelque sorte une fusion de ce qui a été dit dans ce fil, sauf que je ne comprends pas pourquoi rechargerais l'historique global après chaque commande. Je me soucie très rarement de ce qui se passe dans les autres terminaux, mais je lance toujours une série de commandes, disons dans un terminal:

make
ls -lh target/*.foo
scp target/artifact.foo vm:~/

(Exemple simplifié)

Et dans un autre:

pv ~/test.data | nc vm:5000 >> output
less output
mv output output.backup1

Pas question que je veuille que la commande soit partagée

Yarek T
la source
1
La raison pour laquelle vous rechargez l'historique après chaque commande est qu'il s'agit du comportement requis par la question (et que cela ne répond donc pas à la question telle qu'elle est posée).
Michael Homer
2
@MichaelHomer Foire. N'hésitez pas à invoquer un vote négatif pour que la réponse reste au bas de la liste; toutefois, je tiens à ce que le PO ne se rende pas compte à quel point le comportement demandé serait mauvais, et au fait que cette question est très réaliste.
Yarek T
3
Op ici, ouais, c'est un compromis juste. Ma plainte principale est que je perdais l'histoire. Cela devrait empêcher cela, même si cela ne signifie pas des mises à jour instantanées d'une session à l'autre.
Oli
7

Voici une alternative que j'utilise. C'est fastidieux mais cela résout le problème mentionné par @axel_c: vous souhaiterez parfois avoir une instance d'historique distincte dans chaque terminal (une pour make, une pour la surveillance, une pour vim, etc.).

Je conserve un fichier d'historique annexé distinct que je mets à jour en permanence. J'ai mappé ce qui suit sur un raccourci clavier:

history | grep -v history >> ~/master_history.txt

Ceci ajoute tout l'historique du terminal actuel à un fichier appelé master_history.txt dans votre répertoire personnel.

J'ai aussi un raccourci clavier séparé pour rechercher dans le fichier d'historique principal:

cat /home/toby/master_history.txt | grep -i

J'utilise un chat | grep car il laisse le curseur à la fin pour entrer dans ma regex. Une façon moins laide de le faire serait d’ajouter quelques scripts sur votre chemin pour accomplir ces tâches, mais les raccourcis clavier fonctionnent à mes fins. Je vais aussi périodiquement extraire l'historique des autres hôtes sur lesquels j'ai travaillé et l'ajouter à mon fichier master_history.txt.

Il est toujours agréable de pouvoir rapidement rechercher et trouver cette regex complexe que vous avez utilisée ou cet étrange perl one-liner que vous avez créé il y a 7 mois.

Toby
la source
6

Je peux proposer un correctif pour ce dernier problème: assurez-vous que la variable env HISTCONTROL ne spécifie pas "ignorespace" (ou "ignoreboth").

Mais je ressens votre douleur avec plusieurs sessions simultanées. Ce n'est tout simplement pas bien géré en Bash.

jmanning2k
la source
6

Voici mon amélioration à la réponse de @ lesmana . La principale différence est que les fenêtres simultanées ne partagent pas l'historique. Cela signifie que vous pouvez continuer à travailler dans vos fenêtres sans que le contexte des autres fenêtres ne soit chargé dans vos fenêtres actuelles.

Si vous tapez explicitement 'historique', OU si vous ouvrez une nouvelle fenêtre, vous obtenez l'historique de toutes les fenêtres précédentes.

De plus, j'utilise cette stratégie pour archiver toutes les commandes jamais tapées sur ma machine.

# Consistent and forever bash history
HISTSIZE=100000
HISTFILESIZE=$HISTSIZE
HISTCONTROL=ignorespace:ignoredups

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

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

history() {                  #5
  _bash_history_sync_and_reload
  builtin history "$@"
}

export HISTTIMEFORMAT="%y/%m/%d %H:%M:%S   "
PROMPT_COMMAND='history 1 >> ${HOME}/.bash_eternal_history'
PROMPT_COMMAND=_bash_history_sync;$PROMPT_COMMAND
rouble
la source
5

J'ai choisi de mettre l'historique dans un fichier à la fois, car plusieurs personnes peuvent travailler sur le même serveur. La séparation des commandes de chaque session facilite l'audit.

# Convert /dev/nnn/X or /dev/nnnX to "nnnX"
HISTSUFFIX=`tty | sed 's/\///g;s/^dev//g'`
# History file is now .bash_history_pts0
HISTFILE=".bash_history_$HISTSUFFIX"
HISTTIMEFORMAT="%y-%m-%d %H:%M:%S "
HISTCONTROL=ignoredups:ignorespace
shopt -s histappend
HISTSIZE=1000
HISTFILESIZE=5000

L'histoire ressemble maintenant à:

user@host:~# test 123
user@host:~# test 5451
user@host:~# history
1  15-08-11 10:09:58 test 123
2  15-08-11 10:10:00 test 5451
3  15-08-11 10:10:02 history

Avec les fichiers ressemblant à:

user@host:~# ls -la .bash*
-rw------- 1 root root  4275 Aug 11 09:42 .bash_history_pts0
-rw------- 1 root root    75 Aug 11 09:49 .bash_history_pts1
-rw-r--r-- 1 root root  3120 Aug 11 10:09 .bashrc
Alitch
la source
3

Ici, je vais signaler un problème avec

export PROMPT_COMMAND="${PROMPT_COMMAND:+$PROMPT_COMMAND$'\n'}history -a; history -c; history -r"

et

PROMPT_COMMAND="$PROMPT_COMMAND;history -a; history -n"

Si vous utilisez la source ~ / .bashrc, le $ PROMPT_COMMAND sera comme

"history -a; history -c; history -r history -a; history -c; history -r"

et

"history -a; history -n history -a; history -n"

Cette répétition se produit chaque fois que vous exécutez 'source ~ / .bashrc'. Vous pouvez vérifier PROMPT_COMMAND après chaque fois que vous exécutez 'source ~ / .bashrc' en exécutant 'echo $ PROMPT_COMMAND'.

Vous pouvez voir que certaines commandes sont apparemment brisées: "history -n history -a". Mais la bonne nouvelle est que cela fonctionne toujours, car d'autres pièces forment toujours une séquence de commandes valide (entraînant simplement des coûts supplémentaires en raison de l'exécution répétitive de commandes. Et pas si propre.)

Personnellement j'utilise la version simple suivante:

shopt -s histappend
PROMPT_COMMAND="history -a; history -c; history -r"

qui a la plupart des fonctionnalités alors aucun problème tel que mentionné ci-dessus.

Un autre point à souligner est qu’il n’ya vraiment rien de magique . PROMPT_COMMAND n'est qu'une simple variable d'environnement bash. Les commandes qu'il contient sont exécutées avant que vous obteniez prompt bash (le signe $). Par exemple, votre PROMPT_COMMAND est "echo 123" et vous exécutez "ls" dans votre terminal. L'effet est similaire à l'exécution de "ls; echo 123".

$ PROMPT_COMMAND="echo 123"

output (comme si vous exécutiez 'PROMPT_COMMAND = "echo 123"; $ PROMPT_COMMAND'):

123

Exécutez ce qui suit:

$ echo 3

sortie:

3
123

"history -a" est utilisé pour écrire les commandes d'historique en mémoire dans ~ / .bash_history

"history -c" est utilisé pour effacer les commandes d'historique en mémoire

"history -r" est utilisé pour lire les commandes d'historique de ~ / .bash_history dans la mémoire

Voir l'explication des commandes d'historique ici: http://ss64.com/bash/history.html

PS: Comme d'autres utilisateurs l'ont souligné, l' exportation n'est pas nécessaire. Voir: utilisation de l'export dans .bashrc

fstang
la source
2

J'ai écrit un script pour définir un fichier d'historique par session ou tâche, en fonction des éléments suivants.

        # write existing history to the old file
        history -a

        # set new historyfile
        export HISTFILE="$1"
        export HISET=$1

        # touch the new file to make sure it exists
        touch $HISTFILE
        # load new history file
        history -r $HISTFILE

Il n’est pas nécessaire de sauvegarder toutes les commandes de l’historique, mais il enregistre celles qui me tiennent à cœur et il est plus facile de les récupérer que de passer en revue chaque commande. Ma version répertorie également tous les fichiers d’historique et offre la possibilité de les parcourir tous.

Source complète: https://github.com/simotek/scripts-config/blob/master/hiset.sh

simotek
la source
2

Voici une solution qui ne mélange pas l'historique des sessions individuelles!

Fondamentalement, il faut stocker l'historique de chaque session séparément et le recréer à chaque invite. Oui, il utilise plus de ressources, mais ce n'est pas aussi lent que cela puisse paraître - le retard commence à être perceptible uniquement si vous avez plus de 100 000 entrées dans l'historique.

Voici la logique de base:

# on every prompt, save new history to dedicated file and recreate full history
# by reading all files, always keeping history from current session on top.
update_history () {
  history -a ${HISTFILE}.$$
  history -c
  history -r
  for f in `ls ${HISTFILE}.[0-9]* | grep -v "${HISTFILE}.$$\$"`; do
    history -r $f
  done
  history -r "${HISTFILE}.$$"
}
export PROMPT_COMMAND='update_history'

# merge session history into main history file on bash exit
merge_session_history () {
  cat ${HISTFILE}.$$ >> $HISTFILE
  rm ${HISTFILE}.$$
}
trap merge_session_history EXIT

Consultez cette synthèse pour une solution complète, comprenant des garanties et des optimisations de performances.

Jan Warchoł
la source
1

Cela fonctionne pour ZSH

##############################################################################
# History Configuration for ZSH
##############################################################################
HISTSIZE=10000               #How many lines of history to keep in memory
HISTFILE=~/.zsh_history     #Where to save history to disk
SAVEHIST=10000               #Number of history entries to save to disk
#HISTDUP=erase               #Erase duplicates in the history file
setopt    appendhistory     #Append history to the history file (no overwriting)
setopt    sharehistory      #Share history across terminals
setopt    incappendhistory  #Immediately append to the history file, not just when a term is killed
Mulki
la source
malheureusement la question est strictement pour bash :-)
Jaleks
1
C'est le premier résultat sur google quand je recherche aussi zsh ... Je pensais que cela pourrait aider
Mulki
3
Vous devriez poser une nouvelle question, "Préserver l'historique zsh dans plusieurs fenêtres de terminal", en supposant qu'il n'en existe pas déjà un. C'est parfaitement correct - même encouragé - de répondre à votre propre question si c'est une bonne question.
Oli
1

Je voulais depuis longtemps cela, en particulier la possibilité de récupérer une commande en fonction de son exécution afin de l'exécuter à nouveau dans un nouveau projet (ou de rechercher un répertoire à l'aide d'une commande). J'ai donc assemblé cet outil , qui combine les solutions précédentes pour stocker un historique global de la CLI avec un outil de capture interactif appelé percol (mappé sur C ^ R). La première machine que je commence à utiliser est toujours lisse, maintenant avec un historique CLI âgé de plus de 2 ans.

En ce qui concerne les touches fléchées, il ne perturbe pas l’historique local de la CLI, mais vous permet d’accéder assez facilement à l’historique global (que vous pouvez également mapper sur autre chose que C ^ R).

Gordon Wells
la source
c'est pour zsh?
Sjas
1
oui, je l'ai initialement fait pour zsh. Je l'ai eu bien pour bash et le poisson aussi. Faites-moi savoir si cela fonctionne ou non. Je ne l’ai pas changé depuis un moment et je ne suis pas certain de la clarté de mes instructions d’installation
Gordon Wells
1

Parce que je préfère une histoire infinie qui est enregistrée dans un fichier personnalisé. Je crée cette configuration sur https://stackoverflow.com/a/19533853/4632019 :

export HISTFILESIZE=
export HISTSIZE=
export HISTTIMEFORMAT="[%F %T] "

export HISTFILE=~/.bash_myhistory
PROMPT_COMMAND="history -a; history -r; $PROMPT_COMMAND"
Eugen Konkov
la source
-1

Voici l'extrait de mon .bashrc et de courtes explications là où c'est nécessaire:

# The following line ensures that history logs screen commands as well
shopt -s histappend

# This line makes the history file to be rewritten and reread at each bash prompt
PROMPT_COMMAND="$PROMPT_COMMAND;history -a; history -n"
# Have lots of history
HISTSIZE=100000         # remember the last 100000 commands
HISTFILESIZE=100000     # start truncating commands after 100000 lines
HISTCONTROL=ignoreboth  # ignoreboth is shorthand for ignorespace and     ignoredups

HISTFILESIZE et HISTSIZE sont des préférences personnelles et vous pouvez les modifier selon vos goûts.

Hopping Bunny
la source