Ich weiß, dass diese Frage nicht obskur ist, da sie hier gestellt wird, immer aktualisiert (und hier dupliziert).
Was ich erreichen möchte, ist etwas anders. Ich mag die Idee nicht, dass meine Eingabeaufforderung alle ls
eine Datei neu schreibt Ich tippe (history -a; history -c; history -r
).
Ich möchte die Datei beim Beenden aktualisieren. Das ist einfach (eigentlich Standard), aber Sie müssen Folgendes anhängen, anstatt es neu zu schreiben:
shopt -s histappend
Wenn jetzt ein Terminal geschlossen wird, möchte ich alle anderen, die geöffnet bleiben, auf das Update aufmerksam machen.
Ich ziehe es vor, dies ohne Überprüfung über $PS1
zu tun bei jedem command
dass ich tippe. Ich denke, es wäre besser, eine Art Signal zu erfassen. Wie würdest du das machen? Wenn nicht möglich, vielleicht ein einfacher cronjob
?
Wie können wir dieses Rätsel lösen?
Akzeptierte Antwort:
Kreativ und involvierende Signale, sagen Sie? Okay:
trap on_exit EXIT
trap on_usr1 USR1
on_exit() {
history -a
trap '' USR1
killall -u "$USER" -USR1 bash
}
on_usr1() {
history -n
}
Schmeiß das in .bashrc
Los geht. Dies verwendet Signale, um jeder bash
mitzuteilen Prozess, um nach neuen Verlaufseinträgen zu suchen, wenn ein anderer beendet wird. Das ist ziemlich schrecklich, aber es funktioniert wirklich.
Wie funktioniert es?
trap
setzt einen Signalhandler für entweder ein Systemsignal oder eines der internen Ereignisse von Bash. Der EXIT
event ist jede kontrollierte Beendigung der Shell, während USR1
ist SIGUSR1
, ein bedeutungsloses Signal, das wir uns aneignen.
Immer wenn die Shell beendet wird, machen wir:
- Gesamten Verlauf explizit an die Datei anhängen.
- Deaktivieren Sie
SIGUSR1
Handler und sorgen dafür, dass diese Shell das Signal ignoriert. - Sende das Signal an alle laufenden
bash
Prozesse desselben Benutzers.
Wenn ein SIGUSR1
ankommt, wir:
- Lade alle neuen Einträge aus der Verlaufsdatei in die speicherinterne Verlaufsliste der Shell.
Aufgrund der Art und Weise, wie Bash mit Signalen umgeht, erhalten Sie die neuen Verlaufsdaten erst, wenn Sie Enter drücken das nächste Mal, also ist das an dieser Front nicht besser, als history -n
zu setzen in PROMPT_COMMAND
. Es erspart jedoch das ständige Lesen der Datei, wenn nichts passiert ist, und es wird überhaupt nicht geschrieben, bis die Shell beendet wird.
Hier gibt es jedoch noch ein paar Probleme. Die erste ist die Standardantwort auf SIGUSR1
ist die Shell zu beenden. Jede andere bash
Prozesse (z. B. laufende Shell-Skripte) werden beendet. .bashrc
wird nicht von nicht interaktiven Shells geladen. Stattdessen eine Datei namens BASH_ENV
geladen ist:Sie können diese Variable in Ihrer Umgebung global so einstellen, dass sie auf eine Datei zeigt mit:
trap '' USR1
darin, das Signal in ihnen zu ignorieren (was das Problem löst).
Verwandte:Terminalbefehl, um herauszufinden, ob ein Server virtuell oder physisch ist?Obwohl dies das tut, wonach Sie gefragt haben, wird die Bestellung, die Sie erhalten, etwas ungewöhnlich sein. Insbesondere Teile der Geschichte werden in unterschiedlichen Reihenfolgen wiederholt, wenn sie geladen und separat gespeichert werden. Das ist im Wesentlichen das, wonach Sie fragen, aber seien Sie sich bewusst, dass der Aufwärtspfeilverlauf an dieser Stelle viel weniger nützlich wird. Verlaufsersetzungen und dergleichen werden jedoch geteilt und funktionieren gut.