С технической точки зрения /dev/null в Linux — это файл виртуального устройства. Программы и утилиты могут взаимодействовать с ним как с настоящим файлом: запрашивать данные, а также отправлять в него любую информацию. Но всё, что вы пишете в /dev/null, отправляется в пустоту и забывается (другими словами, отправляется в чёрную дыру). Чтобы понять, почему это полезно, вы должны сначала иметь базовое представление о стандартном потоке вывода данных (stdout) и стандартном потоке вывода ошибок (stderr).
stdout и stderr
Всякий раз, когда запускается какая-либо утилита командной строки, она генерирует два типа вывода: стандартный вывод выполнения команды отправляется в stdout, а сообщения об ошибках (если таковые есть) — в stderr.
По умолчанию stdout и stderr связаны с окном терминала (или консолью). Это означает, что всё, что отправляется в stdout и stderr, обычно отображается на нашем экране. Но с помощью перенаправления вывода мы можем изменить это поведение. Например, мы можем перенаправить вывод stdout в файл. Таким образом, вместо отображения информации о выполнении команды на экране терминала, она будет сохранена в файле, который мы позже сможем прочитать. Или же можно перенаправить stdout на физическое устройство, скажем, на цифровой ЖК-дисплей.
В Linux-системах stdout имеет файловый дескриптор 1
, а stderr — файловый дескриптор 2
. Используя данные дескрипторы, мы можем перенаправлять вывод из stdout и stderr в другие файлы:
1>
используется для перенаправления стандартного вывода данных (stdout);
2>
используется для перенаправления вывода сообщений об ошибках (stderr). Например, 2>/dev/null
отправляет сообщения об ошибках в «чёрную дыру», а 2>/home/user/error.log
— в файл error.log.
&>
используется для перенаправления как стандартного вывода данных (stdout), так и вывода сообщений об ошибках (stderr).
/dev/null как средство избавления от ненужного вывода
Допустим, нам нужно найти файлы в каталоге /sys, которые относятся к настройкам питания:
grep -r power /sys/
В выводе команды будет много файлов, которые обычный пользователь (не root) не сможет прочитать (мы получим сообщение об ошибке «Отказано в доступе»). Эти сообщения загромождают терминал и затрудняют поиск. Поскольку ошибки «Отказано в доступе» являются частью stderr, то мы можем перенаправить их в «чёрную дыру», используя /dev/null:
grep -r power /sys/ 2>/dev/null
Как вы можете видеть, теперь результат воспринимается гораздо проще.
В других случаях может быть полезно сделать обратное: отфильтровать стандартный вывод, чтобы мы могли видеть только ошибки, например:
ping ravesli.com 1>/dev/null
На вышеприведенном скриншоте показано, что без перенаправления команда ping
отображает свой обычный вывод. Во второй команде ничего не отображается, пока сеть подключена, но как только она отключается, выводится (только) сообщение об ошибке.
Мы можем перенаправить как stdout, так и stderr в два разных места:
ping google.com 1>/dev/null 2>error.log
В этом случае стандартный вывод выполнения команды не будет отображаться вовсе, а сообщения об ошибках будут сохранены в файле error.log.
Перенаправление всего вывода в /dev/null
Иногда полезно избавиться от всех выходных данных. Есть два способа сделать это:
grep -r power /sys/ >/dev/null 2>&1
Часть >/dev/null
означает «перенаправить данные из stdout в /dev/null», а часть 2>&1
означает «перенаправить данные из stderr в stdout». Таким образом мы перенаправили весь вывод команды в пустоту.
Примечание: В этом случае мы должны ссылаться на стандартный вывод (stdout) при помощи знака амперсанда — &1
, а не просто 1
. Запись 2>1
перенаправит данные из stdout в файл с именем 1
.
Стоит отметить, что здесь очень важен порядок: если вы измените параметры перенаправления следующим образом:
grep -r power /sys/ 2>&1 >/dev/null
…то это сработает не так, как задумывалось. Часть 2>&1
перенаправит stderr в stdout, отобразит вывод на экране, после чего перенаправит stdout в /dev/null. Конечным результатом станет то, что вместо искомой информации вы увидите сообщения об ошибках. Если вы не можете запомнить правильный порядок составляющих, есть более простое перенаправление:
grep -r power /sys/ &>/dev/null
В этом случае &>/dev/null
эквивалентно выражению «перенаправить как stdout, так и stderr в /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 в качестве имени сохраняемого файла:
wget -O /dev/null https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/debian-11.1.0-amd64-netinst.iso
Заключение
/dev/null — это файл виртуального устройства, который при записи в него всё отправляет в пустоту, а при чтении из него — считывает ноль. Истинный потенциал /dev/null очень хорошо раскрывается в различных bash-сценариях.
На первый взгляд, первый пункт — странный пример применения /dev/null. Напрашивается вопрос: нет возможности попросту НЕ допускать вывод ненужного информационного мусора, чем обязательно сливать его в /dev/null?
Спасибо вам за интересный и полезный цикл статей.
Всегда пожалуйста. 🙂