Как трубу stderr, а не stdout?

Просто зайдите на Android-монитор устройства из студии Android, затем DDMS -> Emulator Control. Там будут свойства скорости и задержки.

896
задан Jonathan Leffler 2 June 2016 в 20:05
поделиться

4 ответа

Первое перенаправление stderr на stdout - канал; затем перенаправьте stdout на / dev / null (без изменения того, куда идет stderr):

command 2>&1 >/dev/null | grep 'something'

Подробнее о перенаправлении ввода-вывода во всем его разнообразии см. в главе о Перенаправлениях в справочном руководстве Bash.

Обратите внимание, что последовательность перенаправлений ввода-вывода интерпретируется слева направо, но каналы устанавливаются до того, как интерпретируются перенаправления ввода-вывода. Дескрипторы файлов, такие как 1 и 2, являются ссылками на описания открытых файлов. Операция 2> & 1 заставляет файловый дескриптор 2, также известный как stderr, ссылаться на то же описание открытого файла, на которое в настоящее время ссылается файловый дескриптор 1, известный как stdout (см. dup2 () и open () ). Операция > / dev / null затем изменяет файловый дескриптор 1 так, чтобы он ссылался на описание открытого файла для / dev / null , но это не меняет того факта, что файловый дескриптор 2 относится к описанию открытого файла, на которое изначально указывал файловый дескриптор 1, а именно, канал.

1124
ответ дан 19 December 2019 в 20:20
поделиться

Для тех, кто хочет перенаправить stdout и stderr навсегда в файлы, используйте grep для stderr, но оставляйте stdout для записи сообщений в tty:

# save tty-stdout to fd 3
exec 3>&1
# switch stdout and stderr, grep (-v) stderr for nasty messages and append to files
exec 2> >(grep -v "nasty_msg" >> std.err) >> std.out
# goes to the std.out
echo "my first message" >&1
# goes to the std.err
echo "a error message" >&2
# goes nowhere
echo "this nasty_msg won't appear anywhere" >&2
# goes to the tty
echo "a message on the terminal" >&3
9
ответ дан JBD 2 June 2016 в 20:05
поделиться

Гораздо проще визуализировать вещи, если вы думаете о том, что на самом деле происходит с «перенаправлениями» и «каналами». Перенаправления и каналы в bash делают одно: изменяют место, на которое указывают дескрипторы файлов процессов 0, 1 и 2 (см. / Proc / [pid] / fd / *).

Когда труба или "|" оператор присутствует в командной строке, первое, что должно произойти, это то, что bash создает fifo и указывает FD 1 команды левой стороны на это fifo и указывает FD 0 команды правой стороны на то же самое fifo.

Далее, операторы перенаправления для каждой стороны оцениваются слева направо , и текущие настройки используются всякий раз, когда происходит дублирование дескриптора. Это важно, потому что, поскольку канал был настроен первым, FD1 (левая сторона) и FD0 (правая сторона) уже изменились по сравнению с тем, чем они обычно могли быть, и любое их дублирование будет отражать этот факт.

Поэтому, когда вы набираете что-то вроде следующего:

command 2>&1 >/dev/null | grep 'something'

Вот что происходит по порядку:

  1. создается труба (fifo). «команда FD1» указывает на эту трубу. «grep FD0» также указывает на этот канал
  2. «команда FD2» указывает на то место, где «команда FD1» указывает в данный момент (канал)
  3. «команда FD1» указывает на / dev / null

Итак, весь вывод, который «команда» записывает в свой FD 2 (stderr), попадает в канал и читается «grep» с другой стороны. Все выходные данные, которые «команда» записывает в свой FD 1 (стандартный вывод), попадают в / dev / null.

Если вместо этого вы выполняете следующее:

command >/dev/null 2>&1 | grep 'something'

Вот что происходит:

  1. создается канал и «команда FD 1» и «grep FD» 0 "указывают на него
  2. " команда FD 1 "указывает на / dev / null
  3. " команда FD 2 "указывает на то, куда в данный момент указывает FD 1 (/ dev / null)

Итак, все stdout и stderr из «команды» переходят в / dev / null. Ничто не идет к трубе, и, таким образом, "grep" будет закрываться, не отображая ничего на экране.

Также обратите внимание, что перенаправления (файловые дескрипторы) могут быть только для чтения (<), только для записи (>) или для чтения-записи (<>).

Последнее замечание. Записывает ли программа что-то в FD1 или FD2, полностью зависит от программиста. Хорошая практика программирования гласит, что сообщения об ошибках должны идти в FD 2, а нормальный вывод - в FD 1, но вы часто найдете неаккуратное программирование, которое смешивает два или иным образом игнорирует соглашение. [+1121]

94
ответ дан Michael Martinez 2 June 2016 в 20:05
поделиться

Или чтобы поменять местами вывод stderr и stdout вместо использования: -

command 3>&1 1>&2 2>&3

Это создает новый дескриптор файла (3) и назначает его в то же место, что и 1 (stdout), затем назначает fd 1 (stdout) для в том же месте, что и fd 2 (stderr), и, наконец, назначает fd 2 (stderr) тому же месту, что и fd 3 (stdout). Stderr теперь доступен как stdout, а старый stdout сохранился в stderr. Это может быть излишним, но, надеюсь, дает более подробную информацию о файловых дескрипторах bash (для каждого процесса доступно 9).

347
ответ дан 19 December 2019 в 20:20
поделиться
Другие вопросы по тегам:

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