Eu me acostumei a fazer isso:
someprogram >output.file
Faço isso sempre que quero salvar a saída que um programa gera em um arquivo. Também estou ciente das duas variantes desse redirecionamento de entrada / saída :
someprogram 2>output.of.stderr.file
(para stderr)someprogram &>output.stderr.and.stdout.file
(para stdout + stderr combinados)
Hoje me deparei com uma situação que não considerava possível. Eu uso o seguinte comando xinput test 10
e, como esperado, tenho a seguinte saída:
user @ hostname: ~ $ xinput test 10 pressionar a tecla 30 liberação da chave 30 pressionar a tecla 40 liberação da chave 40 pressionar a tecla 32 liberação da chave 32 pressionar a tecla 65 liberação da tecla 65 pressionar a tecla 61 liberação da tecla 61 pressionar a tecla 31 ^ C usuário @ hostname: ~ $
Eu esperava que essa saída pudesse, como sempre, ser salva em um arquivo como o uso xinput test 10 > output.file
. Mas, ao contrário da minha expectativa, o arquivo output.file permanece vazio. Isso também é válido xinput test 10 &> output.file
apenas para garantir que eu não perca algo no stdout ou stderr.
Estou realmente confuso e, portanto, pergunto aqui se o xinput
programa pode ter uma maneira de evitar que sua saída seja redirecionada?
atualizar
Eu olhei para a fonte. Parece que a saída é gerada por esse código (veja o trecho abaixo). Parece-me que a saída seria gerada por um printf comum
// no arquivo test.c static void print_events (Exibir * dpy) { Evento XEvent; enquanto (1) { XNextEvent (dpy, & Evento); // [... alguns outros tipos de eventos são omitidos aqui ...] if ((Event.type == key_press_type) || (Event.type == key_release_type)) { loop int; XDeviceKeyEvent * key = (XDeviceKeyEvent *) & Event; printf ("chave% s% d", (Event.type == key_release_type)? "release": "pressione", tecla-> código da tecla); for (loop = 0; loopaxes_count; loop ++) { printf ("a [% d] =% d", chave-> primeiro_axis + loop, chave-> eixo_dados [loop]); } printf ("\ n"); } } }
Modifiquei a fonte para isso (veja o próximo trecho abaixo), o que me permite ter uma cópia da saída no stderr. Esta saída eu sou capaz de redirecionar:
// no arquivo test.c static void print_events (Exibir * dpy) { Evento XEvent; enquanto (1) { XNextEvent (dpy, & Evento); // [... alguns outros tipos de eventos são omitidos aqui ...] if ((Event.type == key_press_type) || (Event.type == key_release_type)) { loop int; XDeviceKeyEvent * key = (XDeviceKeyEvent *) & Event; printf ("chave% s% d", (Event.type == key_release_type)? "release": "pressione", tecla-> código da tecla); fprintf (stderr, "chave% s% d", (Event.type == key_release_type)? "release": "pressione", tecla-> código da tecla); for (loop = 0; loopaxes_count; loop ++) { printf ("a [% d] =% d", chave-> primeiro_axis + loop, chave-> eixo_dados [loop]); } printf ("\ n"); } } }
Minha idéia no momento é que, talvez, ao redirecionar o programa perca a capacidade de monitorar os eventos de liberação de tecla.
fonte
setvbuf(stdout, (char *) NULL, _IONBF, NULL)
. Talvez isso também seja interessante !?stdbuf -o0
faz, enquantostdbug -oL
restaura o buffer de linha como quando a saída vai para um terminal.stdbuf
força o aplicativo a chamarsetvbuf
usando umLD_PRELOAD
truque.unbuffer test 10 > file
(unbuffer
faz parte dasexpect
ferramentas)Um comando pode gravar diretamente para
/dev/tty
impedir o redirecionamento regular.fonte
/dev/tty
em um sistema Linux, usescript -c ./demo demo.log
(fromutil-linux
).Parece que
xinput
rejeita a saída para um arquivo, mas não rejeita a saída para um terminal. Para conseguir isso, provavelmentexinput
use a chamada do sistemapara verificar se o filedescriptor a ser aberto se refere a um terminal ou não.
Encontrei o mesmo fenômeno há algum tempo com um programa chamado
dpic
. Depois que eu olhei para a fonte e alguma depuração, removi as linhas relacionadasisatty
e tudo funcionou como esperado novamente.Mas eu concordo com você que esta experiência é muito perturbadora;)
fonte
isatty
teste feito. A saída é gerada pelaprintf
função (eu acho que é o C padrão). Eu adicionei algunsfprintf(stderr,"output")
e isso é possível redirecionar + prova que todo o código é realmente executado no caso do xinput. Obrigado pela sugestão, afinal foi a primeira trilha aqui.No seu
test.c
arquivo, você pode liberar os dados em buffer usando(void)fflush(stdout);
diretamente após suasprintf
instruções.Na linha de comando, você pode habilitar a saída com buffer de linha executando
xinput test 10
em um pseudo terminal (pty) com oscript
comandofonte
Sim. Até fiz isso no DOS quando programava em pascal. Eu acho que o princípio ainda vale:
Isso quebrou qualquer cano.
fonte
con
é o nome do DOS para o que o unix chama/dev/tty
, ou seja, o terminal (controlador).