Как перенаправить stderr и stdout в разные файлы, а также отобразить в терминале?

30

Я хочу видеть вывод команды в терминале, как если бы не было перенаправления. Кроме того, stderr необходимо перенаправить на err.log, а stdout - на stdout.log.

Было бы также неплохо иметь точную копию того, что отображается в терминале, т.е. ошибки, напечатанные как и когда это происходит, в отдельном файле: stdouterr.log.

Балки
источник
@ Нуно Нет, это не так. ОП хочет иметь разные файлы для stdout и stderr.
Dogbane
@ Dogbane Да, ты прав. Прости за это.
Нуно К. Инасиу
Я до сих пор нахожу этот вопрос очень знакомым. Позвольте мне посмотреть ... Вот очень похожий unix.stackexchange.com/q/4195/250 , а вот связанный unix.stackexchange.com/q/1416/250
phunehehe

Ответы:

37

Используйте teeкоманду следующим образом:

(cmd | tee stdout.log) 3>&1 1>&2 2>&3 | tee stderr.log

3>&1 1>&2 2>&3 это то, как вы меняете stderr и stdout, потому что tee может принимать только stdout.

Взгляните на команду Unix tee для более продвинутого использования перенаправлений tee.

кендырь
источник
Хорошее решение. Есть ли способ получить код выхода cmd?
turbanoff
2
@turbanoff Заменить cmdна (cmd ; echo >exit_code.txt $?).
Парфянский выстрел
Я считаю, что это должно лучше сохранить порядок вещей, выводимых в командную строку:((cmd | tee stdout.log) 3>&1 1>&2 2>&3 | tee stderr.log)
TTT
5

Я думаю, что запись stdout и stderr в два разных файла - отличная идея. Разве это не делает журналы асинхронными? Поэтому я опробовал следующее:

  • стандартный вывод "stdout.log" (как и предполагал догбейн)
  • stderror к "stderr.log" (как предположил догбейн)
  • все вывести на «all.log» и
  • все еще будет в состоянии видеть вывод на дисплее (хотя в отдельном терминале!)

((cmd | tee stdout.log) 3>&1 1>&2 2>&3 | tee stderr.log) &> all.log

в другом терминале

tail -f --sleep-interval=2 all.log
Sreeni
источник
Разве нельзя напрямую направить stderr ко второму tty? Тогда никакой лог-файл не требуется.
Стивен Лу
@ StevenLu Да, если вы знаете имя и имеете разрешение на запись во второй tty, это можно сделать.
Jasen
1
проще было бы &| tee all.logна конце команды вместо&> all.log
Jasen
@Jasen: второй раз вижу &|. Я тоже понимаю &>, |&но что &|значит в этом контексте? Я не смог найти подходящую ссылку на синтаксис, не в сети, даже не обращаясь к странице руководства bash "bash (1)" ... Tx
Cbhihe
1
@ Cbhihe, насколько я могу судить, ничего не делает, я хотел сказать|&
Jasen
3

@ Dogbane, спасибо.
Я также нашел другой способ, который сохраняет оба потока примерно в том порядке, в котором они будут напечатаны без перенаправления.

command 2> >(tee errlog | tee -a bothLog > /dev/tty ) | tee outlog | tee -a bothLog

Но это работает только с оболочками, которые поддерживают процесс замены.

Балки
источник
-2

попробуй это :

command 2>&1 | tee bothLog
Василе
источник
4
Здравствуйте vasile, это не отвечает на вопрос: balki нужны отдельные файлы для stdout и stderr, ваше решение будет смешивать оба в одном потоке.
Мат
Почему люди объединяют stdout и stderr вместе? Или сказать другим, чтобы сделать это?
nurettin