Как перенаправить stderr в файл
При использовании команды nohup для запуска команды в фоновом режиме часть содержимого отображается в терминале.
cp: error reading ‘/mnt/tt/file.txt’: Input/output error
cp: failed to extend ‘/mnt/tt/file.txt’: Input/output error
Я хочу сохранить этот контент в файл.
2 ответа
В Linux (и других ОС) есть два основных потока вывода: стандартный вывод (stdout) и стандартная ошибка (stderr). Сообщения об ошибках, как те, которые вы показываете, печатаются со стандартной ошибкой. Классический оператор перенаправления (command > file
) перенаправляет только стандартный вывод, поэтому стандартная ошибка по-прежнему отображается на терминале. Для перенаправления stderr у вас есть несколько вариантов:
Перенаправить стандартный вывод в один файл и стандартный вывод в другой файл:
command > out 2>error
Перенаправить stderr на стандартный вывод (
&1
), а затем перенаправить стандартный вывод в файл:command >out 2>&1
Перенаправить оба в файл:
command &> out
Для получения дополнительной информации о различных операторах управления и перенаправления см. Здесь.
Первое, на что следует обратить внимание, это то, что есть несколько способов, в зависимости от вашей цели и оболочки, поэтому это требует небольшого понимания нескольких аспектов. Кроме того, некоторые команды, такие как time
а также strace
записывать вывод в stderr по умолчанию и может предоставлять или не предоставлять метод перенаправления, специфичный для этой команды
Основная теория, лежащая в основе перенаправления, заключается в том, что процесс, порожденный оболочкой (предполагается, что это внешняя команда, а не встроенная оболочка), создается с помощью fork()
а также execve()
системные вызовы, а до этого еще один системный вызов dup2()
выполняет необходимые перенаправления перед execve()
случается. В этом смысле перенаправления наследуются от родительской оболочки. m&>n
а также m>n.txt
сообщить оболочке о том, как выполнить open()
а также dup2()
системный вызов (см. также, как работает перенаправление ввода, в чем разница между перенаправлением и конвейером и что именно означает перенаправление вывода)
Перенаправления оболочки
Наиболее типичным является через 2>
в Supratika Banerjee, таких как dash
(который связан с /bin/sh
) а также bash
; первая - это оболочка по умолчанию и POSIX-совместимая, а вторая - то, что большинство пользователей используют для интерактивного сеанса. Они отличаются по синтаксису и возможностям, но, к счастью, для нас перенаправление потока ошибок работает одинаково (за исключением &>
нестандартный). В случае csh и его производных, перенаправление stderr там не совсем работает.
Давайте вернемся к 2>
часть. Обратите внимание на две ключевые вещи: >
означает оператор перенаправления, где мы открываем файл и 2
целое число обозначает дескриптор файла stderr; на самом деле именно так стандарт POSIX для языка оболочки определяет перенаправление в разделе 2.7:
[n]redir-op word
Для простого >
перенаправление, 1
целое число подразумевается для stdout
т.е. echo Hello World > /dev/null
это так же, как echo Hello World 1>/dev/null
, Обратите внимание, что оператор целого числа или перенаправления не может быть заключен в кавычки, в противном случае оболочка не распознает их как таковые, а вместо этого обрабатывает как текстовую строку. Что касается пробелов, важно, чтобы целое число находилось рядом с оператором перенаправления, но файл может быть либо рядом с оператором перенаправления, либо нет, т.е. command 2>/dev/null
а также command 2> /dev/null
будет работать просто отлично.
Несколько упрощенный синтаксис для типичной команды в оболочке будет
command [arg1] [arg2] 2> /dev/null
Хитрость в том, что перенаправление может появиться где угодно. Это оба 2> command [arg1]
а также command 2> [arg1]
действительны. Обратите внимание, что для bash
оболочка, там существует &>
способ перенаправить потоки stdout и stderr одновременно, но опять же - это зависит от bash, и если вы стремитесь к переносимости сценариев, он может не работать. Смотрите также Ubuntu Wiki и В чем разница между &> и 2> & 1.
Примечание: >
оператор перенаправления усекает файл и перезаписывает его, если файл существует. 2>>
может быть использован для добавления stderr
в файл.
Если вы можете заметить, >
предназначен для одной команды. Для сценариев мы можем перенаправить поток stderr всего сценария извне, как в myscript.sh 2> /dev/null
или мы можем использовать встроенный exec. Встроенный exec обладает возможностью перезаписи потока для всего сеанса оболочки, так сказать, в интерактивном режиме или с помощью сценария. Что-то вроде
#!/bin/sh
exec 2> ./my_log_file.txt
stat /etc/non_existing_file
В этом примере файл журнала должен показывать stat: cannot stat '/etc/non_existing_file': No such file or directory
,
Еще один способ - через функции. Как отметил Supratika Banerjee в своем ответе, мы можем написать объявление функции с уже прикрепленным перенаправлением, то есть
some_function(){
command1
command2
} 2> my_log_file.txt
Команды, пишущие исключительно в stderr
Такие команды как time
а также strace
записать их вывод в stderr по умолчанию. В случае time
команда, единственная жизнеспособная альтернатива - перенаправить вывод всей команды, то есть
time echo foo 2>&1 > file.txt
альтернативно, синхронный список или подоболочка могут быть перенаправлены, если вы хотите разделить вывод (как показано в соответствующем посте):
{ time sleep 1 2> sleep.stderr ; } 2> time.txt
Другие команды, такие как strace
или же dialog
предоставить средства для перенаправления stderr. strace
имеет -o <filename.txt>
опция, которая позволяет указать имя файла, в который должен быть записан вывод. Существует также возможность записи текстового файла для каждого подпроцесса, который strace
видит. dialog
Команда записывает текстовый интерфейс пользователя в stdout, но выводит в stderr, поэтому для сохранения его вывода в переменную (потому что var=$(...)
и конвейеры получают только stderr) нам нужно поменять местами дескрипторы файлов
result=$(dialog --inputbox test 0 0 2>&1 1>/dev/tty);
но кроме того, есть --output-fd
флаг, который мы также можем использовать. Есть также метод именованных каналов. Я рекомендую прочитать связанный пост о dialog
Команда для подробного описания того, что происходит.