Что такое /dev/null и как его использовать в Bash
Linux - это интересная операционная система, в которой размещены некоторые виртуальные устройства для различных целей. Для программ, работающих в системе, эти виртуальные устройства действуют так, как будто это реальные файлы. Инструменты могут запрашивать и получать данные из этих источников. Данные генерируются ОС вместо того, чтобы считывать их с диска.
Одним из таких примеров является /dev/null. Это специальный файл, который присутствует в каждой системе Linux. Однако, в отличие от большинства других виртуальных файлов, вместо чтения он используется для записи. Все, что вы запишете в /dev/null, будет отброшено, забыто в пустоте. В системе UNIX он известен как нулевое устройство.
Зачем вам выбрасывать что-то в пустоту? Давайте посмотрим, что такое /dev/null и как он используется.
Предварительно
Прежде чем углубиться в использование /dev/null, мы должны иметь четкое представление о потоке данных stdout и stderr. Ознакомьтесь с этим коротким руководством по stdin, stderr и stdout.
Давайте сделаем небольшое уточнение. При запуске любой утилиты командной строки она генерирует два вывода. Вывод идет на stdout, а ошибка (если она возникла) - на stderr. По умолчанию оба этих потока данных связаны с терминалом.
Например, следующая команда выведет строку, заключенную в двойные кавычки. Здесь вывод сохраняется в stdout.
$ echo "Hello World"
Следующая команда покажет нам статус выхода ранее запущенной команды.
$ echo $?
Поскольку предыдущая команда была выполнена успешно, статус выхода равен 0. В противном случае статус выхода будет другим. Что произойдет, если вы попытаетесь выполнить недопустимую команду?
$ adfadsf $ echo $?
Теперь нам нужно разобраться в файловом дескрипторе. В экосистеме UNIX это целочисленные значения, присвоенные файлу. И stdout, и stderr имеют определенный дескриптор файла: stdout = 1, stderr = 2. Используя дескриптор файла (1 и 2), мы можем перенаправить stdout и stderr в другие файлы.
Cледующий пример перенаправит stdout команды echo в текстовый файл. Здесь мы не указали дескриптор файла. Если он не указан, bash будет использовать stdout по умолчанию.
$ echo "Hello World" > log.txt
Следующая команда перенаправит stderr в текстовый файл.
$ asdfadsa 2> error.txt
Использование /dev/null
Перенаправление вывода в /dev/null
Теперь мы готовы узнать, как использовать /dev/null. Сначала давайте проверим, как фильтровать обычный вывод и ошибки. В следующей команде grep попытается найти строку (hello, в данном случае) в каталоге "/sys".
$ grep -r hello /sys/
Однако это вызовет множество ошибок, поскольку без привилегий root grep не может получить доступ к ряду файлов. В этом случае он выдаст ошибку "Permission denied". Теперь, используя перенаправление, мы можем получить более четкий результат.
$ grep -r hello /sys/ 2> /dev/null
Вывод выглядит намного лучше, верно? Ничего! В этом случае у grep нет доступа ко многим файлам, а в тех, что есть, нет строки "hello".
В следующем примере мы будем пинговать Google.
$ ping google.com
Однако мы не хотим видеть все эти успешные результаты пинга. Вместо этого мы хотим сосредоточиться только на ошибках, когда ping не смог достичь Google. Как нам это сделать?
$ ping google.com 1> /dev/null
Здесь содержимое stdout сбрасывается в /dev/null, оставляя только ошибки.
Перенаправить весь вывод в /dev/null
В некоторых ситуациях вывод может оказаться бесполезным. Используя перенаправление, мы можем сбросить весь вывод в пустоту.
$ grep -r hello /sys/ > /dev/null 2>&1
Давайте немного разобьем эту команду. Сначала мы сбрасываем весь stdout в /dev/null. Затем, во второй части, мы говорим bash отправить stderr в stdout. В этом примере выводить нечего. Однако, если вы запутались, вы всегда можете проверить, успешно ли выполнилась команда.
$ echo $?
Значение равно 2, потому что команда выдала много ошибок.
Если вы склонны забывать файловый дескриптор stdout и stderr, следующая команда подойдет как нельзя лучше. Это более обобщенный формат предыдущей команды. И stdout, и stderr будут перенаправлены в /dev/null.
$ grep -r hello /sys/ &> /dev/null
Другие примеры
Это интересный пример. Знаете инструмент dd? Это мощный инструмент для преобразования и копирования файлов. Узнайте больше о dd. Используя dd, мы можем проверить скорость последовательного чтения вашего диска. Конечно, это не точное измерение. Однако для быстрого теста это довольно полезно.
$ dd if=<big_file> of=/dev/null status=progress bs=1M iflag=direct
user@comp:~/Downloads$ dd if=ubuntu-18.04.4-desktop-amd64.iso of=/dev/null status=progress bs=1M iflag=direct 2091909120 bytes (2.1 GB, 1.9 GiB) copied, 14 s, 149 MB/s 2028+1 records in 2028+1 records out 2126544896 bytes (2.1 GB, 2.0 GiB) copied, 14.263 s, 149 MB/s user@comp:~/Downloads$
Здесь я использовал "ubuntu-18.04.4-desktop-amd64.iso" в качестве большого файла.
Аналогичным образом вы также можете проверить скорость загрузки вашего интернет-соединения.
$ wget -O /dev/null <big_file_link> $ wget -O /dev/null https://speedtest.selectel.ru/10GB
--
Надеемся, у вас есть четкое понимание того, что такое файл /dev/null. Это специальное устройство, которое при записи в него отбрасывает, а при чтении из него считывает null. Истинный потенциал этой интересной возможности заключается в интересных bash-скриптах.
Вас интересуют сценарии на bash? Ознакомьтесь с руководством для начинающих по написанию сценариев на bash.
--