Как я могу достичь
cmd >> file1 2>&1 1>>file2
То есть stdout и stderr должны перенаправлять на один файл (file1), и только stdout (file2) должен перенаправлять на другой (оба в режиме добавления)?
Проблема в том, что когда вы перенаправляете свой вывод, он больше не доступен для следующего перенаправления. Вы можете передать tee
в подоболочку, чтобы сохранить выходные данные для второго перенаправления:
( cmd | tee -a file2 ) >> file1 2>&1
или если вы хотите увидеть вывод в терминале:
( cmd | tee -a file2 ) 2>&1 | tee -a file1
Чтобы не добавлять stderr первого tee
в file1
, вы должны перенаправить stderr вашей команды в некоторый файловый дескриптор (например, 3), а затем снова добавить это в stdout:
( 2>&3 cmd | tee -a file2 ) >> file1 3>&1
# or
( 2>&3 cmd | tee -a file2 ) 3>&1 | tee -a file1
(спасибо @ фра-сан)
С zsh
:
cmd >& out+err.log > out.log
В режиме добавления:
cmd >>& out+err.log >> out.log
В zsh
и при условии, что mult_ios
опция не была отключена, когда дескриптор файла (здесь 1) перенаправляется несколько раз для записи, тогда оболочка реализует встроенную функцию tee
для дублирования вывода для всех целей.
out+err
иout
что здесь значит. Имена файлов? Потоки будут перенаправлены?cmd >& file1 > file2
Вы можете: пометить stdout (используя UNBUFFERED sed, то есть:)
sed -u ...
, заставить stderr также перейти к stdout (без тегов, так как он не прошел через это пометку sed), и, таким образом, иметь возможность различать 2 в результирующем лог-файле.Следующее: медленно (его можно серьезно оптимизировать, используя для примера сценарий perl вместо while ...; do ...; done, для примера, который будет порождать подоболочки и команды в каждой строке!), Странно (кажется, мне нужно 2 {} этапов для того, чтобы в одном stdout переименовать, а затем в другом добавить к нему stderr «свернул») и т. д. Но это: « доказательство концепции », которое будет пытаться сохранить порядок вывода максимально возможного количества stdout & stderr:
источник
ls unknown
) для печати чего-либо на stderr?>&2 echo "error"
было бы хорошо. (2)tee
можно добавлять к нескольким файлам одновременно. (3) Почему бы не простоcat
вместоgrep "^"
? (4) ваш скрипт потерпит неудачу, когда вывод stderr начнется с_stdout_
. (5) почему?ls loop
будет выводить как на stdout, так и на stderr, смешанные (альтернативно), в контролируемом порядке, чтобы мы могли проверить, что мы сохранили порядок stderr / stdout, несмотря на пометку stdout 2): возможно, gnu tail, но не регулярный хвост (напр., на aix.). 3): grep "^" также показывает оба имени файла. 4): это может быть изменено переменной. 5): извилистый пример работает на старых oses (ex, old aix), где я его тестировал (нет доступных perl).uniquetag="banaNa11F453355B28E1158D4E516A2D3EDF96B3450406
...)Если порядок вывода должен быть следующим: stdout, то stderr ; нет решения только с перенаправлением.
Stderr должен быть сохранен во временном файле
Описание:
Единственный способ перенаправить один вывод (например, stdout или stderr) на два файла - это воспроизвести его. Команда
tee
является правильным инструментом для воспроизведения содержимого файлового дескриптора. Итак, первоначальной идеей иметь один вывод для двух файлов было бы использовать:Это воспроизводит stdin of tee для обоих файлов (1 и 2), оставляя выходные данные tee по-прежнему неиспользованными. Но нам нужно добавить (использовать
-a
) и только одну копию. Это решает обе проблемы:Чтобы предоставить
tee
stdout (тот, который нужно повторить), нам нужно использовать stderr непосредственно из команды. С одной стороны, если порядок не важен (порядок вывода (скорее всего) будет сохранен как сгенерированный, в зависимости от того, что выводится первым, он будет сохранен первым). Или:cmd 2>>file1 | tee -a file2 >>file1
cmd 2>>file1 > >( tee -a file2 >>file1 )
( cmd | tee -a file2 ) >> file1 2>&1
Вариант 2 работает только в некоторых оболочках. Вариант 3 использует дополнительную подоболочку (медленнее), но использует имена файлов только один раз.
Но если stdout должен быть первым (какой бы вывод заказа не был сгенерирован), нам нужно сохранить stderr, чтобы добавить его в файл в конце (первое опубликованное решение).
источник
sponge
делает:(cmd | tee -a out >> out+err) 2>&1 | sponge >> out+err
В интересах разнообразия:
Если ваша система поддерживает
/dev/stderr
, тобуду работать. Стандартный вывод команды
cmd
отправляется как в stdout, так и в stderr конвейера. Стандартная ошибкаcmd
обходитtee
и выходит из stderr конвейера.Так
cmd
, иcmd
смешанного.Тогда просто отправить эти потоки в правильные файлы.
Как и в случае почти любого подобного подхода (включая ответ Стефана ),
file1
строки могут быть не в порядке.источник