Подтвердить что ты не робот

Напишите 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 Перенаправление ввода/вывода, но я не могу понять это.

4b9b3361

Ответ 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