FHS とファイル配置・検索 - find/locate と FHS【LPIC-1 104.7】
この記事で達成できること
- FHS(Filesystem Hierarchy Standard)の主要ディレクトリの用途を説明できる
- 「共有可能/非共有」「静的/可変」の区分でファイルの置き場所を判断できる
findの主要テスト(-name/-type/-size/-mtime/-perm/-user/-newer/-exec)を使い分けられるlocate/updatedbの仕組みと/etc/updatedb.confを理解できるfindとlocate、which/whereis/typeの使い分けを根拠付きで答えられる
LPIC-1 主題 104.7「システムファイルを見つけ、正しい位置に配置する」の中核。設定ファイルやログがどこにあるべきかを FHS で判断し、find / locate で実際に探し当てる技術。
FHS のどこに何を置くか
FHS 3.0 は Linux のディレクトリ構造を標準化した仕様。各ディレクトリには明確な役割があり、ファイルの種類で置き場所が決まる。まずは試験頻出の主要ディレクトリを押さえる。
| ディレクトリ | FHS 上の用途 |
|---|---|
/bin |
全ユーザーが使う必須コマンドのバイナリ |
/sbin |
システム管理用のバイナリ |
/etc |
ホスト固有のシステム設定(静的・非共有) |
/lib |
必須の共有ライブラリとカーネルモジュール |
/usr |
共有可能・読み取り専用のプログラムとデータ |
/usr/bin |
一般ユーザー向けの大半のコマンド |
/usr/sbin |
起動に必須でないシステム管理コマンド |
/usr/local |
管理者がローカルに導入したソフト |
/var |
運用中に変化する可変データ |
/var/log |
ログファイル |
/var/spool |
印刷・メール等のスプールデータ |
/tmp |
一時ファイル |
/home |
一般ユーザーのホームディレクトリ |
/root |
root ユーザーのホームディレクトリ |
/boot |
ブートローダの静的ファイルとカーネル |
/dev |
デバイスファイル |
/proc |
プロセス・カーネル情報の仮想ファイルシステム |
/sys |
デバイス・カーネルの仮想ファイルシステム |
/opt |
追加アプリケーションソフトウェアパッケージ |
/mnt |
一時的にマウントするファイルシステムの場所 |
/media |
リムーバブルメディアのマウントポイント |
/srv |
このシステムが提供するサービス用データ |
/bin と /sbin には「/usr をマウントする前に必要なコマンド」を置く決まりがある。起動直後やシングルユーザーモードでも /usr が別パーティションで未マウントの状況があるため、最低限の復旧コマンドはルートパーティション側に置く設計になっている。
/proc と /sys はディスク上に実体がない仮想ファイルシステム。/proc/cpuinfo や /sys/class/ はカーネルが動的に生成する情報で、編集してファイルを「保存」する場所ではない。
共有可能/非共有・静的/可変とは
FHS は 2 つの独立した軸でファイルを分類する。「共有可能(shareable)か非共有(unshareable)か」と「静的(static)か可変(variable)か」。この区分が分かると、なぜ /usr と /var が分かれているのかが腑に落ちる。
- 共有可能: 1 台に置いて複数ホストから使えるファイル(例:
/usrのプログラム、/home) - 非共有: そのホスト固有のファイル(例:
/etcの設定、デバイスのロックファイル) - 静的: 管理者が手を入れない限り変わらないファイル(バイナリ・ライブラリ・ドキュメント)
- 可変: 運用中に通常変化するファイル(ログ・スプール・キャッシュ)
| 共有可能 | 非共有 | |
|---|---|---|
| 静的 | /usr、/opt |
/boot、/etc |
| 可変 | /var/mail、/var/spool/news |
/var/run、/var/lock |
この分類の狙いは、静的ファイルを読み取り専用メディアに置いたり、可変ファイルだけ別のバックアップ方針にしたりできるようにすること。歴史的に UNIX は両者を混在させていたが、可変ファイルを /var に集約することで /usr を読み取り専用で別マウントできるようになった。
/usr と /usr/local の使い分け
ディストリビューションのパッケージ管理が入れるソフトは /usr(/usr/bin 等)に、管理者が手動で導入したローカルなソフトは /usr/local(/usr/local/bin 等)に置く。役割を分ける理由は明確で、混ぜないことがシステム保守の前提になる。
/usr 配下はパッケージマネージャ(apt / dnf 等)の管理領域で、OS アップグレードやパッケージ更新で上書きされる可能性がある。一方 /usr/local はパッケージ管理が触らない領域なので、ソースからビルドしたソフトや自前スクリプトをここに置けば、OS 更新で消える・衝突する事故を避けられる。
自前ビルドしたコマンドを /usr/bin に直接コピーすると、同名パッケージの更新時に上書き・衝突するおそれがある。手動導入は /usr/local に置くのが FHS の意図。
find の主要テストを使い分ける
find は指定ディレクトリ以下を実時間で走査し、条件に合うファイルを探す。locate と違って常に最新の状態を反映し、検索後の処理(削除・権限変更等)まで一気にできるのが強み。
Step 1: 名前と種類で絞り込む
find /etc -name '*.conf' -type f
/etc/ssh/sshd_config.conf /etc/logrotate.conf /etc/resolv.conf
-name はファイル名(パス末尾のベース名)をシェルパターンで照合する。-type f は通常ファイル、-type d はディレクトリ、-type l はシンボリックリンクを表す。大文字小文字を無視するなら -iname を使う。
Step 2: サイズと更新日時で探す
find /var/log -type f -size +100M find /home -type f -mtime -7
/var/log/journal/system.journal /home/user/report-draft.md
-size +100M は 100 MiB を超えるファイル。接尾辞は c(バイト)、k(KiB)、M(MiB)、G(GiB)で、+ は「より大きい」、- は「より小さい」を意味する。-mtime -7 は「7×24 時間以内に更新」。-mtime +1 は「2 日以上前に更新」を意味する点に注意(端数は切り捨て)。
Step 3: 所有者と権限で探す
find /home -user alice -perm -0200 find / -perm /4000 -type f 2>/dev/null
/home/alice/notes.txt /usr/bin/passwd
-user alice は所有者が alice のファイル。-perm /4000 は「指定ビットのいずれかが立っている」(ここでは SUID)を意味し、-perm -0664 のように - を付けると「指定ビットがすべて立っている」になる。SUID ビットの調査などに使える。
Step 4: 検索結果をまとめて処理する
find /tmp -name '*.tmp' -mtime +7 -exec rm {} +
find . -name '*.txt' -newer reference.txt -exec ls -l {} \;-rw-r--r-- 1 user user 320 May 30 10:00 ./new-note.txt
-exec command {} \; は一致したファイルごとにコマンドを 1 回実行し、{} がファイル名に置換される。-exec command {} + は複数ファイルをまとめて 1 つのコマンドラインに渡す(xargs に近い動作)ため効率的。-newer reference.txt は基準ファイルより新しく更新されたものを選ぶ。
-exec ... {} \; のセミコロンはシェルに解釈されないよう \; とエスケープする(または ';')。これを忘れると find: missing argument to -exec 等のエラーになる。
locate と updatedb の仕組み
locate はファイルシステムを直接走査せず、あらかじめ作られたファイル名データベースを検索するため非常に高速。多くのディストリビューションでは mlocate 実装が使われる。
Step 1: locate で高速検索する
locate sshd_config locate -i readme
/etc/ssh/sshd_config /usr/share/doc/openssh-server/README
locate はデータベースに登録された名前を瞬時に返す。-i(--ignore-case)で大文字小文字を無視できる。ただし結果は「データベースを最後に更新した時点」のスナップショットである点に注意。
Step 2: updatedb でデータベースを更新する
sudo updatedb locate newfile.txt
/home/user/newfile.txt
updatedb がデータベースを再構築する。新規作成・削除したファイルは updatedb を実行するまで locate の結果に反映されない。多くの環境では cron 等で定期実行されるが、作成直後のファイルを探すなら手動更新が必要。
Step 3: /etc/updatedb.conf で対象を調整する
grep -E 'PRUNEPATHS|PRUNEFS' /etc/updatedb.conf
PRUNEFS="NFS nfs nfs4 afs binfmt_misc ..." PRUNEPATHS="/tmp /var/spool /media /var/lib/os-prober ..."
/etc/updatedb.conf で索引対象を調整する。PRUNEPATHS は索引から除外するディレクトリ、PRUNEFS は除外するファイルシステム種別。これにより /tmp やネットワークマウント等が無駄に索引されるのを防いでいる。
find と locate はどう使い分けるか
リアルタイム性が必要なら find、名前だけ高速に探すなら locate。両者は競合せず、用途で使い分けるのが正解。
find はディスクを実走査するため遅いが、常に最新で、サイズ・更新日時・権限・所有者といった多彩な条件と、-exec による後続処理が使える。locate はデータベース参照で一瞬だが、名前ベースの検索に限られ、updatedb 後でないと最新状態を反映しない。「さっき作ったファイルがどこか」は find、「あの設定ファイルのパスは」は locate が向く。
which / whereis / type の違い
コマンドの「場所」を調べる 3 つは目的が異なる。実行されるバイナリの場所は which、関連ファイル一式は whereis、シェルがどう解釈するかは type。
which python3 whereis ls type cd type ll
/usr/bin/python3 ls: /usr/bin/ls /usr/share/man/man1/ls.1.gz cd is a shell builtin ll is aliased to `ls -alF'
which:PATH上から実行されるコマンドのフルパスを返すwhereis: コマンドのバイナリ・ソース・man ページの場所を探すtype: シェル組み込み。その名前がエイリアス・組み込み・関数・キーワード・ファイルのどれとして解釈されるかを示す
cd のようなシェル組み込みコマンドは which では見つからない(実行ファイルが存在しないため)。「なぜ which cd が空なのか」は type cd が組み込みだと教えてくれる。
よくあるミスと対処
- locate の結果が古い: 作ったばかりのファイルが出ない / 消したはずのファイルが残る。
sudo updatedbでデータベースを更新する -execのセミコロン忘れ:find ... -exec rm {} \;の\;を書かずfind: missing argument to -execになる。\;または+で終端する/usrと/usr/localの混同: 自前ビルドのソフトを/usr/binに入れてパッケージ更新で衝突。手動導入は/usr/localに置く-mtimeの符号誤解:-mtime -1(24 時間以内)と-mtime +1(2 日以上前)を取り違える。「今日のファイル」は-mtime -1- which でシェル組み込みを探す:
which cdが空で戸惑う。組み込み・エイリアスの確認はtypeを使う
トラブルシューティング
症状: locate で作成直後のファイルが見つからない
原因: locate はデータベースを参照し、updatedb 実行時点のスナップショットしか持たない
確認:
locate newfile.txt
対処: sudo updatedb でデータベースを更新してから再検索する。最新状態を確実に探すなら find を使う。
症状: find -exec でエラー「missing argument to -exec」
原因: コマンド終端のセミコロンがエスケープされていない
確認:
find . -name '*.log' -exec ls -l {} \;対処: -exec のコマンドは \;(1 件ずつ実行)または +(まとめて実行)で必ず終端する。
症状: find / を実行すると権限エラーが大量に出る
原因: 一般ユーザーで読めないディレクトリ(/proc の一部や他ユーザー領域)を走査している
確認:
find / -name target.conf 2>/dev/null
対処: 2>/dev/null で標準エラーを捨てるか、検索範囲を /etc 等に絞る。システム全体を確実に探すなら sudo find を使う。
作業完了チェックリスト
- [ ] 主要 FHS ディレクトリの用途を表で確認した
- [ ] 共有可能/非共有・静的/可変の区分を理解した
- [ ]
findで名前・種類・サイズ・更新日時・権限・所有者の検索を試した - [ ]
-exec {} \;と-exec {} +の違いを確認した - [ ]
locate検索後にsudo updatedbで更新を反映した - [ ]
which/whereis/typeを使い分けた
まとめ
| 目的 | コマンド / 場所 | ポイント |
|---|---|---|
| 設定ファイルの場所 | /etc(静的・非共有) |
ホスト固有 |
| 可変データの場所 | /var(ログ・スプール) |
運用で変化 |
| 手動導入ソフト | /usr/local |
パッケージ管理と分離 |
| 条件付き検索+処理 | find -size/-mtime/-exec |
実時間・最新・後処理可 |
| 名前の高速検索 | locate + sudo updatedb |
DB 参照・要更新 |
| 実行ファイルの場所 | which / whereis / type |
用途で使い分け |
FHS はファイルの「正しい置き場所」を判断する地図、find / locate はその地図上で目的のファイルを探す道具。両方を押さえれば、未知のシステムでも設定やログを迷わず辿れる。