13

Как подавить вывод команды, но показать ее, если команда выхода кодирует ошибку?

3 ответа3

17

К сожалению, предположение, что stderr используется только для вывода ошибок, не всегда верно. Скорее, stderr часто используется для любого и всех интерактивных выводов и диагностики, т.е. выводов, предназначенных для чтения пользователем в интерактивном приглашении 1. wget и dd - известные примеры.

Некоторые команды предоставляют флаг (например, -quiet или -silent) для подавления вывода без ошибок - прочитайте их справочные страницы, чтобы увидеть, существует ли он.


Другое соглашение, которое выполняется чаще, - это код выхода: программа возвращает код выхода при выходе. Как правило, 2, код выхода 0 указывает на успех, а любой другой код выхода указывает на ошибку.

С помощью bash вы можете получить код выхода последней команды из $? переменная. В fish используйте переменную $status . Вы можете передать stderr во временный файл и распечатать его только в случае возникновения ошибки. Например (fish):

command 2>/tmp/outputbuffer
if $status
    cat /tmp/outputbuffer
rm /tmp/outputbuffer

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

if command 2>/tmp/outputbuffer
    cat /tmp/outputbuffer
rm /tmp/outputbuffer

Или же:

command 2>/tmp/outputbuffer; or cat /tmp/outputbuffer; rm /tmp/outputbuffer;

Вы также можете направить стандартный stdout в тот же буфер, используя 2>&1 >/tmp/outputbuffer .

(Примечание: я на самом деле не знаю fish , поэтому я адаптирую концепцию к тому, что я могу найти в ее документации. Синтаксис может быть немного неправильным. Также вы можете использовать mktemp для генерации уникального временного файла - запустите его и запишите имя файла в переменной.)

Если вам нужно запустить все это одновременно в фоновом режиме оболочки, которую вы также используете в интерактивном режиме, то вам лучше написать сценарий для обработки сокрытия вывода и запустить этот сценарий в фоновом режиме с помощью стандартных приемов. (fish). Черт возьми, вы можете поместить что-то вроде следующей функции в ~/.config/fish/config.fish:

function run-silent
    set temp (mktemp)
    if $argv 2>&1 >$temp
        cat $temp
    rm $temp
end

Вызов с run-silent somecommand & (где трейлинг & заставляет его работать в фоновом режиме)

Обратите внимание, что это поглотит исходный код завершения и сбросит как stdout и stderr в случае сбоя. Вы можете настроить его по мере необходимости.


1 Нет даже гарантии, что вывод ошибок не появится на stdout - некоторые программы будут выводить весь вывод там!

2 К сожалению, это не всегда так - код выхода полностью контролируется программой, а некоторые укажут некоторые условия успеха с ненулевыми выходами. Снова, проверьте руководство.

12

Утилиты Unix отправляют общие сообщения в stdout , а сообщения об ошибках - в stderr , поэтому, если мы хотим видеть только сообщения об ошибках, достаточно будет подавить stdout чтобы только stderr получал вывод на консоль.

Способ сделать это (как в bash и в fish) - добавить >/dev/null к команде. Это выводит stdout в небытие, но stderr (с вашими сообщениями об ошибках) все еще проходит через консоль.

Так, например:

Команда echo 1 >/dev/null ничего не печатает, потому что нормальный вывод stdout подавлен и ничего не записано в stderr.

Команда man doesnotexist >/dev/null печатает сообщение об ошибке, потому что man записывает свое сообщение об ошибке в stderr .

2

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

    command > /dev/null 2> /tmp/example_error.log &

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .