Linux перенаправление ошибок в dev null

Обновлено: 08.07.2024

Я пытаюсь понять использование "/ dev / null 2> & 1" здесь. Сначала я подумал, что этот скрипт использует / dev / null для того, чтобы изящно игнорировать ошибки, не вызывая сбой скрипта (вроде как попытка перехватить обработку исключений в языках программирования). Потому что я не понимаю, как использование tar для сжатия каталога в файл tar может привести к любому типу ошибок.

Перенаправление на /dev/null не предотвратит сбой, но очистит выходные потоки stdout и stderr. tar может вызвать ошибки различными способами. Возможно, у вас нет Просто трюк, чтобы избежать ненужного вывода. Что касается того, почему tar может вызывать ошибки: потому что целевой каталог не существует, потому что источник не существует, потому что у вас нет доступа на запись к цели или чтение на источник, потому что tar нет в вашем $ PATH, потому что tar сбой (вы никогда не знаете), потому что на устройстве не осталось места, потому что tar версия изменилась и теперь требует другого синтаксиса, потому что диск вызвал ошибку ввода-вывода. Я уверен, что вы могли бы найти больше.

Нет, это не предотвратит сбой скрипта. Если в tar процессе происходят какие-либо ошибки (например, отказано в разрешении, нет такого файла или каталога, . ), скрипт все равно будет аварийно завершать работу.

Потому что использование > /dev/null 2>&1 перенаправит все выходные данные вашей команды (как stdout и stderr ) /dev/null , что означает, что выходные данные не выводятся на терминал.

В сценарии вы используете > /dev/null вызывающий:

А потом 2>&1 вызывает:

Насколько понятно > /dev/null 2>&1 , эта команда приводит к тому stderr ==> stdout , что stderr все еще печатается в stdout ?? Почему: CMD > /dev/null 2>&1 работает, но CMD 2>&1 > /dev/null все еще дает мне STDERR? Рекомендуется: используйте 2>& 1 в примерах кода, чтобы подчеркнуть, что число и амперсанд считаются частью оператора перенаправления. Обычно для перенаправления в файл между пробелами > и пробелом /path/to/file , перенаправление в файловый дескриптор, по сути, одно и то же.

Я пытаюсь понять использование "> / dev / null 2> & 1" здесь.

(обратите внимание, что я добавил перенаправление раньше /dev/null в вашем вопросе.)

. не вызывая сбой скрипта (например, попытаться поймать обработку исключений в языках программирования).

Это не совсем похоже на try/catch что-нибудь. Он просто отключает любой вывод (включая ошибку) команды.

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

Это может привести к ошибкам по ряду причин, в том числе:

  • Недостаточные права доступа к файлу (файлам), который вы пытаетесь архивировать, или к файлу, в который вы пытаетесь записать
  • Недостаток места на диске для создания архива

Когда вы запускаете CMD> / dev / null 2> & 1

STDOUT перенаправляет на / dev / null, а затем STDERR перенаправляет на АДРЕС STDOUT, который был установлен в / dev / null, следовательно, и STDOUT, и STDERR указывают на / dev / null

И наоборот, когда вы запускаете CMD 2> & 1> / dev / null

STDERR перенаправляет на АДРЕС STDOUT (дескриптор файла 1 в тот момент или / proc / self / fd / 1), а затем STDOUT перенаправляет на / dev / null, но STDERR продолжает перенаправлять на fd1 !! В результате обычный вывод из STDOUT отбрасывается, но ошибки, поступающие из STDERR, все еще записываются на консоль.

Bash I / O Redirection

Основная идея прояснить это так:

Перенаправления применяются справа налево, в отличие от того, как обычно говорят на английском языке.

перенаправляет stderr на stdout first ( 2>&1 ), а затем отправляет stdout (включая перенаправленные stderr ) на filename ( > filename ). Вот объяснение ABSG (гл. 20) .

перенаправляет stderr и stdout в /dev/null . что означает в никуда . Отправленные вещи /dev/null не сохраняются, не кэшируются и не запоминаются каким-либо образом.

Их просто отправляют в « никуда » и забывают. Это способ запуска программ и проверки того, что они НЕ выдают никаких результатов и никогда не будут отображаться в командной строке или в файле журнала.

Я вижу этот тип вопросов довольно часто . в основном потому, что мне самому пришлось его искать, так как я не программировал годами. Вот некоторая полезная информация из ABSG:

«Перенаправление просто означает захват вывода из файла, команды, программы или сценария и отправку его в качестве ввода в другой файл, команду, программу или сценарий».

Другие ценные ресурсы: в текущем / поддерживаемом разделе есть много ценных ресурсов (в нескольких удобных форматах, таких как html, pdf, text и т. Д.) На странице руководств по проектам документации для Linux . Вот некоторые из них, которые я нашел полезными:

Рассмотрим операторы перенаправления вывода Bash и похожие по функции операторы и конструкции. Я собрал следующий список, если что-то пропустил, то пишите в комментариях:

  • |
  • >
  • > /dev/null
  • >>
  • 2>
  • 2>&1
  • &>
  • &>>
  • <
  • <<
  • <<<
  • Почему << (here document) и <<< (here string) нельзя использовать с переменными
  • В чём различие << (here document) и <<< (here string)
  • <(КОМАНДА)
  • >(КОМАНДА)
  • < <(КОМАНДА АРГУМЕНТЫ)
  • 2> >(КОМАНДА) > /dev/null
  • cat > ФАЙЛ <<_EOF_
  • cat >> ФАЙЛ <<_EOF_
  • cat <<_EOF_ > ФАЙЛ
  • cat <<_EOF_ >> ФАЙЛ

Этот оператор на английском называется pipe, и на русском его называют труба или конвейер. Используется очень часто для перенаправления вывода из одной команды в другую, которая может принимать стандартный вывод. Например:

Символ > используется для перенаправления вывода в файл, например:

В этом примере вывод команды ls -l будет записан в файл dir.txt.

То есть оператор | используется когда вывод передаётся в другую команду, а оператор > используется когда вывод записывается в файл.

Ещё один пример использования сразу обоих операторов:

Результат работы этой последовательности команд будет сохранён в файл num.txt.

Если файл не существует, то он будет создан. Если файл существует, то оператор > полностью удалит его содержимое и запишет новым.

> /dev/null

Это частный случай перенаправления, когда всё из стандартного вывода перенаправляется в псевдоустройство /dev/null. Это означает уничтожение данные. То есть ничего не будет выводиться в стандартный вывод.

Функция оператора >> похожа на > с тем отличием, что оператор >> не удаляет содержимое файла, а дописывает новые данные к уже существующим.

Если файл не существует, то оператор >> создаст его и запишет в него переданные данные.

Оператор 2> перенаправляет стандартный вывод ошибок — standard error (stderr).

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

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

Текст ошибки будет выведен на экран, но файл ls-error.txt окажется пустым.

В данном случае ошибка не будет выведена на экран, а будет сохранена в файл ls-error.txt.

Файловый дескриптор «2» помещается непосредственно перед оператором перенаправления, чтобы выполнить перенаправление стандартной ошибки в файл ls-error.txt.

Конструкция 2>&1 предназначена для перенаправления стандартного вывода и стандартного вывода ошибок в один файл.

Используя этот метод, мы выполняем два перенаправления. Сначала мы перенаправляем стандартный вывод в файл ls-output.txt, а затем перенаправляем дескриптор файла 2 (стандартная вывод ошибок) на дескриптор файла один (стандартный вывод), используя обозначения 2>&1.

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

перенаправляет стандартную ошибку в файл ls-output.txt, но при изменении порядка на

стандартная ошибка направлена на экран.

Последние версии bash предоставляют второй, более упрощённый метод для выполнения комбинированного перенаправления 2>&1:

В этом примере мы используем одинарную запись &> для перенаправления как стандартного вывода, так и стандартной ошибки в файл ls-output.txt.

Вы также можете добавить стандартные выходные данные и стандартные потоки ошибок в один файл, например так:

Итак, &> является аналогом 2>&1, а &>> это то же самое, но с перенаправлением вывода в файл.

Как мы уже рассмотрели выше, символ > является перенаправлением вывода. Что касается символа <, то он перенаправляет ввод. Используется следующим образом:

В этом случае КОМАНДА1 будет выполнена с ФАЙЛ1 в качестве источника ввода вместо клавиатуры, которая является обычным источником стандартного ввода.

Оператор < соответствует использованию | для передачи в программу стандартного ввода. Например, следующие команды являются идентичными:

Ещё один пример, содержимое файла math.txt:

Тогда следующие команды идентичны:


Оператор << называется here document. С его помощью можно ввести строку состоящую из нескольких строк или присвоить переменной многострочное значение.

Если в консоль ввести

и нажать Enter, то переменной a будет присвоено значение «строка» и вновь станет доступно приглашение командной строки, потому что Enter по умолчанию является разделителем, символом новой строки. Из-за этого не получится ввести многострочное значение.

Оператор << (here document) меняет это правило — обозначением для новой строки становится другая последовательность символов. В качестве такого обозначения можно выбрать любой набор символов, единственное условие — этот набор не должен встречаться в водимых данных.

Данная запись означает, что запущена команда cat, после неё идёт оператор << и последовательность символов _EOF_. Эти символы (_EOF_) + Enter означают, что _EOF_ - становится обозначением начала и конца для многострочных данных. То есть Enter больше не будет означать окончание ввода данных, в качестве обозначения окончания ввода данных будет выступать _EOF_. Вместо этих символов можно выбрать что угодно.

Второй ввод _EOF_ + Enter означает конец многострочных данных. После этого будет выполнена команда, то есть будут выведены введённые цифры:


Если вы хотите переменной присвоить многострочное значение, то это можно сделать примерно так:

Выведем значение переменной:


Here document это весьма полезная конструкция, к примеру, с её помощью можно делать шаблоны текста, меню, выводимых данных:


Оператор <<< называется here string. Он передаёт с правой стороны стандартный ввод. Чтобы было понятно, следующие команды эквивалентны:

Почему << (here document) и <<< (here string) нельзя использовать с переменными

Если мы захотим присвоить переменной значение с помощью рассмотренных операторов и попробуем выполнить:

то будет получена ошибка:

Причина в том, что нельзя присвоить значение переменным передав данные в стандартном вводе. Например команда

вызовет точно такую же ошибку.

А операторы << (here document) и <<< (here string) передают данные командам в стандартном вводе.

В чём различие << (here document) и <<< (here string)

Различие между этими операторами в том, что << передаёт многострочные данные, которые обрамляются указанной последовательностью символов, а <<< передаёт только строку.

<(КОМАНДА)

Конструкция <(КОМАНДА) называется «подстановка процессов» (Process Substitution). В качестве КОМАНДА может быть одна или более команд с аргументами. Конструкция

вернёт имя специального файла, прочитав который можно получить вывод КОМАНДЫ.

Применение данного способа записи и чтения в и из команды показано далее.

>(КОМАНДА)

Это ещё одна форма «подстановки процессов» (Process Substitution):

Если используется эта форма, то вместо записи в файл, данные будут переданы на ввод для КОМАНДЫ.

< <(КОМАНДА АРГУМЕНТЫ)

Данная конструкция состоит из двух уже рассмотренных ранее элементов языка Bash:

Как мы только что узнали, <(КОМАНДА АРГУМЕНТЫ) возвращает имя файла из которого нужно считывать результат выполнения КОМАНДЫ. А оператор < передаёт ввод с файла (указанного справа от него) команде на стандартный ввод (указанной слева).

Следующие две команды являются аналогами друг друга:

2> >(КОМАНДА) > /dev/null

Эка комбинация, включающая в себя 3 уже рассмотренных элемента:

  • 2> означает перенаправление стандартного вывода ошибок (stderr)
  • >(КОМАНДА) означает подстановку процессов, в результате стандартный вывод ошибок будет передан для обработки в КОМАНДУ
  • > /dev/null означает перенаправления стандартного вывода в /dev/null, то есть фактическое уничтожение стандартного вывода

Пример практического использования:

cat > ФАЙЛ <<_EOF_

Эта конструкция может показаться очень замысловатой, но она состоит из двух уже рассмотренных элементов:

  • > (перенаправление вывода в файл)
  • << (here document, то есть многострочный ввод)

В результате выполнения этого кода, в ФАЙЛ будут записаны строки

Причём если ФАЙЛ уже существует, то он будет стёрт и заменён указанным содержимым.

То есть это один из способов сохранения в файл многострочного вывода.

cat >> ФАЙЛ <<_EOF_

Эта конструкция похожа на предыдущую, в ней используются

  • >> (перенаправление вывода в файл с дописыванием данных)
  • << (here document, то есть многострочный ввод)

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

В ФАЙЛ будут сохранены строки:

Причём если ФАЙЛ уже существует, то он будет дописан.

cat <<_EOF_ > ФАЙЛ

Данная конструкция получает многострочный ввод по стандартному вводу и сохраняет его в файл. То есть это аналог


С технической точки зрения «/dev/null» является файлом виртуального устройства.

Что касается программ, то они обрабатываются как реальные файлы.

Утилиты могут запрашивать данные из такого рода источников, а операционная система передает им данные.

Но вместо чтения с диска операционная система генерирует эти данные динамически.

Примером такого файла является «/dev/zero».

В этом случае, однако, вы будете записывать в файл устройства

Все, что вы пишете в «/dev/null», отбрасывается, забывается и выбрасывается в пустоту.

Чтобы понять, почему это полезно, вы должны сначала иметь представление о стандартном выводе и стандартной ошибке в операционных системах Linux или * nix.

stdout и stder

Утилита командной строки может генерировать два типа вывода.

Стандартный вывод отправляется на stdout.

Ошибки отправляются в stderr.

По умолчанию stdout и stderr связаны с окном вашего терминала (или консолью).

Это означает, что все, что отправлено на stdout и stderr, обычно отображается на вашем экране.

Но с помощью перенаправления оболочки вы можете изменить это поведение.


Используйте /dev/null, чтобы избавиться от вывода, который вам не нужен

Это легче понять на практическом примере.

Допустим, вы ищете строку в «/sys», чтобы найти файлы, которые относятся к настройкам питания.

Будет много файлов, которые обычный пользователь без прав root не сможет прочитать.

Это приведет к множеству ошибок «Отказано в доступе».


Это затрудняет поиск результатов, которые вы ищете.


Как видите, это гораздо легче читать.

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

На приведенном выше примере показано, что без перенаправления ping отображает свой обычный вывод, когда он может достичь конечного компьютера.

Иногда полезно избавиться от всего вывода.

Есть два способа сделать это.

В этом случае вы должны ссылаться на стандартный вывод как «&1» вместо простого «1.».

Запись «2>1» просто перенаправит стандартный вывод в файл с именем «1».

Здесь важно отметить, что порядок важен.

Если вы измените параметры перенаправления следующим образом:

это не будет работать как задумано.

Это потому, что, как только 2>&1 интерпретируется, stderr отправляется на стандартный вывод и отображается на экране.

Затем stdout подавляется при отправке в «/dev/null».

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

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

Другие примеры, где это может быть полезно для перенаправления в /dev/null

Скажем, вы хотите увидеть, как быстро ваш диск может читать последовательные данные.

С технической точки зрения /dev/null в Linux — это файл виртуального устройства. Программы и утилиты могут взаимодействовать с ним как с настоящим файлом: запрашивать данные, а также отправлять в него любую информацию. Но всё, что вы пишете в /dev/null, отправляется в пустоту и забывается (другими словами, отправляется в чёрную дыру). Чтобы понять, почему это полезно, вы должны сначала иметь базовое представление о стандартном потоке вывода данных (stdout) и стандартном потоке вывода ошибок (stderr).

stdout и stderr

В Linux-системах stdout имеет файловый дескриптор 1 , а stderr — файловый дескриптор 2 . Используя данные дескрипторы, мы можем перенаправлять вывод из stdout и stderr в другие файлы:

1> используется для перенаправления стандартного вывода данных (stdout);

/dev/null как средство избавления от ненужного вывода

Допустим, нам нужно найти файлы в каталоге /sys, которые относятся к настройкам питания:

grep -r power /sys/


grep -r power /sys/ 2>/dev/null


Как вы можете видеть, теперь результат воспринимается гораздо проще.

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


Перенаправление всего вывода в /dev/null

Иногда полезно избавиться от всех выходных данных. Есть два способа сделать это:

grep -r power /sys/ >/dev/null 2>&1

Примечание: В этом случае мы должны ссылаться на стандартный вывод (stdout) при помощи знака амперсанда — &1 , а не просто 1 . Запись 2>1 перенаправит данные из stdout в файл с именем 1 .

Стоит отметить, что здесь очень важен порядок: если вы измените параметры перенаправления следующим образом:

grep -r power /sys/ 2>&1 >/dev/null

grep -r power /sys/ &>/dev/null

Еще примеры использования /dev/null

Допустим, мы хотим посмотреть, как быстро наш диск может считывать последовательные данные. Тест не очень точный, но его вполне достаточно. Для этого мы можем использовать команду dd . С помощью of=/dev/null мы можем указать команде dd , что данные следует отправлять в /dev/null. Параметр if= указывает местоположение файла-источника, из которого будут считываться данные:

dd if=<файл-источник> of=/dev/null status=progress bs=1M iflag=direct


Другой пример. Допустим, у нас появилось желание проверить, как быстро будет скачиваться файл через наше сетевое соединение, но при этом мы не хотим без необходимости записывать данные на наш диск. Для этого достаточно указать /dev/null в качестве имени сохраняемого файла:



Заключение

/dev/null — это файл виртуального устройства, который при записи в него всё отправляет в пустоту, а при чтении из него — считывает ноль. Истинный потенциал /dev/null очень хорошо раскрывается в различных bash-сценариях.

Читайте также: