Перенаправить все последующие команды 'stderr, используя exec

У меня есть файл bash, который мне нужно перенаправить весь вывод в один файл, журнал отладки, а также на терминал. Мне нужно перенаправить как stdout, так и stderr в debug и записать его для всех команд в скрипте.

Я не хочу добавлять 2>&1 | tee -a $DEBUG для каждой отдельной команды в файле. Я мог бы жить с помощью | tee -a $DEBUG.

Я помню, что был способ сделать это с помощью чего-то вроде exec 2>&1.

В настоящее время я использую что-то вроде следующего:

#!/bin/bash
DEBUGLOG=/tmp/debug
exec 2>&1
somecommand | tee -a $DEBUGLOG
somecommand2 | tee -a $DEBUGLOG
somecommand3 | tee -a $DEBUGLOG

, но это не сработает. Кто-нибудь имеет решение /может объяснить причину?

33 голоса | спросил Avi 20 Jpm1000000pmSun, 20 Jan 2013 22:01:27 +040013 2013, 22:01:27

1 ответ


35

Что касается решения для перенаправления сразу нескольких команд:

#!/bin/bash
{
    somecommand 
    somecommand2
    somecommand3
} 2>&1 | tee -a $DEBUGLOG

Почему ваше исходное решение не работает: exec 2> & 1 перенаправит стандартный вывод ошибки на стандартный вывод вашей оболочки, который, если вы запустите свой скрипт из консоли, будет вашей консолью. перенаправление каналов на команды будет перенаправлять только стандартный вывод команды.

С точки зрения somecommand, его стандартный вывод переходит в канал, подключенный к tee, а стандартная ошибка переходит в тот же файл /псевдофайл, что и стандартная ошибка оболочки, которую вы перенаправляете на стандартный вывод оболочки, который будет консолью, если вы запустите свою программу с консоли.

Единственный истинный способ объяснить это - увидеть, что на самом деле происходит:

Первоначальная среда вашей оболочки может выглядеть так, если вы запустите ее с терминала:

stdin -> /dev/pts/42
stdout -> /dev/pts/42
stderr -> /dev/pts/42

После перенаправления стандартной ошибки на стандартный вывод (exec 2>&1), вы ... ничего не меняете. Но если вы перенаправите стандартный файл сценария в файл, вы получите такую ​​среду:

stdin -> /dev/pts/42
stdout -> /your/file
stderr -> /dev/pts/42

Тогда перенаправление стандартной ошибки оболочки в стандартный вывод закончится следующим образом:

stdin -> /dev/pts/42
stdout -> /your/file
stderr -> /your/file

Запуск команды наследует эту среду. Если вы запустите команду и подключите ее к tee, среда команды будет:

stdin -> /dev/pts/42
stdout -> pipe:[4242]
stderr -> /your/file

Таким образом, стандартная ошибка вашей команды по-прежнему связана с тем, что оболочка использует в качестве стандартной ошибки.

Фактически вы можете увидеть окружение команды, просмотрев /proc/[pid]/fd: use ls -l, чтобы также отобразить содержимое символической ссылки. Файл 0 здесь является стандартным вводом, 1 является стандартным выходом, а 2 является стандартной ошибкой. Если команда открывает больше файлов (и большинство программ), вы также увидите их. Программа также может выбрать перенаправление или закрытие стандартного ввода /вывода и повторное использование 0, 1 и 2.

ответил BatchyX 20 Jpm1000000pmSun, 20 Jan 2013 22:16:43 +040013 2013, 22:16:43

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132