Я так привык делать это:
someprogram >output.file
Я делаю это всякий раз, когда хочу сохранить вывод, сгенерированный программой, в файл. Мне также известны два варианта этого перенаправления ввода-вывода :
someprogram 2>output.of.stderr.file
(для stderr)someprogram &>output.stderr.and.stdout.file
(для обоих stdout + stderr вместе взятых)
Сегодня я столкнулся с ситуацией, которую я не считал возможным. Я использую следующую команду xinput test 10
и, как и ожидалось, у меня есть следующий вывод:
user @ hostname: ~ $ xinput test 10 нажатие клавиши 30 ключ релиз 30 нажатие клавиши 40 выпуск ключа 40 нажатие клавиши 32 ключ разблокировки 32 нажатие клавиши 65 выпуск ключа 65 нажатие клавиши 61 ключ релиз 61 нажатие клавиши 31 ^ C пользователь @ имя хоста: ~ $
Я ожидал, что этот вывод, как обычно, может быть сохранен в файл, как с помощью xinput test 10 > output.file
. Но когда, вопреки моим ожиданиям, файл output.file остается пустым. Это также верно xinput test 10 &> output.file
только для того, чтобы я не пропустил что-то на stdout или stderr.
Я действительно сбит с толку и поэтому спрашиваю здесь, может ли xinput
программа избежать перенаправления вывода?
Обновить
Я посмотрел на источник. Кажется, результат генерируется этим кодом (см. Фрагмент ниже). Мне кажется, что вывод будет сгенерирован обычным printf
// в файле test.c static void print_events (Display * dpy) { XEvent Event; while (1) { XNextEvent (dpy, & Event); // [... некоторые другие типы событий здесь опущены ...] if ((Event.type == key_press_type) || (Event.type == key_release_type)) { цикл int; XDeviceKeyEvent * key = (XDeviceKeyEvent *) & Event; printf («ключ% s% d», (Event.type == key_release_type)? «release»: «нажать», key-> keycode); for (loop = 0; loopaxes_count; loop ++) { printf ("a [% d] =% d", key-> first_axis + loop, key-> axis_data [loop]); } Е ( "\ п"); } } }
Я изменил исходный код для этого (см. Следующий фрагмент ниже), который позволяет мне иметь копию вывода на stderr. Этот вывод я могу перенаправить:
// в файле test.c static void print_events (Display * dpy) { XEvent Event; while (1) { XNextEvent (dpy, & Event); // [... некоторые другие типы событий здесь опущены ...] if ((Event.type == key_press_type) || (Event.type == key_release_type)) { цикл int; XDeviceKeyEvent * key = (XDeviceKeyEvent *) & Event; printf («ключ% s% d», (Event.type == key_release_type)? «release»: «нажать», key-> keycode); fprintf (stderr, "ключ% s% d", (Event.type == key_release_type)? "release": "нажатие", key-> keycode); for (loop = 0; loopaxes_count; loop ++) { printf ("a [% d] =% d", key-> first_axis + loop, key-> axis_data [loop]); } Е ( "\ п"); } } }
Моя идея в настоящее время заключается в том, что, возможно, при перенаправлении программа теряет способность контролировать события отпускания клавиш.
источник
setvbuf(stdout, (char *) NULL, _IONBF, NULL)
. Может быть, это тоже интересно!stdbuf -o0
, что делает, в то же времяstdbug -oL
восстанавливает буферизацию строки, как когда выходной сигнал поступает на терминал.stdbuf
это заставить приложение вызвать сsetvbuf
помощьюLD_PRELOAD
трюка.unbuffer test 10 > file
(unbuffer
входит в составexpect
инструментов)Команда может напрямую писать для
/dev/tty
предотвращения регулярного перенаправления.источник
/dev/tty
системе Linux, используйтеscript -c ./demo demo.log
(fromutil-linux
).Похоже,
xinput
отклоняет вывод в файл, но не отклоняет вывод в терминал. Для этого, вероятно,xinput
используйте системный вызовпроверить, относится ли открываемый файловый дескриптор к терминалу или нет.
Я наткнулся на то же явление некоторое время назад с программой под названием
dpic
. После того, как я посмотрел на источник и немного отладил, я удалил строки, связанные с,isatty
и все снова заработало, как и ожидалось.Но я согласен с вами, что этот опыт очень беспокоит;)
источник
isatty
. Выход генерируетсяprintf
функцией (я думаю, это стандарт C). Я добавил несколько,fprintf(stderr,"output")
и это можно перенаправить + доказывает, что весь код действительно выполняется в случае xinput. Спасибо за предложение, ведь это был первый путь здесь.В вашем
test.c
файле вы можете сбросить буферизованные данные, используя(void)fflush(stdout);
сразу после вашихprintf
заявлений.В командной строке вы можете включить вывод с буферизацией строки, запустив команду
xinput test 10
с псевдотерминалом (pty)script
.источник
Да. Я даже делал это в DOS-времена, когда я программировал на паскале. Я думаю, что принцип все еще действует:
Это сломало любые трубы.
источник
con
является именем DOS для того, что вызывает Unix/dev/tty
, то есть (управляющий) терминал.