Hier ist das Endprodukt in Aktion auf einem Split-Screen-Xterm, von den Shell-Standardeinstellungen bis hin zur Arbeit mit nur wenigen Befehlen:
Ein rauerer Weg, dies zu tun, als im Screenshot gezeigt, könnte folgendermaßen aussehen:
PS1='$( { date ; fc -l -0 ; } >${TGT_PTY} )'$PS1
Wo ${TGT_PTY}
wäre das, was Sie aus dem tty
Befehl herausholen, wenn Sie tatsächlich eine interaktive Shell auf dem Bildschirm ausführen, auf dem Sie Ihre Ausgabe wünschen. Sie können auch jede beschreibbare Datei verwenden, da sie im Wesentlichen nur ein Ziel für die Umleitung von Dateien ist.
Ich verwende die pty- Syntax für Pseudo-Terminals, weil ich davon ausgehe, dass es sich um ein xterm handelt, aber Sie können genauso gut ein vt zuweisen - und Ihr gestreamter Verlauf ist immer nur eine CTRL-ALT-Fn
Tastenkombination entfernt. Wenn ich es wäre, könnte ich die beiden Begriffe kombinieren und es zu einer screen
oder einer tmux
Sitzung auf einem dedizierten vt machen ... Aber ich schweife ab.
Auf einem frisch gebooteten Computer werde ich mit der typischen /bin/login
Eingabeaufforderung auf einer typischen Linux- getty
Konsole begrüßt . Ich drücke, CTRL-ALT-F2
um auf eine weniger typische kmscon
Konsole zuzugreifen, die sich viel mehr wie eine xterm
als eine verhält tty
. Ich gebe den Befehl ein tty
und erhalte als Antwort /dev/pts/0
.
Im Allgemeinen multiplexen xterms ein einzelnes Endgerät mithilfe von Pseudo-Terminals in mehrere. Wenn Sie also in X11 etwas Ähnliches tun, indem Sie zwischen Terminal-Registerkarten oder Fenstern wechseln, erhalten Sie wahrscheinlich auch eine Ausgabe wie diese /dev/pts/[0-9]*
. Die virtuellen Terminalkonsolen, auf die mit CTRL-ALT-Fn
Tastenkombinationen zugegriffen wird, sind jedoch echte (er) Endgeräte und erhalten daher ihre eigene /dev/tty[0-9]*
Bezeichnung.
Dies ist der Grund, warum nach der Anmeldung bei Konsole 2, wenn ich tty
an der Eingabeaufforderung tippe, die Antwort lautet, /dev/pts/0
aber wenn ich dasselbe auf Konsole 1 mache, ist die Ausgabe /dev/tty1
. Auf jeden Fall mache ich dann wieder auf Konsole 2:
bash
PS1='$( { date ; fc -l -0 ; } >/dev/tty1 )'$PS1
Es ist kein Effekt erkennbar. Ich tippe noch ein paar Befehle ein und wechsle dann durch erneutes Drücken zu Konsole 1 CTRL-ALT-F1
. Und dort finde ich wiederholte Einträge, die <date_time>\n<hist#>\t<hist_cmd_string>
für jeden Befehl aussehen, den ich auf Konsole 2 eingegeben habe.
Wenn Sie nicht direkt auf ein Endgerät schreiben, könnte eine andere Option folgendermaßen aussehen:
TGT_PTY=
mkfifo ${TGT_PTY:=/tmp/shell.history.pipe}
{ echo 'OPENED ON:'
date
} >${TGT_PTY}
Und dann vielleicht ...
less +F ${TGT_PTY}
Der grobe Eingabeaufforderungsbefehl entspricht nicht Ihren Spezifikationen - keine Formatzeichenfolge für date
und auch keine Formatierungsoptionen fc
-, aber sein Mechanismus erfordert nicht viel: Jedes Mal, wenn Ihre Eingabeaufforderung den letzten Verlaufsbefehl ausgibt und das aktuelle Datum und die aktuelle Uhrzeit ausgeschrieben werden die von ${TGT_PTY}
Ihnen angegebene Datei. So einfach ist das.
Das Beobachten und Drucken des Shell-Verlaufs ist fc
der Hauptzweck. Es ist eine eingebaute Shell, auch wenn dies date
nicht der Fall ist. In zsh
fc
kann alle Arten von ausgefallenen Formatierungsoptionen bereitstellen, von denen einige für Zeitstempel gelten. Und natürlich, wie Sie oben beachten, bash
‚s history
kann das gleiche tun.
Im Interesse einer saubereren Ausgabe können Sie eine hier besser erläuterte Technik verwenden , um eine persistente Verfolgungsvariable in der aktuellen Shell festzulegen, obwohl Sie sie verfolgen und in Unterschalen innerhalb der Eingabeaufforderungssequenz verarbeiten müssen.
Hier ist ein tragbares Mittel zum Formatieren nach Ihren Vorgaben:
_HIST() { [ -z ${_LH#$1} ] ||
{ date "+${1}%t[%F %T]"
fc -nl -0
} >${TGT_PTY}
printf "(_LH=$1)-$1"
}
: "${_LH=0}"
PS1='${_LH##*[$(($(_HIST \!)))-9]}'$PS1
Ich implementiere den Zähler last_history$_LH
, der nur die neuesten Aktualisierungen verfolgt, damit Sie nicht zweimal denselben Verlaufsbefehl ausschreiben - zum Beispiel nur, indem Sie die Eingabetaste drücken. Es ist ein wenig Streit erforderlich, um die Variable in der aktuellen Shell zu erhöhen, damit sie ihren Wert behält, obwohl die Funktion in einer Subshell aufgerufen wird - was wiederum im Link besser erklärt wird .
Die Ausgabe sieht aus wie <hist#>\t[%F %T]\t<hist_cmd>\n
Aber das ist nur die voll portable Version. Mit bash
nur Schal builtins mit weniger und durch die Implementierung durchgeführt werden kann - und das ist wahrscheinlich wünschenswert , wenn man bedenkt , dass dies ein Befehl ist , dass jedes Mal , wenn Sie laufen drücken [ENTER]
. Hier sind zwei Möglichkeiten:
_HIST() { [ -z ${_LH#$1} ] || {
printf "${1}\t[%(%F %T)T]"
fc -nl -0
} >${TGT_PTY}
printf "(_LH=$1)-$1"
}
PROMPT_COMMAND=': ${_LH=0};'$PROMPT_COMMAND
PS1='${_LH##*[$(($(_HIST \!)))-9]}'$PS1
Alternativ können Sie mit bash
dem history
Befehl 's die _HIST
Funktion folgendermaßen definieren :
_HIST() { [ -z ${_LH#$1} ] ||
HISTTIMEFORMAT="[%F %T]<tab>" \
history 1 >${TGT_PTY}
printf "(_LH=$1)-$1"
}
Die Ausgabe für beide Methoden sieht ebenfalls so aus: <hist#>\t[%F %T]\t<hist_cmd>\n
Die history
Methode enthält jedoch einige führende Leerzeichen. Trotzdem glaube ich, dass die history
Zeitstempel der Methode genauer sind, da ich nicht glaube, dass sie warten müssen, bis der Befehl, auf den verwiesen wird, abgeschlossen ist, bevor sie ihren Stempel erhalten.
Sie können in beiden Fällen vermeiden, einen Status zu verfolgen, wenn Sie den Stream nur irgendwie filtern uniq
- wie Sie es vielleicht tun, mkfifo
wie ich bereits erwähnt habe.
Wenn Sie dies jedoch in der Eingabeaufforderung wie dieser tun, wird es immer nur so schnell wie nötig aktualisiert, indem Sie lediglich die Eingabeaufforderung aktualisieren. Es ist einfach.
Sie können auch etwas Ähnliches tun, wie Sie es tun, tail
aber lieber festlegen
HISTFILE=${TGT_PTY}
fn+1
zum Vergleichen aktualisiere ! Vielen Dank!