Первое, что следует отметить, это то, что есть несколько способов в зависимости от вашей цели и оболочки, поэтому для этого требуется небольшое понимание множества аспектов. Кроме того, некоторые команды, такие как time
и strace
записывайте выходные данные в stderr по умолчанию и может предоставлять или не предоставлять метод перенаправления, специфичный для этой команды
Основная теория, лежащая в основе перенаправления, заключается в том, что процесс, порожденный оболочкой (при условии, что это внешняя команда, а не встроенная оболочка), создается с помощью fork()
и execve()
системные вызовы, и до этого произойдет еще один системный вызов dup2()
выполняет необходимые перенаправления, прежде чем execve()
происходит. В этом смысле перенаправления наследуются от родительской оболочки. То m&>n
и m>n.txt
проинформируйте оболочку о том, как выполнить open()
и dup2()
системный вызов (см. также Как работает перенаправление ввода, В чем разница между перенаправлением и каналом, и Что именно означает & в перенаправлении вывода )
Перенаправления оболочки
Наиболее типичным является то, что через 2>
в Похожие на Борна раковины, такие как 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/shexec 2> ./my_log_file.txtstat /etc/non_existing_file
В этом примере файл журнала должен отображать stat: cannot stat '/etc/non_existing_file': No such file or directory
.
Еще один способ - с помощью функций. Как золушка как отмечено в его ответе, мы можем написать объявление функции с уже прикрепленным перенаправлением, то есть
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
команда для подробного описания происходящего.