ディスクに空きがあるのに書き込めない

ディスクの空き容量は十分あるのにファイルを作成できないことがある。

$ df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda1        50G   20G   30G  40% /
$ touch /var/log/app/new.log
touch: cannot touch '/var/log/app/new.log': No space left on device

df -hでは空き容量があるように見えるが、inode(アイノード)が枯渇している場合に同じエラーが出る。

inodeとは

inodeはファイルシステムがファイルやディレクトリの属性(所有者、パーミッション、タイムスタンプなど)を管理するデータ構造。 ファイルシステム作成時にinode数の上限が決まり、ファイル数がその上限に達するとディスクに空きがあっても新しいファイルを作成できない。

df -i でinode使用状況を確認する

df -iでinode使用状況を確認できる。

$ df -i
Filesystem       Inodes  IUsed    IFree IUse% Mounted on
/dev/sda1       3276800 3276800       0  100% /
tmpfs            756644      16  756628    1% /dev

IUse%が100%になっているファイルシステムがinode枯渇している。

-hオプションと組み合わせると数値が読みやすくなる。

$ df -ih
Filesystem     Inodes IUsed IFree IUse% Mounted on
/dev/sda1         13M  541K   12M    5% /
tmpfs            739K    16  739K    1% /dev

inodeを消費しているディレクトリを特定する

どのディレクトリが多くのinodeを消費しているかはfindコマンドで調べる。

$ find / -xdev -printf "%h\n" 2>/dev/null | sort | uniq -c | sort -rn | head -10
   4201 /var/spool/postfix/maildrop
    420 /var/lib/dpkg/info
    312 /tmp/php-sessions
     89 /var/log/app
     13 /var/lib/dpkg

各オプションの意味は以下の通り。

  • -xdev: 調査対象のファイルシステムのみを対象にする(マウントポイントを跨がない)
  • -printf "%h\n": ファイルが存在するディレクトリ名を出力する

出力をパイプでsort | uniq -c | sort -rnに渡すと、ファイル数の多い順にディレクトリが並ぶ。

上記の例では/var/spool/postfix/maildropに4000件以上のファイルがあり、inode枯渇の原因と特定できる。