Программа командной строки может предотвратить свой перенаправляемый вывод?

Существует также OLDPWD, переменная среды, которая, согласно IEEE 1003.1 (POSIX), должен быть обновлен с предыдущим рабочим каталогом каждый раз cd изменяет рабочий каталог (для любопытных, строка 80244 из страницы 2506 IEEE 1003.1-2008).

49
28.12.2012, 13:21
5 ответов

Это просто, что, когда stdout не является терминалом, вывод буферизуется.

И когда Вы нажимаете Ctrl-C, тот буфер потерян, поскольку/если он еще не был записан.

Вы получаете то же поведение с чем-либо использование stdio. Попробуйте, например:

grep . > file

Введите несколько непустых строк и нажмите Ctrl-C, и Вы будете видеть, что файл пуст.

С другой стороны, тип:

xinput test 10 > file

И введите достаточно на клавиатуре для буфера для получения сытыми (по крайней мере, 4k ценность ouput), и Вы будете видеть, что размер файла растет блоками 4k за один раз.

С grep, можно ввести Ctrl-D для grep выходить корректно сбросив его буфер. Для xinput, Я не думаю, что существует такая опция.

Отметьте это по умолчанию stderr не буферизуется, который объясняет, почему Вы получаете другое поведение с fprintf(stderr)

Если, в xinput.c, Вы добавляете a signal(SIGINT, exit), это, говорят xinput выходить корректно, когда это получает SIGINT, Вы будете видеть file больше не пусто (предположение, что это не отказывает, поскольку называющий библиотечные функции от обработчиков сигналов не гарантируется безопасным: рассмотрите то, что могло произойти, если сигнал входит, в то время как printf пишет в буфер).

Если это доступно, Вы могли бы использовать stdbuf команда для изменения stdio буферизация поведения:

stdbuf -oL xinput test 10 > file

Существует много вопросов на этом сайте, которые покрывают отключение stdio буферизация типа, где Вы найдете еще больше альтернативных решений.

55
27.01.2020, 19:34
  • 1
    WOW :), который добился цели.спасибо. Таким образом в конце мое восприятие проблемы было неправильным. Там ничто не существовал к inhibt перенаправлению, это был простой Ctrl-C, остановленный это, прежде чем данные были сброшены. спасибо –  humanityANDpeace 28.12.2012, 13:55
  • 2
    там было бы способом предотвратить буферизацию stdout? –  humanityANDpeace 28.12.2012, 13:55
  • 3
    @Stephane Chazelas: большое спасибо за Ваше подробное объяснение. В дополнение к то, что Вы уже сказали, что я узнал, что можно установить буфер на, освободило буфер с setvbuf(stdout, (char *) NULL, _IONBF, NULL). Возможно, это также представляет интерес!? –  user1146332 28.12.2012, 14:18
  • 4
    @user1146332, да, который был бы что stdbuf -o0 делает, в то время как stdbug -oL строка восстановлений, буферизующая как то, когда вывод переходит к терминалу. stdbuf действительно вынуждает приложение звонить setvbuf использование a LD_PRELOAD прием. –  Stéphane Chazelas 28.12.2012, 14:23
  • 5
    другое обходное решение: unbuffer test 10 > file (unbuffer часть expect инструменты) –  Olivier Dulac 28.12.2012, 17:40

Команда может непосредственно записать в /dev/tty предотвращение регулярного перенаправления для случая.

$ cat demo
#!/bin/ksh
LC_ALL=C TZ=Z date > /dev/tty
$ ./demo >demo.out 2>demo.err
Fri Dec 28 10:31:57  2012
$ ls -l demo*
-rwxr-xr-x 1 jlliagre jlliagre 41 2012-12-28 11:31 demo
-rw-r--r-- 1 jlliagre jlliagre  0 2012-12-28 11:31 demo.err
-rw-r--r-- 1 jlliagre jlliagre  0 2012-12-28 11:31 demo.out
23
27.01.2020, 19:34
  • 1
    Ваш пример высказывает мнение +, отвечает на вопрос. Да это возможно. Это, конечно, "неожиданно" и uncommen для программ, чтобы сделать так, который, по крайней мере, дурачил меня в не рассмотрении такой возможной вещи. Ответ user1146332 также кажется убедительным способом избежать перенаправления. Для ярмарки и начиная с, оба данных ответа являются одинаково возможными способами избежать перенаправления вывода программы командной строки в файл, я не могу выбрать ни один из ответов, которые я предполагаю :(. Мне должны были бы разрешить выбрать два права ответов. Большая работа, Спасибо! –  humanityANDpeace 28.12.2012, 13:25
  • 2
    FTR, если Вы хотите получить вывод, записанный в /dev/tty в системе Linux использовать script -c ./demo demo.log (от util-linux). –  ndim 28.12.2012, 19:40
  • 3
    Если Вы не работаете в tty, но вместо этого в имуществе, можно найти это путем рассмотрения procfs (/proc/$PID/fd/0 и т.д.). Для записи в соответствующее имущество перейдите к fd каталогу родительского процесса и посмотрите, является ли это символьная ссылка на/dev/pts / [0-9] +. Затем Вы пишете в то устройство (или рекурсивно вызываете, если это не pts). –  dhasenan 28.12.2012, 19:48

Это похоже xinput вывод отклонений в файл, но не отклоняет вывод к терминалу. Достигнуть этого, вероятно xinput используйте системный вызов

int isatty(int fd)

проверять, относится ли filedescriptor, который будет открыт, к терминалу или нет.

Я наткнулся на то же явление только что с названной программой dpic. После того, как я изучил источник и некоторую отладку, я удалил строки, связанные с isatty и все работало как ожидалось снова.

Но я соглашаюсь с Вами, что этот опыт является очень тревожащим ;)

9
27.01.2020, 19:34
  • 1
    я действительно думал, что у меня было свое искупление. Но (1) рассмотрение источника (test.c файл в xinput исходном пакете) нет никакого появления isatty тестирование сделано. ouput сгенерирован printf функция (я думаю, что это - стандарт C), один. Я добавил некоторых fprintf(stderr,"output") и это возможно перенаправить +, доказывает, что целый код действительно runned в случае xinput. Спасибо за предложение, в конце концов, это был первый след здесь. –  humanityANDpeace 28.12.2012, 13:11

Да. Я даже сделал это во времена DOS, когда я запрограммировал в Паскале. Я предполагаю, что принцип все еще содержит:

  1. Близкий stdout
  2. Вновь откройте stdout как консоль
  3. Запишите вывод в stdout

Это действительно повреждало любые каналы.

-1
27.01.2020, 19:34
  • 1
    “ Вновь открыл stdout”: stdout определяется как дескриптор файла 1. Можно ли вновь открыть дескриптор файла 1, но какой файл Вы открыли бы? Вы, вероятно, имеете в виду открытый терминал, в этом случае не имеет значения, пишет ли программа в fd 1. спасибо –  Gilles 'SO- stop being evil' 29.12.2012, 01:08
  • 2
    @Gilles файл был "доводом"против"": насколько я помню - но да, я совершенствовал точку 2 в том направлении. –  Nils 29.12.2012, 23:54
  • 3
    con название DOS того, что называет Unix /dev/tty, т.е. (управление) терминал. –  Gilles 'SO- stop being evil' 30.12.2012, 00:15

В Вашем test.c файл Вы могли сбросить буферизированное использование данных (void)fflush(stdout); непосредственно после Вашего printf операторы.

    // in test.c
    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);
    //(void)fflush(NULL);
    (void)fflush(stdout);

На командной строке можно включить вывод с буфером строки путем выполнения xinput test 10 в псевдотерминале (имущество) с script команда.

script -q /dev/null xinput test 10 > file      # FreeBSD, Mac OS X
script -c "xinput test 10" /dev/null > file    # Linux
0
27.01.2020, 19:34

Теги

Похожие вопросы