用語集
タイムスタンプ
UNIX におけるファイルの時刻管理 (atime/ctime/mtime) (更新時刻・更新日時・変更日時)
最終更新
UNIX・Linux のファイルには、一般的に 3つのタイムスタンプがある。
- atime … 最終アクセス時刻 (access time)
- mtime … 最終変更時刻 (modify time)
- ctime … 最終ステータス変更時刻 (change time)
●タイムスタンプの表示
ls -l で mtime、ls -lc で ctime、ls -lu で atime を表示することができる。
% ls -l abc.txt
-rw-r--r-- 1 user group 2052 Jan 8 16:55 abc.txt
⇒ mtime
% ls -lc abc.txt
-rw-r--r-- 1 user group 2052 Jan 8 16:53 abc.txt
⇒ ctime
% ls -lu abc.txt
-rw-r--r-- 1 user group 2052 Feb 12 08:31 abc.txt
⇒ atime
また、stat コマンドでもそれぞれのタイムスタンプを表示することができる。
% stat hoge.txt
File: `hoge.txt'
(略)
Access: 2018-05-10 21:14:12.372266973 +0900
Modify: 2018-05-10 21:14:11.165267108 +0900
Change: 2018-05-10 21:14:11.165267108 +0900
●タイムスタンプの変更
atime・mtime は、touch コマンドを用いれば (つまり utimes(2) を用いれば) 任意の時刻を設定することが可能である。
しかし ctime に任意の時刻を設定することはできない。これは、chmod コマンドなどを使って ctime に現在時刻をセットすることはできるが、過去や未来の日時をセットできないということ。ただし fsdb コマンドなどで、ファイルシステムを直接いじれば何でもアリである。
●atime・mtime・ctime の詳細
atime は、最後にファイルにアクセスした時刻のこと。より正確には、ファイル内容を read(2) した場合に変更される。ファイルをオープンしただけでは変更されないし、ファイル内容を write(2) しても変更されない。当然ながら、read(2) する権限がなかった場合も変更されない。
mtime は、最後にファイルを変更した時刻のこと。より正確には、ファイルに write(2) または truncate(2) した場合に変更される。
ctime は、最後にファイルを変更した時刻のこと。より正確には、ファイルに write(2) または truncate(2) した場合、そして inode データの修正を行った場合に変更される。inode データに含まれるのは、
- ファイル名
- ファイルサイズ
- パーミッション
- リンク数
- オーナー・グループ
などである。つまり、write(2)・rename(2)・truncate(2)・chmod(2)・link(2)・chown(2) などのシステムコールを発行すると ctime が更新される。なお、たまに「ctime はファイル生成時刻 であり、Create TIME の略である」と解説している文章を見かけるが、誤り。
ファイル内容を write(2) や truncate(2) で更新した場合、mtime と ctime の両方が更新されることに注意 (ファイルサイズが変わらないように write(2) すれば、ctime は更新されないかと予想していたが、試してみると更新されてしまった)。
●シンボリックリンクのタイムスタンプ
いまどきの UNIX ではシンボリックリンクそのものの atime, mtime, ctime を持っているが、シンボリックリンクそのもののタイムスタンプを変更できるのは lutimes(2) を持つ OS のみである。*BSD には lutimes(2) が実装されているのでシンボリックリンクそのものの atime・mtime を変更できるが、lutimes(2) を持たない Linux・Solaris・HP-UX では変更ができない。
●ファイル生成時刻
伝統的な UNIX では、ファイル生成時刻は保持していない。ただし FreeBSD 5.x から使用されている UFS2 では、inode が生成された時刻「birthtime」という情報がある (struct stat の st_birthtime)。これぞまさしくファイル生成時刻と言えるだろう。NetBSD や macOS でも birthtime は使用可能である。
Linux 界隈では、ext4 よりファイル生成時刻 crtime が追加されているが、カーネルや glibc が未対応であるため、値を取り出すことができない状況が続いていた。2017年5月リリースの Linux-4.11 カーネルにて statx(2) システムコールが追加され、struct statx_timestamp stx_btime にて取得が可能になったので、早晩 glibc も対応が進むと思われる。
●mount の noatime オプション
ファイルを read(2) すると atime が更新されてしまうが、更新には少なからず時間がかかる。たとえば web サーバなどの用途では、どのファイルが参照されたかは web サーバのログに記録すればよいので、atime を更新する価値がほとんどない。そのような場合、mount 時に noatime オプションを付加することで atime の更新が行われなくなり、少しだけパフォーマンスが向上する。
# mount -t ufs -o noatime /www
●ファイルシステム
これまで「UNIX のファイルには、一般的に 3つのタイムスタンプがある」などと解説してきたが、実際にはファイルシステムにも依存する。
たとえば、UFS2 ではファイル生成時刻を保持できる。仮に Linux で UFS2 をマウントできたとして、Linux 側にファイル生成時刻を読み出すインタフェースがなかったとしたら、それを参照することはできない (Linux の UFS2 対応状況は知らない)。