Файл /dev/null есть в каждой Linux-системе. Он весит ноль байт, но именно туда ежедневно сливаются терабайты ненужного вывода, а если его удалить, то вовсе падут cron, ssh и половина ваших bash-скриптов. Под катом расскажу, откуда взялась эта «чёрная дыра», почему это не обычный файл, а псевдоустройство, и что на нём завязано. 

Битовая корзина и память для записи 

Начну издалека — у /dev/null была физическая предшественница, битовая корзина. На телетайпах IBM выбитые из перфоленты и перфокарт кусочки бумаги падали в специальный контейнер, который причастные шуточно звали «bit bucket». Туда отправлялось то, что больше никому не нужно, и обратно оттуда ничего не возвращалось… Очень символично, а айтишники любят символизм, поэтому термин прижился и перекочевал в программирование. 

Например, в 1972 году инженеры Signetics выпустили шуточный даташит на микросхему 25120 — по нему это была память только для записи, из которой невозможно ничего прочитать. 

Цит.: «Память только для записи Signetics — это полностью интегрированное твердотельное устройство, в котором используются режимы усиления и истощения. Она предназначена для хранения N слов, каждое из которых состоит из 9046 бит (термин N может означать любое число вплоть до бесконечности). Микросхема Signetics WOM, изготовленная по некомплементарной МОП-технологии, содержит устройства с каналами P («P» = пифагорейский), N («N» = наполеоновский) и neu (устройства с каналами neu усиливают или ослабляют сигнал одновременно или хаотично, независимо от полярности затвора, но бывают случаи, когда они вообще ничего не делают)».

Эту небольшую историческую отсылку я сделал, чтобы донести, что история нулевого устройства уже существовала до того, как она появилась в Unix-подобных ОС. Похожие способы отбрасывать ненужный вывод были и в других операционках — в DOS устройство называлось NUL, в OpenVMS использовалось обозначение NL:, в AmigaOS применялся обработчик NIL:, а в JCL на мейнфреймах IBM аналогичную роль выполнял параметр DD DUMMY. 

Появление в Unix

Летом 1969 года Кен Томпсон, оставшись в одиночестве почти на месяц (пишут, что жена с новорождённым сыном уехала к родственникам) написал первую версию операционки Unix на языке ассемблера PDP-7. В ноябре 1973 года, когда вышло четвёртое издание руководства программиста, в директории /dev красовалась научная запись о том, что /dev/null — пустой обычный файл. Запись в него работала, но файл при этом рос на диске, и его приходилось время от времени чистить руками. 

Год спустя, в пятом издании, /dev/null уже позиционировался как специальный символьный девайс с семантикой «запись всегда успешна, ничего нигде не сохраняется, а чтение сразу возвращает конец файла».

После у этой битовой корзины начала разрастаться семья. Позднее рядом с /dev/null появился /dev/zero, который при чтении возвращает поток нулевых байтов. Интересно, что изначально он был нужен для анонимной памяти под разделяемые библиотеки, а не для затирания дисков. Позже появился /dev/full — устройство, которое всегда отвечает «нет места». В Linux за эти устройства отвечает файл drivers/char/mem.c. 

Как устроен /dev/null

Разберу его через ls -l /dev/null:

ls -l /dev/null

crw-rw-rw- 1 root root 1, 3 ... /dev/null

Буква c в начале означает character device — символьное устройство. Это точка входа в драйвер, а числа 1 и 3 говорят ядру, какой именно драйвер и какой обработчик вызвать при обращении. 

Самое важное — при записи в /dev/null данные никуда не попадают (буквально). Функция write_null в drivers/char/mem.c просто возвращает count, сообщая программе, что указанное количество байтов успешно записано, хотя никаких действий с ними не выполняет. Функция read_null же возвращает ноль, который программа воспринимает как конец файла или EOF. 

У файла права 666 — читать и писать может вообще любой пользователь. Это осознанное решение разработчиков, поскольку null должен оставаться доступным всем процессам. 

При записи /dev/null не приходится обращаться к диску, поэтому результат зависит от системных вызовов и подготовки данных. 

Также /dev/null не каталог, поэтому mv file /dev/null не переместит файл в никуда, а просто заменит собой файл устройства. Если после такой команды у вас внезапно (сам по себе, ага) пропал нормальный null — пора учить mknod.

Что происходит, когда /dev/null исчезает

Немного отвлекусь, в сборнике Unix Administration Horror Stories из девяностых есть история о том, как админ удалил /dev/null, и вскоре он был воссоздан как обычный файл. После этого в системе начались СТРАШНЫЕ-ПРЕСТРАШНЫЕ проблемы с правами, а понять причину он не мог (новичок же ж).

Там же есть перл об очистке битовой корзины — сообщение об ошибке, которое просит почистить мусорку, в которую ничего нельзя выбросить (это мой любимый экспонат юниксового юмора, а другие истории можно почитать тут).

Возвращаюсь к теме, весь шелл-мир /dev/null построен на идиоме «отправь вывод в никуда»:

command > /dev/null 2>&1

Сначала stdout уходит в /dev/null, потом stderr перенаправляется туда же. Если перевернуть конструкцию (2>&1 > /dev/null), то ошибки продолжат сыпаться. 

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

  • данные перестанут исчезать,

  • права доступа станут неподходящими для остальных пользователей,

  • чтение больше не будет возвращать конец файла.

На современных ОС, где /dev размещён на devtmpfs или tmpfs, такой файл будет есть оперативную память. Если же /dev находится на обычной файловой системе, то под угрозой окажется свободное место на соответствующем разделе. Страшно? Будет ещё страшнее. 

Будут проблемы и с cron. Любая задача, вывод которой не отправлен в /dev/null, приводит к письму для владельца задачи, а на сервере без почты эти письма копятся в /var/mail или падают с ошибками в логах. Отключить отправку можно через MAILTO="", а подавить вывод конкретной команды позволяет именно перенаправление в /dev/null.

С ним же связаны и демоны. Процессы, отрывающиеся от терминала, традиционно перенаправляют stdin, stdout и stderr в /dev/null. Если устройства нет, то демон не сможет корректно отцепиться. В systemd та же логика спрятана в директивах StandardOutput=null и StandardError=null, и это тот самый /dev/null.

Также куча утилит при запуске открывает /dev/null как замену пустого входа. В скриптах приёмом «</dev/null» глушат интерактивные программы, которые виснут в ожидании ввода — fsck, некоторые инсталляторы, apt с его вопросами. Без работающего /dev/null такие конструкции будут непредсказуемы, и дебажить это удовольствие сомнительное.

И наконец, /dev/null связан с ssh в цикле:

while read host; do

    ssh $host uptime

done < hosts.txt

Он (такой цикл) может пропустить часть хостов, поскольку SSH читает стандартный ввод и забирает данные из того же файла, который обрабатывает read. Обычно проблему решают параметром -n или перенаправлением ввода из /dev/null, но оба варианта зависят от работоспособности файла.

Проверить, что ваш /dev/null настоящий и живой, можно через:

stat -c 'type=%F mode=%a major=%t minor=%T' /dev/null 

В выводе должно быть «type=character special file mode=666 major=1 minor=3». Если там «regular file», у меня для вас плохие новости, и этот раздел вы только что читали не зря.

Восстановить удалённый /dev/null, если что, можно командой:

sudo mknod -m 666 /dev/null c 1 3

mknod создаёт файл устройства, c говорит, что устройство символьное, 1 и 3 — это major и minor. Но, к слову, на живых системах /dev обычно на tmpfs и управляется udev, так что после перезагрузки устройство вернётся и само.

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

sudo rm -f -- /dev/null

sudo mknod -m 666 /dev/null c 1 3

После этого ещё раз запустите mknod и проверьте результат. 

Чем же полезен /dev/null

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

: > /var/log/myapp.log

# или дедовским способом

cat /dev/null > /var/log/myapp.log

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

Ещё /dev/null удобен как «источник пустоты» на входе. Например, GNU tar умеет распознавать вывод архива в /dev/null и ради оптимизации может пропустить чтение содержимого файлов. Если нужно прочитать файлы, архив следует пропустить через конвейер:

tar -cf - /etc | cat > /dev/null

Если нужен код завершения всего конвейера, вводите:

set -o pipefail

tar -cf - /etc | cat > /dev/null

Заодно расскажу про его младшего брата — /dev/full ведёт себя как переполненный диск (любая запись возвращает ENOSPC):

echo test > /dev/full

echo: write error: No space left on device

А /dev/zero пригодится, когда нужен файл заданного размера или чистое затирание:

# Файл размером 1 ГиБ, заполненный нулями

dd if=/dev/zero of=test.bin bs=1M count=1024 

# Записать нули во все доступные логические блоки

sudo dd if=/dev/zero of=/dev/sdX bs=1M status=progress

Со второй командой, как вы понимаете, главное не перепутать sdX. 

Ну и наконец

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

Делитесь в комментариях, для чего вы используете /dev/null чаще всего.

© 2026 ООО «МТ ФИНАНС»

Комментарии (14)


  1. astenix
    27.08.2026 12:05

    В Linux за эти устройства отвечает файл drivers/char/mem.c. 

    Где?

    Искал-проверял — нет его.


    1. dlinyj
      27.08.2026 12:05

      https://github.com/torvalds/linux/blob/73e3f0710014fe6d4ed98cfc02292f6121db7558/drivers/char/mem.c#L415

      static ssize_t write_null(struct file *file, const char __user *buf,
      			  size_t count, loff_t *ppos)
      {
      	return count;
      }


  1. Granulex
    27.08.2026 12:05

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


  1. Chupaka
    27.08.2026 12:05

    ноль документации

    https://man7.org/linux/man-pages/man4/zero.4.html


  1. UncleAndy
    27.08.2026 12:05

    Как-то по молодости лет перепутал параметры в команде ln и сделал /dev/null некорректным симлинком. Пришлось поразбираться почему это на сервере все рухнуло. :))) Хорошо что сервер был в физическом доступе. :)+


    1. randomsimplenumber
      27.08.2026 12:05

      Под root работать - к скорой переустановке.


  1. wiki7979
    27.08.2026 12:05

    Как было бы интересно, если бы концепция "все есть файл" была реализована в популярной системе. Сколько бы всего утекло в сеть без каких-либо серьёзных усилий, м-м-м...


    1. randomsimplenumber
      27.08.2026 12:05

      Поясните, что куда и почему утекло, и при чем тут концепция файла.


      1. wiki7979
        27.08.2026 12:05

        Не буду пояснять, ибо минусуютъ.


        1. randomsimplenumber
          27.08.2026 12:05

          За хорошее годное пояснение плюсуют. А за плохое негодное - могут и табуретку выбить.


  1. beswalod
    27.08.2026 12:05

    А кто-нибудь объяснит, зачем какая-то внешняя команда, которая всегда возвращает 0/1/true/false/EOF/etc, если то же самое можно сделать в коде программы, просто написав "return anything;"?


    1. randomsimplenumber
      27.08.2026 12:05

      Чтобы не писать в коде.


      1. ciuafm
        27.08.2026 12:05

        Спасибо за лаконичный и точный ответ, многим было непонятно ;-)


    1. PashaWNN
      27.08.2026 12:05

      Концепция юникса, в которой всё было задумано так, чтобы сложные скрипты строились из максимально простых программ, работающих со стандартным вводом-выводом. Те самые cat и подобные программки. И вот гораздо проще перенаправить ненужный вывод в null, чем городить в программе отдельный флаг, отвечающий за подавление вывода. Т. е. по умолчанию считаем, что пользователь захочет оперировать файлами и даём ему удобный способ, а для ситуаций, когда вывод не нужен/нужны нули вместо файла/что-то ещё такое — даём универсальный способ, который подойдёт для любой программы, которая умеет работать с файлами.