РЕДАКТИРОВАТЬ

РЕДАКТИРОВАТЬ

РЕДАКТИРОВАТЬ

Пожалуйста, просмотрите не только принятый ответ, но и другие.

Вопрос

Почему перенаправление STDOUT и STDERR в один и тот же файл не работает, хотя выглядит так же, как 1>[FILENAME] 2>&1 ?

Вот пример:

perl -e 'print "1\n" ; warn "2\n";' 1>a.txt 2>a.txt
cat a.txt
# outputs '1' only.

Ну, почему? Я думал, что это работает, потому что... STDOUT перенаправляется в a.txt, как и STDERR. Что случилось с STDERR?

решение1

Оба ваших перенаправления обрезают файл, поэтому второе (в хронологическом порядке выполнения) перезапишет первое. Попробуйте

rm a.txt ; touch a.txt ; perl -e 'print "1\n" ; warn "2\n";' 1>>a.txt 2>>a.txt

Или просто используйте тот же дескриптор файла

perl -e 'print "1\n" ; warn "2\n";' 1>a.txt 2>&1

решение2

При этом 1>a.txt 2>&1дескриптор файла №1 равендублированныйк № 2. Они оба ссылаются на один и тот же «открытый файл», и оба имеют общую текущую позицию и режим чтения/записи. (На самом деле нет никакой разницы между использованием 2>&1 и 2<&1.)

При использовании 1>a.txt 2>a.txtоба файловых дескриптора являютсяоткрылся независимои имеют отдельные позиции курсора. (Файл также усекается дважды.) Если вы напишете «Hello» в fd #1, его позиция переместится на байт 5, но fd #2 останется на байте 0. Печать в fd #2 просто перезапишет данные, начиная с 0.

Это легко увидеть, если вторая запись короче:

$ perl -e 'STDOUT->print("abcdefg\n"); STDOUT->flush; STDERR->print("123");' >a.txt 2>a.txt

$ cat a.txt 
123defg

Обратите внимание, что Perl имеет внутреннюю буферизацию, поэтому в этом примере явный flush() необходим для того, чтобы гарантировать, что данные fd #1 будут записаны до данных fd #2. В противном случае потоки будут сброшены в непредсказуемом порядке при выходе.

Для сравнения, если дескрипторы файлов являются общими, записи просто следуют друг за другом:

$ perl -e 'STDOUT->print("abcdefg\n"); STDOUT->flush; STDERR->print("123");' >a.txt 2>&1

$ cat a.txt 
abcdefg
123

Связанный контент