Как я могу достичь
cmd >> file1 2>&1 1>>file2
То есть stdout и stderr должны перенаправлять на один файл (file1), и только stdout (file2) должен перенаправлять на другой (оба в режиме добавления)?
Как я могу достичь
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для дублирования вывода для всех целей.
cmd >& file1 > file2
Вы можете: пометить stdout (используя UNBUFFERED sed, то есть:) sed -u ..., заставить stderr также перейти к stdout (без тегов, так как он не прошел через это пометку sed), и, таким образом, иметь возможность различать 2 в результирующем лог-файле.
Следующее: медленно (его можно серьезно оптимизировать, используя для примера сценарий perl вместо while ...; do ...; done, для примера, который будет порождать подоболочки и команды в каждой строке!), Странно (кажется, мне нужно 2 {} этапов для того, чтобы в одном stdout переименовать, а затем в другом добавить к нему stderr «свернул») и т. д. Но это: « доказательство концепции », которое будет пытаться сохранить порядок вывода максимально возможного количества stdout & stderr:
#basic principle (some un-necessary "{}" to visually help see the layers):
# { { complex command ;} | sed -e "s/^/TAGstdout/" ;} 2>&1 | read_stdin_and_redispatch
#exemple:
# complex command = a (slowed) ls of several things (some existing, others not)
# to see if the order of stdout&stderr is kept
#preparation, not needed for the "proof of concept", but needed for our specific exemple setup:
\rm out.file out_AND_err.file unknown unknown2
touch existing existing2 existing3
#and the (slow, too many execs, etc) "proof of concept":
uniquetag="_stdout_" # change this to something unique, that will NOT appear in all the commands outputs...
# avoid regexp characters ("+" "?" "*" etc) to make it easy to remove with another sed later on.
{
{ for f in existing unknown existing2 unknown2 existing3 ; do ls -l "$f" ; sleep 1; done ;
} | sed -u -e "s/^/${uniquetag}/" ;
} 2>&1 | while IFS="" read -r line ; do
case "$line" in
${uniquetag}*) printf "%s\n" "$line" | tee -a out_AND_err.file | sed -e "s/^${uniquetag}//" >> out.file ;;
*) printf "%s\n" "$line" >> out_AND_err.file ;;
esac;
done;
# see the results:
grep "^" out.file out_AND_err.file
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 должен быть сохранен во временном файле
cmd 2>>file-err | tee -a file1 >>file2
cat file-err >> file1
rm file-err
Описание:
Единственный способ перенаправить один вывод (например, stdout или stderr) на два файла - это воспроизвести его. Команда teeявляется правильным инструментом для воспроизведения содержимого файлового дескриптора. Итак, первоначальной идеей иметь один вывод для двух файлов было бы использовать:
... | tee file1 file2
Это воспроизводит stdin of tee для обоих файлов (1 и 2), оставляя выходные данные tee по-прежнему неиспользованными. Но нам нужно добавить (использовать -a) и только одну копию. Это решает обе проблемы:
... | tee -a file1 >>file2
Чтобы предоставить teestdout (тот, который нужно повторить), нам нужно использовать stderr непосредственно из команды. С одной стороны, если порядок не важен (порядок вывода (скорее всего) будет сохранен как сгенерированный, в зависимости от того, что выводится первым, он будет сохранен первым). Или:
cmd 2>>file1 | tee -a file2 >>file1cmd 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 | tee -a /dev/stderr) 2>> file1 >> file2
буду работать. Стандартный вывод команды cmd
отправляется как в stdout, так и в stderr конвейера. Стандартная ошибка cmdобходит tee
и выходит из stderr конвейера.
Так
cmd, иcmdсмешанного.Тогда просто отправить эти потоки в правильные файлы.
Как и в случае почти любого подобного подхода (включая ответ Стефана ),
file1строки могут быть не в порядке.
out+errиoutчто здесь значит. Имена файлов? Потоки будут перенаправлены?