Wie startet man ein Programm ordnungsgemäß und ermöglicht die Umleitung seiner laufenden Ausgabe (stdout und stderr) zu einem späteren Zeitpunkt?

Wie startet man ein Programm ordnungsgemäß und ermöglicht die Umleitung seiner laufenden Ausgabe (stdout und stderr) zu einem späteren Zeitpunkt?

Das Problem ist ganz einfach: Ich finde es nützlich, die Möglichkeit zu haben,ein- (und aus-)schaltendie Ausgabe eines laufenden Programms in jedem Moment, den ich brauche. Genauer gesagt möchte ich die Möglichkeit haben, die Standardausgabe (und den Fehler) von der aktuellen Shell auf eine andere, auf /dev/nulleine Datei oder zurück auf die ursprüngliche Shell umzuleiten.

Ich suche nach etwas Direktem (und Sicherem), das die Tatsache ausnutzt, dass ich weißim Vorausdass ich die Ausgänge ein- und ausschalten werde. Ich poste auch eine Antwort.


Unten ist mein erster Versuch. Nehmen wir an, ich arbeite in der Shell Nummer 35.

$ who am I                     # the command line to ask where am I
myuser  pts/35  ...            # The answer 

Mein Versuch beginnt mit einem symbolischen Link zu diesem Terminal

ln -s /dev/pts/35  MyOutput  # The command to link

Die Idee ist, das Programm mit der Umleitung auf diesen Link zu starten

./Execute_program > MyOutput

Es funktioniert, es leitet die Ausgabe an mein Terminal um, aber wenn ich den Befehl zum Ändern des Links gebe,

ln -sf  /dev/null  MyOutput

der Link ändert sich,aber die Umleitung ändert sich nichtwie ich es erhofft hatte. Es ändert sich nichts für den laufenden Prozess. Wenn ich ein neues Programm auf die gleiche Weise starte, folgt die Umleitung der neuen Vorgabe des Links.
Wenn ich erneut starte und den Link auf setze, /dev/nullwird die Ausgabe wie erwartet unterdrückt, aber wenn ich den Link wieder ändere, ändert sich die Umleitung nicht.
Wenn ich einen Link auf einen Link setze, erhalte ich das gleiche Ergebnis. Die Verwendung von hard linkändert die Situation nicht.

Leiderdie Shell erweitert die Befehlszeile beim Start.

Gibt es eine Möglichkeit, die Aufgabe auf ähnliche Weise zu erledigen, oder muss ich herausfinden, wie ich dem Prozess (oder den PPID-Prozessen) mitteile, dass der Link geändert wurde?


Anmerkungen:

Dies ist eine Frage aus der Reihe "Wie kann ich die Ausgabe eines laufenden Prozesses umleiten?", aber sie beginnt nicht mit dem Punkt„Ups, ich habe das Programm gestartet und vergessen, die Ausgabe umzuleiten. Jetzt möchte ich es tun.“, sondern umgekehrt: „Wie kann ich ein Programm mit dem ausdrücklichen Ziel starten, die Ausgabe zu einem späteren Zeitpunkt woandershin umzuleiten?“.


Ich beabsichtige, ein solches Verfahren zu verwenden, wenn es nicht möglich (oder praktisch) ist , den Quellcode des Programms zu ändern.lesendass es möglich ist disown, den Prozess zu verwenden screenund von einem Bildschirm auf einen anderen zu übertragen … oder einen Debugger zu verwenden, um den Prozess abzufangen … Alle diese Lösungen könnten mit viel Erfahrung und Aufwand funktionieren, einige von ihnen bergen jedoch auch ein gewisses Risiko.

Antwort1

Ich finde eine Lösung über mkfifo, die eine Named Pipe erstellt, oderFIFOs.
Es ist so einfach wie das Erstellen eines symbolischen Links und es ist möglich, alle von der Shell zugelassenen Umleitungen zu verwenden.

mkfifo MyOutput

ls -lgibt

0 prw-r--r-- 1 My_username My_username  0 May 11 17:45 MyOut|

Ich kann das Programm mit Weiterleitung zu diesem Link starten

./Execute_program > MyOutput  &  cat MyOutput 

und die Ausgabe beginnt am Terminal zu fließen.

Wenn ich ctrl+ drücke c, unterbreche ich den Ablauf, aber nicht den laufenden Prozess (ich muss etwas wie kill pidoder verwenden kill %1, um dies zu tun).
Wenn ich ein zweites Mal frage,FIFOsum auf dem Terminal zu dumpen (erneut mit cat MyOutput), wird ab diesem Moment mit dem Dump der Ausgabe begonnen.

Hinweise und Warnungen:

  • Bis ich einen Dump anfordere, FIFOswird die gesamte Ausgabe gespeichert.
    Wenn ich das erste Mal danach frage, wird esausspülenalle.
  • Ich kann auf eine andere Datei umleiten (oder anhängen)cat MyOutput >> NewRealFile
  • Ich kann es cat MyOutputauch von einem anderen Terminal aus verwenden!
  • Warnung: Wenn ich zwei verschiedene Programme (oder Instanzen) auffordere, die Ausgabe auf dasselbe Programm umzuleiten, FIFOswird der Fluss zusammengeführt (keina prioriMöglichkeit zu unterscheiden, aus welchen Programmen diese Zeile stammt).
  • Warnung: Wenn ich 2 oder mehr Mal frage (vielleicht von verschiedenen Terminals aus), wird für jede Anfrage eine Zeile ausgegeben, die die Ausgabe an den Anforderer aufteilt. Vielleicht gibt es eine sichere Problemumgehung ...

Antwort2

Wenn ich Ihre Frage richtig verstehe:

script 1>>~/out.fifo 2>>~/error.fifo 

Zur Überwachung können Sie dann Folgendes tun:

watch cat ~/out.fifo

Sie könnten echte Dateien anstelle von Fifos verwenden

script 1>/tmp/$0-out 2>/tmp/$0-error

Führen Sie dann das Tail-F-Verfahren aus. Sie werden ersetzt, wenn Sie die Skripte erneut ausführen.

Ich bevorzuge die zweite Methode oder einfach die Verwendung eines Multiplexers (also eines Bildschirms oder was auch immer diese Woche die populäre Reinkarnation ist).

screen -t "name" bash -c 'script'

Dann

screen -r

zu „Monitor“ und Strg+Anzeige zum Trennen.

Halten Sie am Ende Ihres Skripts unbedingt an, wenn Sie die Ausgabe nach der Ausführung sehen möchten.

Antwort3

ich an deiner Stelle würde die Ausgabe einfach in eine Datei umleiten und diese Datei dann tailf-en, wenn ich die Ausgabe sehen möchte... außerdem möchtest du vielleicht die Größe dieser Datei begrenzen, wenn du denkst, dass die Ausgabe ziemlich lang wird, oder die Datei in den RAM statt auf die Festplatte schreiben lassen, wenn du denkst, dass die Ausgabe ziemlich schnell sein wird, aber wie man das macht, ist eine andere Frage, keine Ahnung.

verwandte Informationen