Je suis devenu tellement habitué à faire ceci:
someprogram >output.file
Je le fais chaque fois que je veux enregistrer le résultat généré par un programme dans un fichier. Je connais également les deux variantes de cette redirection IO :
someprogram 2>output.of.stderr.file
(pour stderr)someprogram &>output.stderr.and.stdout.file
(pour les deux stdout + stderr combinés)
Aujourd'hui, j'ai rencontré une situation que je n'aurais pas cru possible. J'utilise la commande suivante xinput test 10
et comme prévu, j'ai la sortie suivante:
utilisateur @ nomhôte: ~ $ xinput test 10 touche enfoncée 30 libération de clé 30 touche 40 libération de clé 40 touche 32 libération de clé 32 touche 65 libération de clé 65 touche 61 libération de clé 61 touche 31 ^ C utilisateur @ nom d'hôte: ~ $
Je pensais que cette sortie pourrait, comme d’habitude, être sauvegardée dans un fichier similaire à xinput test 10 > output.file
. Mais lorsque cela est contraire à mes attentes, le fichier output.file reste vide. Ceci est également vrai pour xinput test 10 &> output.file
m'assurer que je ne manque rien sur stdout ou stderr.
Je suis vraiment confus et demande donc ici si le xinput
programme aurait un moyen d'éviter que sa sortie soit redirigée?
mise à jour
J'ai regardé la source. Il semble que la sortie soit générée par ce code (voir l'extrait de code ci-dessous). Il me semble que la sortie serait générée par un printf ordinaire
// dans le fichier test.c static void print_events (Display * dpy) { Événement XEvent; tandis que (1) { XNextEvent (dpy, & Event); // [... d'autres types d'événements sont omniprés ici ...] if ((Event.type == key_press_type) || (Event.type == key_release_type)) { boucle int; XDeviceKeyEvent * key = (XDeviceKeyEvent *) & Event; printf ("clé% s% d", (Event.type == key_release_type)? "release": "appuyez sur", clé-> code de touche); for (loop = 0; loopaxes_count; loop ++) { printf ("a [% d] =% d", clé-> first_axis + boucle, clé-> axis_data [boucle]); } printf ("\ n"); } } }
J'ai modifié le source pour cela (voir l'extrait suivant ci-dessous), ce qui me permet d'avoir une copie de la sortie sur stderr. Cette sortie, je suis capable de rediriger:
// dans le fichier test.c static void print_events (Display * dpy) { Événement XEvent; tandis que (1) { XNextEvent (dpy, & Event); // [... d'autres types d'événements sont omniprés ici ...] if ((Event.type == key_press_type) || (Event.type == key_release_type)) { boucle int; XDeviceKeyEvent * key = (XDeviceKeyEvent *) & Event; printf ("clé% s% d", (Event.type == key_release_type)? "release": "appuyez sur", clé-> code de touche); fprintf (stderr, "clé% s% d", (type d'événement == clé_release_type)? "release": "presse", clé-> code clé); for (loop = 0; loopaxes_count; loop ++) { printf ("a [% d] =% d", clé-> first_axis + boucle, clé-> axis_data [boucle]); } printf ("\ n"); } } }
Mon idée actuelle est que, peut-être qu'en faisant la redirection, le programme perd sa capacité à surveiller les événements d'activation de touche.
la source
setvbuf(stdout, (char *) NULL, _IONBF, NULL)
. C'est peut-être aussi intéressant !?stdbuf -o0
fait, tout enstdbug -oL
restaure ligne en mémoire tampon comme lorsque la sortie passe à un terminal.stdbuf
force l'application à appeler ensetvbuf
utilisant uneLD_PRELOAD
astuce.unbuffer test 10 > file
(unbuffer
fait partie desexpect
outils)Une commande peut directement écrire pour
/dev/tty
empêcher la redirection habituelle.la source
/dev/tty
sur un système Linux, utilisezscript -c ./demo demo.log
(depuisutil-linux
).Il semble que la
xinput
sortie d'un fichier soit rejetée, mais pas celle d'un terminal. Pour ce faire,xinput
utilisez probablement l'appel systèmevérifier si le FileScriptor à ouvrir fait référence à un terminal ou non.
Je suis tombé sur le même phénomène il y a un moment avec un programme appelé
dpic
. Après avoir jeté un œil sur le code source et un peu de débogage, j’ai supprimé les lignes associéesisatty
et tout a fonctionné comme prévu à nouveau.Mais je suis d'accord avec vous que cette expérience est très dérangeante;)
la source
isatty
test effectué. La sortie est générée par uneprintf
fonction (je pense que c’est un C standard). J'en ai ajouté quelquesfprintf(stderr,"output")
- unes et il est possible de les rediriger + prouve que tout le code est vraiment exécuté dans le cas de xinput. Merci pour la suggestion après tout c'était la première piste ici.Dans votre
test.c
fichier, vous pouvez vider les données mises en mémoire tampon(void)fflush(stdout);
directement après vosprintf
déclarations.Sur la ligne de commande, vous pouvez activer la sortie avec mise
xinput test 10
en tampon de ligne en exécutant la commande dans un pseudo-terminal (pty)script
.la source
Oui. Je l'ai même fait dans DOS-times quand j'ai programmé en pascal. Je suppose que le principe est toujours valable:
Cela a cassé des tuyaux.
la source
con
est le nom DOS de ce que appelle unix/dev/tty
, c’est-à-dire le terminal (de contrôle).