Bearbeiten: Diese Frage war ursprünglich Bash-spezifisch. Ich hätte immer noch lieber eine Bash-Lösung, aber wenn es eine gute Möglichkeit gibt, dies in einer anderen Shell zu tun, dann wäre das auch nützlich, um es zu wissen!
Okay, Top-Level-Beschreibung des Problems. Ich möchte in der Lage sein, einen Bash-Hook hinzuzufügen, so dass, wenn ein Benutzer eintritt, zum Beispiel $cat foo | sort -n | less
, dies abgefangen und in wrapper 'cat foo | sort -n | less'
übersetzt wird. Ich habe Wege gesehen, Befehle vor und nach jedem Befehl auszuführen (mit DEBUG-Traps oder PROMPT_COMMAND oder ähnlichem), aber nichts darüber, wie man jeden Befehl abfängt und ihn von einem anderen Prozess verarbeiten lässt. Gibt es eine Möglichkeit, dies zu tun?
Für eine Erklärung, warum ich das gerne machen würde, falls die Leute andere Vorschläge haben, wie man es angehen könnte:
Mit Tools wie dem Skript können Sie alles, was Sie in einem Terminal tun, in einem Protokoll (wie , bis zu einem gewissen Grad, bash Geschichte). Allerdings machen sie es nicht sehr gut - Skript mischt Eingabe mit Ausgabe in eine große Zeichenfolge und wird mit Anwendungen wie vi verwechselt, die den Bildschirm übernehmen, Geschichte gibt Ihnen nur die rohen Befehle eingegeben, und keiner von ihnen funktioniert gut, wenn Sie Befehle gleichzeitig in mehrere Terminals eingeben. Was ich tun möchte, ist, viel reichhaltigere Informationen zu erfassen - als Beispiel den Befehl, die Zeit, die er ausgeführt wurde, die Zeit, die er vollendet hat, den Beendigungsstatus, die ersten Zeilen von stdin und stdout. Ich würde es auch vorziehen, dies irgendwo zu einem Abhördämon zu schicken, der mehrere Terminals glücklich multiplexen könnte. Der einfache Weg, dies zu tun ist, den Befehl an ein anderes Programm zu übergeben, das eine Shell ausführen kann, um den Befehl als Subprozess zu behandeln, während man Griffe nach stdin, stdout, exit status usw. bekommt. Man könnte eine Shell schreiben, aber d verlieren viel von der Funktionalität bereits in bash, was ärgerlich wäre.
Die Motivation dafür liegt darin, dass wir versuchen, explorative Datenanalyse wie Prozeduren im Nachhinein sinnvoll zu machen. Mit umfangreicheren Informationen wie dieser wäre es möglich, anständige Berichte über das Geschehen zu erstellen, mehrere Aufrufe eines Befehls in einen zu zerquetschen, wo die ersten wenige Nicht-Null-Exits ergaben, wo Dateien herkamen, nach allem zu suchen, was die Datei berührte, etc etc.
Führe dieses Bash-Skript aus:
%Vor% In seiner einfachsten Form könnte wrapper
aus eval "$LINE"
bestehen. Du hast erwähnt, dass du Timings möchtest, also vielleicht time eval "$line"
. Sie wollten den Exit-Status erfassen, daher sollte die Zeile save=$?
folgen. Und Sie wollten die ersten paar Zeilen von stdout erfassen, also ist eine Umleitung in Ordnung. Und so weiter.
MEHR: Jo So schlägt vor, dass die Handhabung für mehrzeilige Bash-Befehle enthalten sein soll. Wenn eval in seiner einfachsten Form mit "Syntaxfehler: unerwartetes Dateiende" zurückkehrt, müssen Sie vor dem Fortfahren eine Eingabeaufforderung eingeben. Besser noch, um nach richtigen Bash-Befehlen zu suchen, führen Sie bash -n <<<"$line"
aus, bevor Sie eval
ausführen. Wenn bash -n
den End-of-Line-Fehler meldet, werden Sie aufgefordert, weitere Eingaben zu '$ line' hinzuzufügen. Und so weiter.
Binfmt_misc kommt mir in den Sinn. Der Linux-Kernel ermöglicht es, beliebige ausführbare Dateiformate zu erkennen und an die Benutzeranwendung zu übergeben.
Sie können diese Funktion verwenden, um Ihren Wrapper zu registrieren, aber anstatt mit einer beliebigen ausführbaren Datei zu arbeiten, sollte sie alle ausführbaren Dateien behandeln.