Me he acostumbrado tanto a hacer esto:
someprogram >output.file
Lo hago cada vez que quiero guardar la salida que genera un programa en un archivo. También conozco las dos variantes de esta redirección de IO :
someprogram 2>output.of.stderr.file
(para stderr)someprogram &>output.stderr.and.stdout.file
(para ambos stdout + stderr combinados)
Hoy me he encontrado con una situación que no creía posible. Uso el siguiente comando xinput test 10
y, como esperaba, tengo el siguiente resultado:
usuario @ nombre de host: ~ $ xinput test 10 pulsación de tecla 30 lanzamiento clave 30 pulsación de tecla 40 lanzamiento clave 40 pulsación de tecla 32 lanzamiento clave 32 pulsación de tecla 65 lanzamiento clave 65 pulsación de tecla 61 lanzamiento clave 61 pulsación de tecla 31 ^ C usuario @ nombre de host: ~ $
Esperaba que esta salida se pudiera guardar como de costumbre en un archivo como el que se usa xinput test 10 > output.file
. Pero cuando contradice mis expectativas, el archivo output.file permanece vacío. Esto también es cierto para xinput test 10 &> output.file
asegurarse de que no me pierda algo en stdout o stderr.
Estoy realmente confundido y, por lo tanto, pregunto aquí si el xinput
programa podría tener una manera de evitar que su salida sea redirigida.
actualizar
He mirado la fuente. Parece que la salida es generada por este código (ver fragmento a continuación). Me parece que la salida sería generada por una impresión ordinaria
// en el archivo test.c eventos_impresión de vacío estático (Display * dpy) { Evento XEvent; mientras que (1) { XNextEvent (dpy, y Evento); // [... algunos otros tipos de eventos se omiten aquí ...] 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"); } } }
Modifiqué la fuente a esto (vea el siguiente fragmento a continuación), lo que me permite tener una copia de la salida en stderr. Esta salida puedo redirigir:
// en el archivo test.c eventos_impresión de vacío estático (Display * dpy) { Evento XEvent; mientras que (1) { XNextEvent (dpy, y Evento); // [... algunos otros tipos de eventos se omiten aquí ...] 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": "presione", key-> keycode); for (loop = 0; loopaxes_count; loop ++) { printf ("a [% d] =% d", key-> first_axis + loop, key-> axis_data [loop]); } printf ("\ n"); } } }
Mi idea en este momento es que tal vez al hacer la redirección, el programa pierde su capacidad de monitorear los eventos de pulsación de teclas.
fuente
setvbuf(stdout, (char *) NULL, _IONBF, NULL)
. ¿Quizás esto también sea de interés?stdbuf -o0
hace, mientrasstdbug -oL
restaura el almacenamiento en línea como cuando la salida va a un terminal.stdbuf
obliga a la aplicación a llamarsetvbuf
usando unLD_PRELOAD
truco.unbuffer test 10 > file
(unbuffer
es parte de lasexpect
herramientas)Un comando puede escribir directamente para
/dev/tty
evitar que se produzca una redirección regular.fuente
/dev/tty
en un sistema Linux, usescript -c ./demo demo.log
(desdeutil-linux
).Parece que
xinput
rechaza la salida a un archivo pero no rechaza la salida a un terminal. Para lograr esto, probablementexinput
use la llamada al sistemapara verificar si el descriptor de archivo a abrir se refiere a un terminal o no.
Me topé con el mismo fenómeno hace un tiempo con un programa llamado
dpic
. Después de buscar en la fuente y algunas depuraciones, eliminé las líneas relacionadasisatty
y todo volvió a funcionar como se esperaba.Pero estoy de acuerdo con usted en que esta experiencia es muy inquietante;)
fuente
isatty
prueba realizada. La salida se genera porprintf
función (creo que es una C estándar). Agregué algunosfprintf(stderr,"output")
y esto es posible redirigir + prueba que todo el código realmente se ejecuta en el caso de xinput. Gracias por la sugerencia después de todo, fue el primer sendero aquí.En su
test.c
archivo, puede vaciar los datos almacenados en búfer(void)fflush(stdout);
directamente después de susprintf
declaraciones.En la línea de comando, puede habilitar la salida con buffer de línea ejecutando
xinput test 10
en un pseudo terminal (pty) con elscript
comando.fuente
Si. Incluso hice esto en DOS veces cuando programé en pascal. Supongo que el principio aún se mantiene:
Esto rompió cualquier tubería.
fuente
con
es el nombre de DOS para lo que llama unix/dev/tty
, es decir, el terminal (de control).