tmpwatchがctimeを常に書き換えてしまい、tmpwatchが機能しない問題

2016/04/16

/tmp以下のファイルが10日たっても削除されず、tmpwatchが機能していないようだった。
/tmp以下のmtime, atime, ctimeを ls -l, ls -ul, ls -cl でそれぞれ見ていくと、ctimeがtmpwatchがcronで動いた時間になっていた。

tmpwatchがctimeを常に書き換えてしまい、tmpwatchが機能しない問題は、Red Hat Bugzillaに原因が書いてあった。
https://bugzilla.redhat.com/show_bug.cgi?id=51325

Preston Brown

2001-08-13 15:40:52 EDT

The mtime for a file or directory is updated by the filesystem each time the
file is modified. Prior to modifying a file, an application can save the
file's mtime, and then reset it after the modification using the utime(2)
system call.

The atime for a file or directory is updated by the filesystem each time the
file is accessed (read or write). Prior to accessing a file, an application
can save the file's atime, and then reset it after the file access using the
utime(2) system call.

The ctime for a file or directory is updated each time the file or directory's
inode is changed; examples of this are changing permissions, ownership,
link-counts, etc. The ctime for a file or directory can NOT be saved before
and reset after a change. Another significant fact is that the ctime of a file
or directory is CHANGED when resetting the mtime and atime (using the utime(2)
system call) for the file.

When tmpwatch reads the data for a file to determine whether or not it should
be removed, it does not affect the file modification time, but does affect the
file's access time. For this reason, NetBackup saves the file's atime and
mtime prior to reading the file, and resets the atime and mtime
using the utime(2) system call. By "covering it's tracks", tmpwatch does not
cause grief for HSM products or administrator scripts that are utilizing file
access times (atime) as criteria for their operations. While this benefit is
obvious, a side effect is that it does update the file's ctime.

There is no way around this while maintaining compatibility with UNIX
standards.

要は、tmpwatchがatimeを元に戻す時にutime(2) system callを使用するが、そのせいでctimeが変わってしまうらしい。
tmpwatchがファイルを確認し、また確認の結果削除するときに、ディレクトリに読み書きするとmtimeとatimeが変わってしまうので、それを元に戻している。

対策を考える前に、念のためtmpwatchの仕組みを確認する。

tmpwatchの仕組み

tmpwatch [option] [hours] [dirs]

削除ルール

・シンボリックリンクはたどらない
・ファイルシステムを超えて処理しない
・root がオーナの lost+found は処理しない
・空のディレクトリ、通常のファイル、シンボリックリンクのみ削除

オプション

/etc/cron.daily/tmpwatch

cronで毎日tmpwatchが起動するようになっている。

tmpwatchのcron解説
「flags=-umc」と記載があり、tmpwatch に -umc オプションが付加される。
-u, -m, -c が同時に指定されると、最大値(最新時刻)が判定条件になる。

-x オプションで「/tmp/.X11-unix」等が、-X オプションでワイルドカード指定により「/tmp/hsperfdata_」から始まるパスが、tmpwatchの処理対象外になっている。

/tmpは10日経っていると(10d)削除される。
/var/tmpは30日経っていると(30d)削除される。
ちなみに、/tmpと/var/tmpの違いは、/tmpが「再起動するとファイルが消える」領域であるのに対して、/var/tmpは「再起動してもファイルが消えない」領域である、という点にある。

/var/{cache/man,catman}/{cat?,X11R6/cat?,local/cat?}は、それぞれディレクトリであれば([ -d "$d" ])、30日経っていると、w 権限がrootについていなくても強制的に(-f)削除される。

tmpwatchがctimeのせいで機能しない問題への対策

tmpwatchの仕組みを踏まえた上で、tmpwatchがctimeのせいで機能しない問題への対策を考えると、
/etc/cron.daily/tmpwatchのflags=-umcをflags=-umにすべきということになる。

あと、今回の問題とは関係ないが、/tmpや/var/tmpでも、書き込み権限がなくても削除したいなら -f オプションをつけるといい。

参考
http://shobon.hatenablog.com/entry/2014/07/30/223550
http://shobon.hatenablog.com/entry/2014/10/15/213154

-Linux