Как работают эти перенаправления потока? - PullRequest
4 голосов
/ 18 октября 2010

С этой страницы perldoc ,

  1. Чтобы захватить STDERR и STDOUT команды вместе:

    $output = `cmd 2>&1`;
  2. Чтобы захватить STDOUT команды, но сбросить ее STDERR:

    $output = `cmd 2>/dev/null`;
  3. Чтобы захватить STDERR команды, но сбросить ее STDOUT (упорядочение здесь важно):

    $output = `cmd 2>&1 1>/dev/null`;
  4. Для обмена STDOUT и STDERR команды, чтобы захватить STDERR, но оставить STDOUT для выхода из старого STDERR:

    $output = `cmd 3>&1 1>&2 2>&3 3>&-`;

Я делаюне понимаю, как работают 3 и 4, и я не очень уверен, что я понимаю, что 1 и 2 правильно.Ниже то, что я понимаю.Пожалуйста, поправьте меня, где я не прав.

Я знаю, что 0, 1 и 2 символизируют STDIN, STDOUT и STDERR.

  1. перенаправить 2 на 1, так что теперь они оба используют один и тот же поток (& экранировал 1, убедившись, что STDERR не перенаправляется в файл с именем 1 вместо этого)

  2. перенаправить 2 (STDERR) в нулевой поток, чтобы он отбрасывался

  3. Я не понимаю этого.Разве это не должно быть просто

    $output = `cmd 1>/dev/null`;

    Кроме того, если целью является получение STDERR сообщений на STDOUT, не будет ли 1>/dev/null перенаправлять все на /dev/null?

  4. Что здесь происходит?Что такое стрим 3?Это как временная переменная?

Ответы [ 4 ]

3 голосов
/ 18 октября 2010

Обычно у нас есть это:

1-->STDOUT
2-->STDERR

2>&1 перенаправляет дескриптор файла fd2 в fd1

1-->STDOUT
   /
2./

2>/dev/null перенаправляет fd2 в /dev/null.

1-->STDOUT
2-->/dev/null

2>&1 1>/dev/null перенаправляет fd2 на fd1, а затем перенаправляет fd1 на /dev/null

    /dev/null
   /
1./ STDOUT
   /
2./

3>&1 1>&2 2>&3 3>&-

  1. сначала направляет новый fd 3 туда, куда указывает текущий fd 1 (STDOUT).
  2. затем перенаправляет fd1 туда, где fd2 указывает текущее направление (STDERR),
  3. затем перенаправляет fd 2 накуда бы ни указывал fd 3 (STDOUT)
  4. , затем закрывает fd3 (3> & - означает закрытие дескриптора файла 3).

Все это эффективно заменяет fd1 и fd2.fd3 действовала как временная переменная.

1 --STDOUT
 X
2 `-STDERR

См. документы для получения дополнительной информации о перенаправлении ввода-вывода.

3 голосов
/ 18 октября 2010

Хотя это задокументировано в perldocs, перенаправление - это все стандартное перенаправление linux. Вы правильно понимаете 1 и 2.

3) Только STDOUT обычно перехватывается основным перенаправлением (>), поэтому исходный STDOUT должен быть отброшен, и STDERR должны быть отправлены в STDOUT.

4) cmd 3>&1 1>&2 2>&3 3>&- эквивалентно

var tmp = STDOUT;
STDOUT = STDERR;
STDERR = tmp;
delete tmp;
3 голосов
/ 18 октября 2010

На самом деле, ничто из этого не является Perl - все это обрабатывается оболочкой, которую вы вызываете с помощью оператора backticks. Поэтому лучше всего читать man sh или главу Shell стандарта Unix .

Короче говоря, для # 4:

  • 3>&1: Откройте FD 3, чтобы указать, куда в данный момент указывает стандартный вывод.
  • 1>&2: вновь открыть стандартный вывод, чтобы указать, куда в данный момент указывает стандартный вывод.
  • 2>&3: снова откройте stderr, чтобы указать, куда в данный момент указывает FD 3, и именно там указывал стандартный вывод до того, как был завершен предыдущий шаг. Теперь stdout и stderr были успешно заменены.
  • 3>&-: закройте FD 3, потому что он больше не нужен.
0 голосов
/ 18 октября 2010

3.Nope. Порядок имеет значение, поэтому он избавляется от исходного stdout, а затем перемещает stderr в stdout.

4. 3 - это просто другой файловый дескриптор, такой же, как и первый 3. Большинство процессов могут использовать в общей сложности 256 различных файловых дескрипторов.

...