#bash #pipe #stderr
#bash #канал #stderr
Вопрос:
Возможно, уже поздно, и у меня пукает мозг, но не должно ли это
(>amp;2 echo dying) 2>amp;1 >/dev/null
не выдает никаких выходных данных в обычной оболочке?
Аналогично, если это /tmp/x.pl
#!/usr/bin/perl
die "dying"
Тогда почему это
#> perl /tmp/x.pl 2>amp;1 >/dev/null
вывод
dying at /tmp/x.pl line 2.
?
Комментарии:
1. Это, кстати, BashFAQ #55 .
2. Также достаточно распространено, что у shellcheck есть предупреждение для этого
Ответ №1:
Перенаправления обрабатываются слева направо. Итак, что вы делаете, 2>amp;1
прежде чем делать >/dev/null
. Это перенаправляет FD 2 на исходное соединение FD 1 (предположительно, терминал), а затем перенаправляет FD 1 на /dev/null
. FD 2 все еще подключен к терминалу.
Чтобы перенаправить оба stdout
и stderr
на /dev/null
, вы должны использовать
(>amp;2 echo dying) >/dev/null 2>amp;1
Ответ №2:
Порядок, в котором выполняется перенаправление файловых дескрипторов, очень важен.
Просто переключите заказы:
(>amp;2 echo dying) >/dev/null 2>amp;1
perl /tmp/x.pl >/dev/null 2>amp;1
Пока вы делаете:
(>amp;2 echo dying) 2>amp;1 >/dev/null
СТАНДАРТНЫЙ вывод подоболочки ( ()
) перенаправляется туда, где STDERR подоболочки является первым. Затем в родительской (основной) оболочке вы перенаправили STDERR на стандартный вывод, который в этот момент указывает на терминал, поэтому будет напечатан стандартный вывод из подоболочки, затем вы перенаправляете стандартный вывод, на /dev/null
который будет отправлен стандартный /dev/null
вывод с этого момента оценки, а не раньше.
Аналогичное замечание относится и ко второму случаю.
Итак, всегда поддерживайте порядок при работе с файловыми дескрипторами и порядок вычисления, если слева направо.