Почему это не перенаправляет на /dev/null?

#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 вывод с этого момента оценки, а не раньше.

Аналогичное замечание относится и ко второму случаю.

Итак, всегда поддерживайте порядок при работе с файловыми дескрипторами и порядок вычисления, если слева направо.