Linuxでファイルの最終アクセス日時を表示する方法と応用の実務上の結論は「最終access時刻はstatの%xまたはepoch秒の%Xで読みます。ただしatimeは読取りごとに必ず更新される記録ではないため、mount optionと用途上の限界を併記します。」です。今回の判定単位はfile inodeとmountです。atime単独では閲覧者を証明できないため、epoch値、取得時刻、FSTYPE、mount optionsを一組で保存します。
atimeを証拠として扱う前提
atimeはファイル内容が最後に読まれた時刻を表す候補ですが、relatimeではmtimeやctimeより古い場合などに更新が抑制され、noatimeでは通常更新されません。lazytime、ページキャッシュ、NFSなどのクライアントキャッシュも観測へ影響します。そのため一つの時刻だけから、特定ユーザーがその時刻に開いたと断定する用途には向きません。
人が読む表示にはstat –format=’%n %x’、時系列処理には整数の%Xを使います。findmnt -TでFSTYPEとOPTIONSを同時に保存し、複数ファイルはfindの%A@で比較します。シンボリックリンク自体と参照先のどちらを調べるかも先に決め、device番号とinode番号を添えると、同名ファイルの取り違えを防げます。
atime調査で最初に固定する四項目
- 対象pathとsymbolic linkの扱いを決める
- filesystem typeとmount optionを確認する
- timezoneと必要な時刻精度を決める
- atimeを監査証跡へ使えるか評価する
device・inodeとfindmnt -Tの結果が揃わなければ調査を開始しません。symlinkの参照先が想定と違う場合は停止し、real pathとmount pointを確定してからread前後のsampleを採り直します。
人向け日時・epoch・mount optionを順に採る
access時刻を人向け表示
stat --format='%n %x' -- ./document.txt
timezone offsetを含む表示を記録します。
epoch秒で取得
stat --format='%n %X' -- ./document.txt
機械比較では整数値を使い、表示時にtimezoneを適用します。
全timestampを並べる
stat --format='access=%x\nmodify=%y\nchange=%z\nbirth=%w' -- ./document.txt
atime、mtime、ctime、birthtimeを混同しないよう同時に確認します。
mount情報を確認
findmnt -T ./document.txt -o TARGET,SOURCE,FSTYPE,OPTIONS
relatimeやnoatime等のoptionを対象filesystem単位で読みます。
複数fileをepochで比較
find ./docs -maxdepth 1 -type f -printf '%A@ %p\n' | sort -n
file名にnewlineがある場合は表示formatを別途安全化します。
statの出力とmount条件を結び付ける
atimeは最後にdataへaccessした時刻ですが、performanceのため更新を抑えるmount optionが一般的です。relatimeでは一定条件でのみ更新され、noatimeなら通常更新されません。backup、scanner、cacheのreadが時刻へ影響する場合もあり、userが開いた証明にはなりません。
%xには日時、ナノ秒相当の小数部、timezone offsetが含まれ、%XはUnix epoch秒です。%yはmtime、%zはctime、%wはbirth timeなので列名を省略しません。%wがハイフンになるfilesystemも正常です。ログへは表示値とepoch値の両方を残し、時刻だけでなくpath、device、inode、mount optionを一組にします。
Permission deniedは時刻が存在しない意味ではなく、検索権限や読取り権限の不足です。値が更新されない場合はnoatime、relatimeの条件、cache、readに使ったprocessを確認します。逆に調査command自身のreadでatimeが動く場合もあります。複製時にatimeを保持するtoolもあるため、copy先の値を原本の実アクセス履歴と誤認しません。
atimeが動かない時にnoatimeと権限を分ける
- atimeを必ず最後に人が開いた時刻と解釈する
- relatime/noatimeを確認しない
- ctimeをcreation timeと呼ぶ
- timezoneなしの文字列を比較する
- backupやantivirusのreadを見落とす
stat失敗は0秒扱いにせず、path消失、search permission、mount切替を別statusで記録します。atimeが不変でもnoatimeやrelatimeなら正常候補なので、設定を変えずfixtureで更新条件を再確認します。
atime確認自体のreadが環境によってはatimeを更新し得るため、厳密なforensicsではsnapshotや専用tool、取得手順の承認が必要です。touch -a等で時刻を変更せず、証跡はUTC/offsetと取得時刻を含めて保存します。
監査やforensicsでは、確認のためのopenが証跡を変える可能性を考慮します。必要ならstorage snapshot、read-only image、専用収集toolを使い、原本へのread回数と収集時刻を記録します。atimeを書き戻すtouch -aを復元手段にすると別のmetadataも変化し得るため、無断で実行せず、取得手順自体を証跡へ含めます。
atime確認を再現可能にする
relatime、noatimeを含むtest filesystemでread前後の%x/%Xを記録し、想定更新条件を確認します。file cache、symlink、directory accessも分け、監査用途では別logと照合します。
検証用directoryに既知のmtimeを持つ小さなfileを用意し、read前後の%xと%X、findmntのoption、実行時刻を表にします。relatime条件を満たさず値が変わらないケースも合格例に含めます。通常file、directory、symbolic linkを分け、同じhostで二回取得した値が説明どおりかを確認します。本番fileの時刻をtouchで動かす検証は行いません。
inodeとmount条件を含むatime recordを作る
自動収集ではlocale依存の日時をparseせず、%X、device、inode、sizeを区切り文字付きで出力し、別列にFSTYPEとOPTIONSを保存します。対象が消えた場合、権限不足、stat失敗を0秒へ変換せず個別statusにします。監視の閾値は『何日前』だけでなく、noatime対象を除外する規則とclock同期状態まで定義します。
古いatimeを削除判断へ直結させない
最近読まれていない候補の棚卸しにはatimeを補助指標として使えますが、アクセス主体や目的を追うならauditd、application log、object storage access logなど別の記録が必要です。削除候補の選定ではowner、retention、backup、open file、法的保持を合わせて確認し、atimeが古いという理由だけで自動削除へ接続しません。
合格は同じdevice・inodeについて%xと%Xが一致し、mount option付きで再現できることです。inodeまたはmountが途中で変わったrunは破棄し、snapshotから収集をやり直します。

コメント