🗑️

Linux - /dev/null とは

2025/01/28に公開

Summary

/dev/null はUNIXシステムにおける特殊なデバイスファイルの一つであり、その特徴は

  • 入力されたデータをすべて破棄する
  • 読み取り時は常にEOF(End of File)を返す
  • /dev ディレクトリ配下に配置される疑似デバイスの一種

本記事のモチベーション

  • Ubuntuサーバーの構築
  • UbuntuなどのUNIX系OSをベースイメージとしたDocker解析環境の構築

これらを業務で行うとき、CUDAドライバー・CUDA・Docker Engineなど、様々なツールをパッケージマネージャを用いてインストールします。その際に > /dev/null の表記をよく見かけます。

本記事はよく見かけるがその役割を知らない/dev/nullの実態について解説します。

/dev/nullの実態

以下はIT用語辞典 /dev/nullからの引用です。

デバイスファイル(device file)はコンピュータに接続された各装置への入出力手段をファイルシステム上で提供する特殊なファイルで、「/dev/」ディレクトリ配下に置かれている。このうち、対応する物理的な装置が存在しないものを「疑似デバイス」(pseudo-device)という。

/dev/nullは疑似デバイスの一種で、受け取った入力を何もせず単に破棄する。何らかの出力先の指定が必要だが何の処理もしたくない場合や、標準では画面に表示されるメッセージなどを抑止したい場合、空の入力元が必要な場合などに利用される。

/dev/nullの実態は

  1. /dev/ディレクトリ配下に置かれ、コンピュータに接続された装置への入出力をファイルシステム上で提供するデバイスファイルである
  2. デバイスファイルの中でも入出力先となる物理的な装置が存在しない「疑似デバイス」の一種である
  3. 書き込まれたデータは破棄し、読み出しに対してはEOFを返す

であることがわかりました。

また、疑似デバイスファイルには/dev/nullの他にも/dev/zero/dev/randomがあります。

  • /dev/zero : すべてnull文字の読み出し(ファイルの0埋め等に利用)
  • /dev/random : 乱数生成

/dev/nullの使用例

例1:標準出力の破棄

Ubuntu | Docker Docsより一部引用

以下は、UbuntuにDockerをinstallする際に利用するコマンドの一部です。
/dev/nullを調査するきっかけになったコマンドです。

# Add the repository to Apt sources:
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update

デフォルトのUbuntuのパッケージマネージャであるAptリポジトリにDocker公式のリポジトリを登録するコマンドです。

ここではteeコマンドの出力を/dev/nullにリダイレクトし、破棄しています。teeコマンドからの出力をあえて破棄することで、ログ出力の視認性を向上させています。

例2:読み取りによる空ファイルの作成

読み出しのプロセスに対してEOFを返すことでサイズが0バイトのファイルを作成することもできます。

$ cat /dev/null > empty.txt # /dev/nullの読み取り結果をempty.txtにリダイレクト
$ du empty.txt # ファイルサイズ確認
0	empty.txt # 0Bのファイル

Appendix:「データの破棄」方法

最後に「/dev/nullに入力されたデータはどのような実装で破棄されているのか?」という疑問が湧きましたので、調査してみました。

StackOverFlowに同じ疑問を持った方がいました。

How is /dev/null implememted?

回答中では/dev/nullが実際に利用しているwrite_null関数を引用し、その内容について解説されていました。

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

関数の内容を見るとsize_t型の引数countのみが返り値となっており、それ以外の引数はすべて無視されています。したがって、データの破棄はwrite_null関数は書き込みサイズ(count)をそのまま返し、書き込み操作が成功したことのみを示します。また、メモリにデータを保持しないことでデータ破棄を実現していることがわかりました。


最後まで読んでくださりありがとうございました。
誤字・間違いなどがありましたらご遠慮なくご指摘ください。

Discussion