Ich habe mich daran gewöhnt:
someprogram >output.file
Ich mache das immer dann, wenn ich die von einem Programm generierte Ausgabe in einer Datei speichern möchte. Mir sind auch die beiden Varianten dieser E / A-Umleitung bekannt :
someprogram 2>output.of.stderr.file
(für stderr)someprogram &>output.stderr.and.stdout.file
(für beide stdout + stderr kombiniert)
Heute bin ich auf eine Situation gestoßen, die ich nicht für möglich gehalten habe. Ich benutze den folgenden Befehl xinput test 10
und wie erwartet habe ich die folgende Ausgabe:
user @ hostname: ~ $ xinput test 10 Tastendruck 30 Schlüsselfreigabe 30 Tastendruck 40 Schlüsselfreigabe 40 Tastendruck 32 Schlüsselfreigabe 32 Tastendruck 65 Schlüsselfreigabe 65 Tastendruck 61 Schlüsselfreigabe 61 Tastendruck 31 ^ C user @ hostname: ~ $
Ich habe erwartet, dass diese Ausgabe wie gewohnt in einer Datei gespeichert werden kann xinput test 10 > output.file
. Entgegen meiner Erwartung bleibt die Datei output.file jedoch leer. Dies gilt auch xinput test 10 &> output.file
nur, um sicherzustellen, dass ich auf stdout oder stderr nichts verpasse.
Ich bin wirklich verwirrt und frage daher hier, ob das xinput
Programm eine Möglichkeit hat, die Umleitung der Ausgabe zu vermeiden.
aktualisieren
Ich habe die Quelle angeschaut. Es scheint, dass die Ausgabe von diesem Code generiert wird (siehe Ausschnitt unten). Es scheint mir, dass die Ausgabe von einem normalen printf generiert würde
// in der Datei test.c statische void print_events (Display * dpy) { XEvent Event; während (1) { XNextEvent (dpy & Event); // [... einige andere Ereignistypen sind hier weggelassen ...] if ((Event.type == key_press_type) || (Event.type == key_release_type) { int loop; XDeviceKeyEvent * key = (XDeviceKeyEvent *) & Event; printf ("key% s% d", (Event.type == key_release_type)? "release": "press", key-> keycode); for (loop = 0; loopaxes_count; loop ++) { printf ("a [% d] =% d", key-> first_axis + loop, key-> axis_data [loop]); } printf ("\ n"); } } }
Ich habe die Quelle dahingehend geändert (siehe nächster Ausschnitt unten), dass ich eine Kopie der Ausgabe auf stderr haben kann. Diese Ausgabe kann ich umleiten:
// in der Datei test.c statische void print_events (Display * dpy) { XEvent Event; während (1) { XNextEvent (dpy & Event); // [... einige andere Ereignistypen sind hier weggelassen ...] if ((Event.type == key_press_type) || (Event.type == key_release_type) { int loop; XDeviceKeyEvent * key = (XDeviceKeyEvent *) & Event; printf ("key% s% d", (Event.type == key_release_type)? "release": "press", key-> keycode); fprintf (stderr, "key% s% d", (Event.type == key_release_type)? "release": "press", key-> keycode); for (loop = 0; loopaxes_count; loop ++) { printf ("a [% d] =% d", key-> first_axis + loop, key-> axis_data [loop]); } printf ("\ n"); } } }
Meine derzeitige Idee ist, dass das Programm durch die Weiterleitung möglicherweise nicht mehr in der Lage ist, die Ereignisse beim Drücken und Loslassen von Tasten zu überwachen.
quelle
setvbuf(stdout, (char *) NULL, _IONBF, NULL)
. Vielleicht ist das auch von Interesse !?stdbuf -o0
, währendstdbug -oL
die Zeilenpufferung wiederhergestellt wird , wie wenn die Ausgabe an ein Terminal geht.stdbuf
zwingt die Anwendung,setvbuf
mit einemLD_PRELOAD
Trick aufzurufen .unbuffer test 10 > file
(unbuffer
ist Teil derexpect
Tools)Ein Befehl kann direkt schreiben, um
/dev/tty
eine regelmäßige Umleitung zu verhindern.quelle
/dev/tty
auf einem Linux-System geschriebene Ausgabe erfassen möchten , verwenden Siescript -c ./demo demo.log
(fromutil-linux
).Es sieht so aus, als würde
xinput
die Ausgabe in eine Datei abgelehnt, aber nicht in ein Terminal.xinput
Verwenden Sie dazu wahrscheinlich den Systemaufrufum zu prüfen, ob der zu öffnende Filedescriptor auf ein Terminal verweist oder nicht.
Ich bin vor einiger Zeit mit einem aufgerufenen Programm auf dasselbe Phänomen gestoßen
dpic
. Nachdem ich mir den Quellcode angesehen und einige Fehler behoben hatte, entfernte ich die dazugehörigen Zeilenisatty
und alles funktionierte wieder wie erwartet.Aber ich stimme dir zu, dass diese Erfahrung sehr beunruhigend ist;)
quelle
isatty
Tests durchgeführt wurden. Die Ausgabe wird durch dieprintf
Funktion (ich denke, es ist ein Standard-C) erzeugt. Ich habe einige hinzugefügtfprintf(stderr,"output")
und dies ist möglich, um + umzuleiten, um zu beweisen, dass der gesamte Code im Fall von xinput wirklich ausgeführt wird. Vielen Dank für den Vorschlag, es war doch der erste Trail hier.In Ihrer
test.c
Datei können Sie die gepufferten Daten mit(void)fflush(stdout);
direkt nach Ihrenprintf
Anweisungen leeren.In der Befehlszeile können Sie die
xinput test 10
zeilengepufferte Ausgabe aktivieren, indem Sie den Befehl in einem Pseudoterminal (pty) ausführenscript
.quelle
Ja. Ich habe das sogar in DOS-Zeiten gemacht, als ich in Pascal programmiert habe. Ich denke, das Prinzip gilt immer noch:
Dies hat keine Rohre gebrochen.
quelle
con
ist der DOS-Name für das, was Unix aufruft/dev/tty
, dh das (steuernde) Terminal.