Tout d'abord, ce n'est pas un doublon de threads existants sur SE. J'ai lu ces deux discussions ( 1st , 2nd ) sur un meilleur historique de bash, mais aucune des réponses ne fonctionne - - Je suis d'ailleurs sur Fedora 15.
J'ai ajouté ce qui suit au .bashrc
fichier dans le répertoire utilisateur (/ home/aahan /), et cela ne fonctionne pas. Quelqu'un a une idée?
HISTCONTROL=ignoredups:erasedups # no duplicate entries
HISTSIZE=1000 # custom history size
HISTFILESIZE=100000 # custom history file size
shopt -s histappend # append to history, don't overwrite it
Prompt_COMMAND="history -a; history -c; history -r; $Prompt_COMMAND" # Save and reload the history after each command finishes
D'accord, c'est ce que je veux avec l'historique bash (priorité):
C'est en fait un comportement vraiment intéressant et j'avoue que j'ai sous-estimé la question au début. Mais d'abord les faits:
La fonctionnalité peut être obtenue de plusieurs manières, bien que chacune fonctionne un peu différemment. Notez que, dans chaque cas, pour que l'historique soit "transféré" vers un autre terminal (mis à jour), il faut appuyer sur Enter dans le terminal, où il/elle souhaite récupérer l'historique.
option 1:
shopt -s histappend
HISTCONTROL=ignoredups
Prompt_COMMAND="history -a; history -n; $Prompt_COMMAND"
Cela présente deux inconvénients:
option 2:
HISTCONTROL=ignoredups
Prompt_COMMAND="history -a; history -c; history -r; $Prompt_COMMAND"
(Oui, pas besoin de shopt -s histappend
et oui, cela doit être history -c
au milieu de Prompt_COMMAND
) Cette version présente également deux inconvénients importants:
history
peut donner une fausse sortie - voir ci-dessous.[Modifier] "Et le gagnant est ..."
option 3:
HISTCONTROL=ignoredups:erasedups
shopt -s histappend
Prompt_COMMAND="history -n; history -w; history -c; history -r; $Prompt_COMMAND"
C'est aussi loin que possible. Il s'agit de l'option uniquement pour que erasedups
et l'historique commun fonctionnent simultanément. This est probablement la solution finale à tous vos problèmes, Aahan.
Comme je l'ai mentionné, chacune des solutions ci-dessus fonctionne différemment. Mais l'interprétation la plus trompeuse du fonctionnement des paramètres vient de l'analyse de la sortie de la commande history
. Dans de nombreux cas, la commande peut donner une sortie false. Pourquoi? Parce que il est exécuté avant la séquence des autres commandes history
contenues dans le Prompt_COMMAND
! Cependant, lorsque vous utilisez la deuxième ou la troisième option, on peut surveiller les changements de .bash_history
contenu (en utilisant watch -n1 "tail -n20 .bash_history"
par exemple) et voyez quelle est la véritable histoire.
Tout dépend de la façon dont erasedups
fonctionne. Comme l'indique le manuel bash, "(...) erasedups
entraîne la suppression de toutes les lignes précédentes correspondant à la ligne actuelle de la liste d'historique avant l'enregistrement de cette ligne" . Donc, c'est vraiment ce que l'OP voulait (et pas seulement, comme je le pensais précédemment, qu'aucun doublon n'apparaisse en séquence) . Voici pourquoi chacun des history -.
les commandes doivent ou ne peuvent pas être dans le Prompt_COMMAND
:
history -n
a pour être là avant history -w
pour lire à partir de .bash_history
les commandes enregistrées depuis tout autre terminal,
history -w
has pour être là afin de sauvegarder l'historique dans un fichier et effacer les doublons,
history -a
ne doit pas y être placé au lieu de history -w
, car il ne déclenche pas l'effacement des doublons,
history -c
est également nécessaire car il empêche la corbeille du tampon d'historique après chaque commande,
et enfin, history -r
est nécessaire pour restaurer le tampon d'historique à partir du fichier, rendant ainsi finalement l'historique partagé entre les sessions de terminal.
Dans votre commande d'invite, vous utilisez le -c
commutateur. De man bash
:
- c Effacer la liste d'historique en supprimant toutes les entrées
Pour partager votre historique avec tous les terminaux ouverts, vous pouvez utiliser -n
:
- n Lire les lignes d'historique non lues depuis le fichier d'historique dans la liste d'historique actuelle. Ce sont des lignes ajoutées au fichier d'historique depuis le début de la session bash en cours.
La taille par défaut est également dans le manuel:
HISTSIZE Le nombre de commandes à retenir dans l'historique des commandes (voir HISTORIQUE ci-dessous). La valeur par défaut est 500.
Pour enregistrer des commandes multilignes:
L'option cmdhist Shell, si elle est activée, oblige le Shell à tenter d'enregistrer chaque ligne d'une commande multiligne dans la même entrée d'historique, en ajoutant des points-virgules si nécessaire pour préserver l'exactitude syntaxique. L'option lithist Shell oblige le Shell à enregistrer la commande avec des sauts de ligne intégrés au lieu de points-virgules.
De plus, vous ne devez pas faire précéder les commandes HIST * de export
- ce sont des variables uniquement bash et non des variables d'environnement: HISTCONTROL=ignoredups:erasedups
est suffisant.
C'est ce que j'ai trouvé et j'en suis satisfait jusqu'à présent…
alias hfix='history -n && history | sort -k2 -k1nr | uniq -f1 | sort -n | cut -c8- > ~/.tmp$$ && history -c && history -r ~/.tmp$$ && history -w && rm ~/.tmp$$'
HISTCONTROL=ignorespace
shopt -s histappend
shopt -s extglob
HISTSIZE=1000
HISTFILESIZE=2000
export HISTIGNORE="!(+(*\ *))"
Prompt_COMMAND="hfix; $Prompt_COMMAND"
REMARQUES:
HISTIGNORE
ignore toutes les commandes qui n'ont pas d'arguments. Cela peut ne pas être souhaitable pour certaines personnes et peut être laissé de côté.Utilisez-le à la place:
HISTCONTROL=ignoreboth
Cela ne fonctionne pas, car vous oubliez:
-n read all history lines not already read from the history file and append them to the history list
Mais il semble history -n
est juste bogué quand export HISTCONTROL=ignoreboth:erasedups
est en vigueur.
Permet d'expérimenter:
$ Prompt_COMMAND=
$ export HISTCONTROL=ignoreboth:erasedups
$ export HISTFILE=~/.bash_myhistory
$ HISTIGNORE='history:history -w'
$ history -c
$ history -w
Ici, nous activons l'effacement des doublons, basculons l'historique vers un fichier personnalisé, effaçons l'historique. Une fois toutes les commandes terminées, nous avons un fichier historique vide et une commande dans l'historique actuel.
$ history
$ cat ~/.bash_myhistory
$ history
$ 1 [2019-06-17 14:57:19] cat ~/.bash_myhistory
Ouvrez le deuxième terminal et exécutez également ces six commandes. Après ça:
$ echo "X"
$ echo "Y"
$ history -w
$ history
1 [2019-06-17 15:00:21] echo "X"
2 [2019-06-17 15:00:23] echo "Y"
Maintenant, votre historique actuel a deux commandes et le fichier historique a:
#1560772821
echo "X"
#1560772823
echo "Y"
Retour au premier terminal:
$ history -n
$ history
1 [2019-06-17 14:57:19] cat ~/.bash_myhistory
2 [2019-06-17 15:03:12] history -n
Huh ... aucune des commandes echo
n'est lue. Basculez à nouveau vers le deuxième terminal et:
$ echo "Z"
$ history -w
Maintenant, le fichier historique est:
#1560772821
echo "X"
#1560772823
echo "Y"
#1560773057
echo "Z"
Passez à nouveau au premier terminal:
$ history -n
$ history
1 [2019-06-17 14:57:19] cat ~/.bash_myhistory
2 [2019-06-17 15:03:12] history -n
echo "Z"
Tu peux voir ça echo "Z"
la commande est fusionnée en history -n
.
Un autre bug est dû au fait que les commandes sont lues dans l'historique par numéro de commande et non par heure de commande, je pense. Je m'attends à ce que d'autres commandes echo
apparaissent dans l'historique
Je suis allé avec une combinaison de réponses ici:
$ ./.secretfunction -user myuser -password mypassword
ne sera pas enregistré car il commence par l'espace.history*
et exit
à HISTIGNORE juste pour conserver ces commandes, y compris tout ce qui a été passé comme history | grep awesomecommand
sortir de là car je ne le voudrais pas normalement. Vous pouvez en ajouter d'autres comme: déconnexion, fg, bg, etc.HISTCONTROL=ignoreboth:erasedups:ignorespace
HISTIGNORE="history*:exit"
HISTFILE=~/.bash_history/.$(hostname)_history
shopt -s histappend
function historymerge {
history -n; history -w; history -c; history -r;
}
trap historymerge EXIT
Prompt_COMMAND="history -a; $Prompt_COMMAND"
Grep votre ~/pour Prompt_COMMAND pour vous assurer que vous ne l'avez pas déjà modifié avec history -a. J'ai également ajouté le format TIME/DATE HISTTIMEFORMAT="%x %r %Z "
J'ai aimé mais je n'ai pas inclus dans le bloc ci-dessus car c'est sensible aux paramètres régionaux.
erasedups ne supprime pas (comme chomp dans certaines langues) les espaces de début et de fin. Ceci est un bug. Les suppressions ne suppriment pas non plus toutes les entrées précédentes.
L'utilisation d'une combinaison de l'option 3 de @ rozcietrzewiacz avec un piège de sortie permettra aux terminaux de conserver leurs propres sessions d'historique indépendantes qui convergent à la fermeture. Il semble même fonctionner correctement avec plusieurs sessions sur différentes machines partageant un répertoire de base distant.
export HISTSIZE=5000
export HISTFILESIZE=5000
export HISTCONTROL=ignorespace:erasedups
shopt -s histappend
function historymerge {
history -n; history -w; history -c; history -r;
}
trap historymerge EXIT
Prompt_COMMAND="history -a; $Prompt_COMMAND"
La fonction historymerge
charge les lignes hors session à partir du fichier historique, les combine avec l'historique des sessions, écrit un nouveau fichier historique avec déduplication (écrasant ainsi les lignes en double précédemment ajoutées) et recharge l'historique.
En gardant history -a
dans l'invite minimise le risque de perte d'historique, car il met à jour le fichier d'historique sans déduplication à chaque commande.
Enfin, le piège déclenche historymerge
à la fermeture de la session pour un fichier d'historique propre à jour avec les commandes de la session la plus récemment fermée qui se sont propagées à la fin du fichier (je pense).
Avec cela, chaque session de terminal aura sa propre histoire indépendante à partir du lancement. Je trouve cela plus utile car j'ai tendance à avoir différents terminaux ouverts pour différentes tâches (je veux donc répéter différentes commandes dans chacun). C'est aussi heureusement plus simple que de donner un sens à plusieurs terminaux essayant constamment de resynchroniser leur historique ordonné de manière distribuée (bien que vous puissiez toujours le faire délibérément en utilisant la fonction historymerge
avec certaines sessions ou tous).
Notez que vous souhaiterez que vos limites de taille soient suffisamment grandes pour contenir la longueur d'historique souhaitée plus le volume de lignes non dédupliquées qui peuvent être ajoutées par toutes les sessions actives simultanément. 5000 me suffit en grande partie grâce à l'utilisation extensive de HISTIGNORE
pour filtrer les commandes de faible valeur contenant du spam.