Новички в программировании на Bash рано или поздно столкнутся с /dev/null
и другим непонятным жаргоном: > /dev/null 2>&1
. Это может показаться запутанным, но это довольно просто для понимания и является фундаментальной частью программирования оболочки. Итак, давайте разберемся с пошаговыми примерами.
Начнем с того, что /dev/null
- это специальный файл, который в системах Unix называется нулевым устройством. В просторечии его также называют битовым ведром или черной дырой, потому что он немедленно отбрасывает все, что в него записано, и возвращает только конец файла EOF
при чтении.
Давайте посмотрим, что произойдет, когда мы попытаемся написать в него с помощью оператора перенаправления файлов (>
).
# First let's try writing to this file. $ echo 'text' > /dev/null # Upon inspection, we see that the write was successfully. $ echo $? 0
Символ $?
- это специальная переменная, которая всегда содержит статус выхода предыдущей команды; он будет перезаписываться каждый раз, когда вы запускаете новую команду. По соглашению, код выхода 0
указывает, что предыдущая команда была успешной, в то время как большее значение указывает код ошибки для этой конкретной программы.
Например, если мы найдем ls
на страницах руководства, мы увидим, что код выхода 1
соответствует незначительной проблеме.
Давайте посмотрим на другой пример. Для следующих двух команд: первая (ls
) - допустимая команда, а вторая (ls -0
) - недопустимая команда, потому что она содержит недопустимый параметр -0
.
Это допустимая команда:
$ ls Applications Documents Library Music Public $ echo $? 0
Теперь посмотрим на недопустимую команду:
$ ls -0 ls: illegal option -- 0 usage: ls [-ABCFGHLOPRSTUWabcdefghiklmnopqrstuwx1] [file ...] $ echo $? 1
Проблема со вторым сценарием заключается в том, что он отображает все сообщения об ошибках в STDERR
. Однако для наших скриптов мы хотим подавить сообщения об ошибках. К счастью, есть способ делать именно то, что мы хотим.
Попробуем еще раз с > /dev/null 2>&1
:
$ ls -0 > /dev/null 2>&1 $ echo $? 1
Обратите внимание, что на этот раз мы не увидели сообщений об ошибках. Чтобы сломать это, мы подавляем вывод ошибки (stderr
) команды ls -0
, перенаправляем его на стандартный вывод (stdout
), записывая его в /dev/null
, тем самым немедленно отбрасывая его. Символ >&
- это оператор, который копирует вывод первого файлового дескриптора (2) и перенаправляет на вывод второго файлового дескриптора (1).
Теперь давайте посмотрим, что представляют собой числа в 2>&1
, посмотрев на эту диаграмму файловых дескрипторов.
Мы можем проверить это, выполнив вывод в обычный файл вместо /dev/null
.
$ ls -0 > /tmp/devnull 2>&1 $ echo $? 1 $ cat /tmp/devnull ls: illegal option -- 0 usage: ls [-ABCFGHLOPRSTUWabcdefghiklmnopqrstuwx1] [file ...]
Этот метод обычно используется, чтобы определить, существует ли команда, которую вы можете использовать для работы с различными операционными системами, автоматической установки пакетов, загрузки файлов и, что наиболее важно, для защиты ваших скриптов и систем от неожиданных исключений.
function cmd_exists() { command -v $1 > /dev/null 2>&1 } # cmd_exists ls; echo $? # cmd_exists sl; echo $?
Надеюсь, /dev/null
вместе с перенаправлением вывода, статусами выхода и файловыми дескрипторами должны иметь смысл, поскольку они являются фундаментальными для программирования на Bash. Есть много других операторов ввода-вывода, каждый из которых имеет свои конкретные цели, которые вы можете просмотреть здесь: