Напишите STDOUT & STDERR в файл журнала, также напишите STDERR на экран
Я хотел бы запустить несколько команд и захватить весь вывод в файл журнала. Я также хочу напечатать любые ошибки на экране (или, возможно, отправить кому-то сообщение).
Вот пример. Следующая команда будет запускать три команды и будет записывать весь вывод (STDOUT и STDERR) в один файл журнала.
{ command1 && command2 && command3 ; } > logfile.log 2>&1
Вот что я хочу сделать с выходом этих команд:
- STDERR и STDOUT для всех команд отправляются в файл журнала, в случае, если он мне понадобится позже. Обычно я не буду смотреть здесь, если не возникнут проблемы.
- Распечатайте STDERR на экран (или, необязательно, на канал /bin/mail ), чтобы какая-либо ошибка выделялась и не игнорируется.
-
Было бы неплохо, если бы коды возврата были еще пригодны для использования, чтобы я мог выполнять обработку ошибок. Возможно, я хочу отправить электронное сообщение, если произошла ошибка, например:
{command1 && command2 && command3; } > logfile.log 2 > & 1 || mailx -s "Произошла ошибка" [email protected]
Проблема, с которой я сталкиваюсь, заключается в том, что STDERR теряет контекст во время перенаправления ввода-вывода. A '2 > & 1' преобразует STDERR в STDOUT, и поэтому я не могу просматривать ошибки, если я делаю 2 > error.log
Вот несколько более сочных примеров. Предположим, что я запускаю некоторые знакомые команды сборки, но я не хочу, чтобы вся сборка остановилась только из-за одной ошибки, поэтому я использую флаг "-keep-going".
{ ./configure && make --keep-going && make install ; } > build.log 2>&1
Или здесь простая (и, возможно, неаккуратная) сборка и развертывание script, которая будет продолжаться в случае ошибки.
{ ./configure && make --keep-going && make install && rsync -av --keep-going /foo devhost:/foo} > build-and-deploy.log 2>&1
Я думаю, что я хочу использовать Bash Перенаправление ввода/вывода, но я не могу понять это.
Ответы
Ответ 1
(./doit >> log) 2>&1 | tee -a log
Это займет stdout и добавит его в файл журнала.
Затем stderr преобразуется в stdout, который отправляется на tee
, который добавляет его в журнал (если у вас есть Bash 4, вы можете заменить 2>&1 |
на |&
) и отправит его на стандартный вывод который либо появится на tty, либо может быть передан в другую команду.
Я использовал режим добавления для обоих, так что независимо от того, какой порядок перенаправления оболочки и tee
открыть файл, вы не сдуете оригинал. Тем не менее, возможно, что stderr/stdout чередуется неожиданным образом.
Ответ 2
Если ваша система имеет /dev/fd/ * узлы, вы можете сделать это как:
( exec 5>logfile.txt ; { command1 && command2 && command3 ;} 2>&1 >&5 | tee /dev/fd/5 )
Это открывает файловый дескриптор 5 в вашем файле журнала. Выполняет команды со стандартной ошибкой, направленной на стандартную версию, стандартную версию, направленную на fd 5, и на трубы stdout (которая теперь содержит только stderr) на tee, которая дублирует вывод на fd 5, который является файлом журнала.
Ответ 3
Вот как запустить одну или несколько команд, захватив стандартный вывод и ошибку в том порядке, в котором они сгенерированы, в файл журнала и отобразить только стандартную ошибку на любом экране терминала, который вам нравится. Работает в bash на linux. Вероятно, работает в большинстве других сред. Я буду использовать пример, чтобы показать, как это делается.
Отборочный:
Откройте два окна (оболочки, сеансы tmux, что угодно)
Я продемонстрирую несколько тестовых файлов, поэтому создайте тестовые файлы:
touch /tmp/foo /tmp/foo1 /tmp/foo2
в окне1:
mkfifo /tmp/fifo
0</tmp/fifo cat - >/tmp/logfile
Затем в окне2:
(ls -l /tmp/foo /tmp/nofile /tmp/foo1 /tmp/nofile /tmp/nofile; echo successful test; ls /tmp/nofile1111) 2>&1 1>/tmp/fifo | tee /tmp/fifo 1>/dev/pts/2
Когда вы заменяете /dev/pts/2
на любое значение tty, которое вы хотите отобразить stderr.
Причиной для различных успешных и неудачных команд в подоболочке является просто создание смешанного потока выходных и сообщений об ошибках, чтобы вы могли проверить правильность заказа в файле журнала. Как только вы поймете, как это работает, замените команды "ls" и "echo" на скрипты или команды по вашему выбору.
С помощью этого метода упорядочение вывода и ошибки сохраняется, синтаксис прост и чист, и есть только одна ссылка на выходной файл. Кроме того, существует гибкость при размещении дополнительной копии stderr везде, где вы хотите.
Ответ 4
Try:
command 2>&1 | tee output.txt
Кроме того, вы можете направить stdout и stderr в разные места:
command > stdout.txt >& stderr.txt
command > stdout.txt |& program_for_stderr
Итак, какая-то комбинация из вышеперечисленного должна работать для вас - например, вы можете сохранить stdout в файл и stderr как в файл, так и в другую программу (с tee).
Ответ 5
добавьте это в начало вашего script
#!/bin/bash
set -e
outfile=logfile
exec > >(cat >> $outfile)
exec 2> >(tee -a $outfile >&2)
# write your code here
STDOUT
и STDERR
будут записаны в $outfile
, на консоли будет отображаться только STDERR