cp /dev/null logfile を使う理由

なぜ書き込み中のログファイルの内容をクリアするためには

mv logfile logfile~; touch logfile;

とせずに

cp /dev/null logfile

とするのかしっくりきていなかったのですが、要はmvを使うとinodeが変更されないのでlogfile~に書き続けられてしまうというのが問題だったのですね。

実際テストしてみましょう。

まずはlogfileを作ります。

# touch logfile
# ls -lai
640587 drwxr-xr-x  2 root root 4096 2008-07-30 06:46 .
639361 drwxr-x--- 11 root root 4096 2008-07-30 06:46 ..
640586 -rw-r--r--  1 root root    0 2008-07-30 06:46 logfile

次にlogfileをmvして新しくlogfileを作成します。

# mv logfile logfile~
# touch logfile
# ls -lai
640587 drwxr-xr-x  2 root root 4096 2008-07-30 06:52 .
639361 drwxr-x--- 11 root root 4096 2008-07-30 06:46 ..
640588 -rw-r--r--  1 root root    0 2008-07-30 06:52 logfile
640586 -rw-r--r--  1 root root    0 2008-07-30 06:46 logfile~

logfile~のinodeは640586とmv前のlogfileのinodeと変わりありませんが、新しく作成したlogfileはinodeが640588となっています。

ここで試しにlogfileをrmして再度logfileを作成すると、

# rm logfile
# touch logfile
# ls -lai
640587 drwxr-xr-x  2 root root 4096 2008-07-30 06:57 .
639361 drwxr-x--- 11 root root 4096 2008-07-30 06:46 ..
640588 -rw-r--r--  1 root root    0 2008-07-30 06:57 logfile
640586 -rw-r--r--  1 root root    0 2008-07-30 06:46 logfile~

あれれ?inodeが変わらないぞ。。同じ名前だから少し混同してしまいますが、これは利用しているinodeを一つ解放して再度利用したため、たまたま一緒のinodeになっただけ。なので途中でもう一つファイルを作成すると以下のようになる。

# rm logfile
# touch logfile~~
# touch logfile
# ls -lai
640587 drwxr-xr-x  2 root root 4096 2008-07-30 07:01 .
639361 drwxr-x--- 11 root root 4096 2008-07-30 06:46 ..
640589 -rw-r--r--  1 root root    0 2008-07-30 07:01 logfile
640586 -rw-r--r--  1 root root    0 2008-07-30 06:46 logfile~
640588 -rw-r--r--  1 root root    0 2008-07-30 07:01 logfile~~

logfileの中になにも入っていないので一度書き込みをする。

# cat /etc/hosts > logfile
# ls -lai
640587 drwxr-xr-x  2 root root 4096 2008-07-30 07:01 .
639361 drwxr-x--- 11 root root 4096 2008-07-30 06:46 ..
640589 -rw-r--r--  1 root root  258 2008-07-30 07:17 logfile
640586 -rw-r--r--  1 root root    0 2008-07-30 06:46 logfile~
640588 -rw-r--r--  1 root root    0 2008-07-30 07:01 logfile~~

ファイルサイズが258バイトに増えました。ここで/dev/nullを利用してファイルの中身を空にします。

# cp /dev/null logfile
# ls -lai
640587 drwxr-xr-x  2 root root 4096 2008-07-30 07:01 .
639361 drwxr-x--- 11 root root 4096 2008-07-30 06:46 ..
640589 -rw-r--r--  1 root root    0 2008-07-30 07:20 logfile
640586 -rw-r--r--  1 root root    0 2008-07-30 06:46 logfile~
640588 -rw-r--r--  1 root root    0 2008-07-30 07:01 logfile~~

logfileのinodeは変わらず640589のままでlogfileのファイルサイズは0になりました。

最後に/dev/nullではなくて普通のファイルを上書きコピーするとどうなるかというと

# ls -lai /etc/hosts
799212 -rw-r--r-- 2 root root 258 2008-07-30 05:53 /etc/hosts
# cp /etc/hosts logfile
# cp /etc/hosts logfile~~~
# ls -lai
640587 drwxr-xr-x  2 root root 4096 2008-07-30 07:23 .
639361 drwxr-x--- 11 root root 4096 2008-07-30 06:46 ..
640589 -rw-r--r--  1 root root  258 2008-07-30 07:22 logfile
640586 -rw-r--r--  1 root root    0 2008-07-30 06:46 logfile~
640588 -rw-r--r--  1 root root    0 2008-07-30 07:01 logfile~~
640590 -rw-r--r--  1 root root  258 2008-07-30 07:23 logfile~~~

上書きしたlogfileのinodeは変わらず、新規に作成されたコピーは新しいinodeが振られています。

要は、出力先の/dev/nullは少し特殊な意味を持っているかと思いますが、この場合(cp /dev/null logfile)は空のファイルをコピーしているのと同じですね。