Я ищу a bash
управляйте, где я могу перенаправить:
Я нашел способы, где stderr добавит в конец файла после stdout, но я хочу его так, чтобы выходной файл заказал все, что вывод хронологически как он был бы, если я должен был просто использовать command &> file
.
Я попробовал:
command 2>&1 1>logfile | tee -a logfile
command 2> >(tee -a logfile) 1>>logfile
Я в основном хотел бы, чтобы выходной файл был тем же, как будто я просто сделал command &> logfile
, пока одновременно продолжают печатать сообщения stderr к консоли.
Давайте создадим тестовую функцию, которая отправляет некоторый вывод и в stdout и в stderr:
$ cmd() { echo 1 on stdout; echo 2 on stderr >&2; echo 3 on stdout; echo 4 on stderr >&2; }
Выполнение его мы видим:
$ cmd
1 on stdout
2 on stderr
3 on stdout
4 on stderr
Теперь, мы хотим отправить stdout в файл и stderr и в файл и в экран. Для этого мы используем простое перенаправление для stdout, и для stderr мы перенаправляем в замену процесса, которая добавляет в файл и передает вывод обратно stderr:
$ cmd > cmd.out 2> >( tee -a cmd.out >&2 )
2 on stderr
4 on stderr
$ cat cmd.out
1 on stdout
3 on stdout
2 on stderr
4 on stderr
Я не знаю о способе сохранить хронологический порядок смешанного stdout и сообщений stderr.
Я не думаю, что можно действительно сделать это.
Когда Вы перенаправляете stdout
и stderr
отдельно, они становятся несинхронизируемыми, и нет никакого способа зафиксировать их назад снова. То, что Вы пытаетесь сделать, является чем-то вроде этого:
+------> terminal
|
cmd -(stderr)--> tee ----> file
| ^
+---(stdout)---------------+
Здесь, существует два параллельных пути от cmd
кому: file
, с дополнительным процессом в stderr
путь. В зависимости от планирования могли бы быть задержки пути, который включает tee
, который может и приводить к stderr
сообщения отложены.
Для предотвращения этого система должна была бы переключиться на tee
сразу, когда это вводится. Обычно, на это нельзя рассчитывать, чтобы сделать это. Добавление другого процесса к параллельному пути не поможет, поскольку затем результат будет просто зависеть от планирования между двумя промежуточными процессами (вместо cmd
и tee
).
Это работает, если Вы добавляете stdout в файл и перенаправляете stderr к tee
, также добавляя в файл:
$ bash -c "echo a;bahs;echo b;bhas" >>file 2> >( tee -a file >&2 )
bash: bahs: command not found
bash: bhas: command not found
$ cat file
a
bash: bahs: command not found
b
bash: bhas: command not found
Это не работает с тестом из ответа glenn jackman, и я не могу перенести голову почему.
Вы можете сделать что-то вроде этого:
echo "asd" | xargs -I % sh -c 'echo % && echo % > asd'
Первое эхо передается в xargs, который принимает его в качестве аргумента и создает две команды эха, первый результат выводится на терминал, а второй - в файл назван также asd как текст.
Вы можете установить переадресацию после, чтобы соответствовать вашим потребностям.