Ich versuche, ein Bash-Skript zu erstellen, das den Terminalverlauf in einer Datei namens hist.txt speichert. Die Verwendung history > hist.txt
scheint im Bash-Skript nicht zu funktionieren, funktioniert jedoch einwandfrei, wenn sie in der Befehlszeile ausgeführt wird.
Jede Anleitung wird sehr geschätzt.
Danke Judy
~/.bash_history
Datei des Benutzers lesen .Antworten:
Kurze Antwort
Führen Sie das Skript mit
source
oder aus.
:oder
Letzteres ist für verschiedene Schalen etwas kompatibler.
Lange Antwort
Diese Frage hebt einen wichtigen Punkt hervor, nämlich dass Shell-Skripte in ihrem eigenen Kontext ausgeführt werden. Betrachten Sie das folgende Shell-Skript, um zu sehen, was dies bedeutet:
Wenn Sie dies ausführen, erhalten Sie eine Ausgabe wie folgt:
Sie werden jedoch feststellen, dass Sie sich nach dem Ausführen des Skripts immer noch in dem Verzeichnis befinden, in dem Sie sich vor dem Ausführen befanden: Das
cd /
Innere des Skripts hat Ihre Sitzung nicht wirklich beeinflusst - es hat nur den Kontext beeinflusst, in dem das Skript ausgeführt wurde, in welchem wird für die Ausführung des Skripts erstellt und bei seiner Rückkehr zerstört.Der
source
Befehl liest 'Befehle aus dem Dateinamenargument im aktuellen Shell-Kontext und führt sie aus', sodass sich alle darin enthaltenen Befehlecd
auf Ihre aktuelle Sitzung auswirken. Wenn Sie das obige Skript ausführen, indem Sie es an übergeben, werdensource
Sie feststellen, dass Sie nach der Ausführung im Stammverzeichnis landen.In diesem Fall besteht das Problem darin, dass der
history
Befehl den Verlauf für den aktuellen Shell-Kontext angibt. Der Shell-Kontext, in dem Ihr Skript ohne Verwendung ausgeführt wird,source
hat keinen Verlauf, sodass nichts in die Ausgabedatei geschrieben wird. Wenn Sie es verwendensource
, wird es im richtigen Kontext ausgeführt und funktioniert wie erwartet.NB: Ist
source
eine Shell eingebaut, kein Programm an sich - in Bashsource
ist das gleichbedeutend mit.
, aber in einigen Shells.
funktioniert nur - habe ichsource
in dieser Antwort verwendet, weil es einfacher zu lesen ist als.
, aber für maximale Kompatibilität.
sollte verwendet werden.quelle
Beachten Sie zunächst, dass sich Ihr Verlauf bereits in einer Datei befindet. Wenn Sie Bash ausführen, lautet der Name normalerweise
~/.bash_history
. Genauer gesagt ist es das, worauf Sie die Variable eingestellt habenHISTFILE
. Wenn Sie es in eine andere Datei kopieren möchten, führen Sie es einfach auscat "$HISTFILE" > hist.txt
Der Grund, warum der
history
Befehl in einem Bash-Shell-Skript nicht funktioniert, liegt daran, dass Skripte in einer nicht interaktiven untergeordneten Shell Ihrer aktuellen Shell-Sitzung ausgeführt werden. Untergeordnete Shells erben nicht die gesamte Umgebung des übergeordneten Elements (also nicht alle festgelegten Variablen), sondern nur die exportierten Variablen. Zur Veranschaulichung gibt das folgende Skript den Wert der Variablen wieder$var
:Stellen Sie
$var
nun etwas ein und führen Sie das Skript aus:Als nächstes exportieren Sie zuerst die Variable:
Wie Sie sehen, steht die Variable nach dem Export für untergeordnete Shells zur Verfügung.
Wie bereits erwähnt, wird der Verlauf in der Datei gespeichert, auf die die Variable zeigt
$HISTFILENAME
. Da dies nicht standardmäßig exportiert wird, wird es beim Ausführen eines Skripts nicht festgelegt:Wie Sie im obigen Beispiel sehen können, wird die Variable
HISTFILE
in meiner normalen Shell-Sitzung festgelegt, ist jedoch beim Ausführen des Skripts leer.Um den Verlauf zu erhalten, haben Sie einige Möglichkeiten:
Der Standardwert
HISTFILE
ist$HOME/.bash_history
. Wenn Sie das nicht geändert haben, können Sie diesen Befehl einfach in Ihrem Skript ausführen:Sie können die
$HISTFILE
Variable an Ihr Skript übergeben undcat
das:Speichern Sie das Obige als
foo.sh
und führen Sie es wie folgt aus:Stellen Sie sicher, dass die Variable exportiert wird. Fügen Sie diese Zeile zu Ihren
~/.bash_profile
(falls vorhanden) oder~/.profile
(falls~/.bash_profile
nicht vorhanden) Dateien hinzu:Melden Sie sich dann ab und wieder an, und Sie sollten in der Lage sein,
history > hist.txt
ein Skript wie erwartet auszuführen . Dies liegt daran,export VAR
dass "$ VAR für Kinderschalen verfügbar machen" bedeutet. In der Praxis bedeutet dies, dass der Wert vonHISTFILE
von der nicht interaktiven Shell geerbt wird, mit der Sie Ihr Skript ausführen.Während das festgelegt
HISTFILE
wird, wurde es von der Shell, die das Skript ausführt, nicht gelesen. Damit es funktioniert, müssen Sie eshistory -r
zuerst lesen . Das ganze Skript würde so aussehen:Alternativ können Sie es auch manuell exportieren, bevor Sie das Skript ausführen:
Aber Sie müssen noch
history -r
im Skript.Sie können
source
es wie in der Antwort von @ p0llard vorgeschlagen .quelle