Значение открытого (STDERR, "> & STDOUT") - PullRequest
2 голосов
/ 07 июля 2019

я нахожу это в одном примере сценария, Затем я ищу в Google и нашел следующие слова,

Обратите внимание, что вы не можете просто открыть STDERR, чтобы быть дубликатом STDOUT в вашем Perl Запрограммируйте и не вызывайте оболочку для перенаправления. Это не работа:

open(STDERR, ">&STDOUT");

Это не удалось, потому что open () заставляет STDERR идти туда, куда собирался STDOUT время открытия (). Затем обратные пометки заставляют STDOUT переходить к строке, но не изменяйте STDERR (который все еще идет к старому STDOUT).

Теперь я в замешательстве. Что именно означает open(STDERR, ">&STDOUT");?

Ответы [ 2 ]

5 голосов
/ 07 июля 2019

При & в режиме >& при вызове

open STDERR, ">&STDOUT";  # or: open STDERR, ">&", \*STDOUT

первый указанный дескриптор файла становится копией второго. См. , откройте и посмотрите man 2 dup2, поскольку это происходит через dup2 системный вызов. Обозначения соответствуют перенаправлению ввода / вывода оболочки . Так как здесь существует первый дескриптор файла (STDERR) & dagger; , он сначала закрывается.

Эффект состоит в том, что отпечатки на STDERR будут идти туда, куда STDOUT шел до того, как это было сделано, с побочным эффектом оригинального STDERR, закрытым.

Это допустимо и не приводит к ошибкам, но не является хорошим способом перенаправления STDERR в целом - после этого мы больше не можем восстановить STDERR. См. open о том, как перенаправить STDERR.

Остальная часть комментария явно относится к ситуации, когда после этого вызова open используются обратные галочки (см. qx * ​​1032 *), которые перенаправляют STDOUT выполненной команды (ей) на программу. , Все это, похоже, относится к идее перенаправления STDERR на STDOUT таким образом.

Увы, STDERR, сделанный этим open призывом идти туда, куда шел STDOUT, не перенаправляется обратными чертами и, таким образом, все еще идет "туда". В моем случае печать на STDERR заканчивается на терминале, когда я вижу предупреждение (ls: cannot access...) с

perl -we'open STDERR, ">&STDOUT"; $out = qx(ls no_such)'

(в отличие от perl -we'$out = qx(ls no_such 2>&1)'). Явные распечатки на STDERR также отправляются на терминал как STDOUT (добавьте такие распечатки и перенаправьте вывод в файл для просмотра).

Этого можно ожидать, поскольку & сделал копию дескриптора файла, поэтому «новый» (прежний STDERR) по-прежнему идет туда, куда шел STDOUT, то есть к Терминал. Что, конечно, непреднамеренно в этом случае и, следовательно, ошибка


& dagger; & thinsp; Каждая программа в UNIX подключается к стандартным потокам stdin, stdout и stderr, с файловыми дескрипторами 0, 1 и 2 соответственно. В программе на Perl мы получаем готовые файловые дескрипторы для них, например STDERR (для fd 2).

Некоторые полезные посты о манипуляциях с дескрипторами файлов в оболочке:

2 голосов
/ 07 июля 2019

Это в основном dup2(fileno(STDOUT), fileno(STDERR)).См. Справочную страницу dup2 вашей системы.

Короче говоря, она ассоциирует STDERR с тем же потоком, что и STDOUT на системном уровне.После выполнения команды запись в любую из них будет аналогична записи в STDOUT до изменения.

Если кто-то не запутался в STDOUT или STDERR, это эквивалентно команде оболочки

exec 2>&1
...