メインコンテンツまでスキップ

ファイルシステム

Linuxのファイルシステム階層、マウント、パーミッションの基礎を学びます。


目次

  1. ファイルシステム階層
  2. ファイルの種類
  3. マウント
  4. inode
  5. リンク
  6. ファイルシステムの種類
  7. コンテナでのファイルシステム

ファイルシステム階層

FHS(Filesystem Hierarchy Standard)

/
├── bin → 基本コマンド(ls, cp, mv等)
├── boot → ブートローダー、カーネル
├── dev → デバイスファイル
├── etc → 設定ファイル
├── home → ユーザーのホームディレクトリ
├── lib → 共有ライブラリ
├── media → リムーバブルメディアのマウントポイント
├── mnt → 一時的なマウントポイント
├── opt → サードパーティソフトウェア
├── proc → プロセス情報(仮想ファイルシステム)
├── root → rootユーザーのホーム
├── run → 実行時データ
├── sbin → システム管理コマンド
├── srv → サービスデータ
├── sys → カーネル・デバイス情報(仮想)
├── tmp → 一時ファイル
├── usr → ユーザープログラム
│ ├── bin → ユーザーコマンド
│ ├── lib → ライブラリ
│ ├── local → ローカルインストール
│ └── share → アーキテクチャ非依存データ
└── var → 可変データ
├── log → ログファイル
├── cache → キャッシュ
├── lib → 状態情報
└── run → 実行時データ

重要なディレクトリ

ディレクトリ説明
/etc設定ファイル/etc/passwd, /etc/nginx/
/var/logログファイル/var/log/syslog, /var/log/nginx/
/procプロセス情報/proc/cpuinfo, /proc/meminfo
/sysカーネル情報/sys/class/net/, /sys/block/
/devデバイスファイル/dev/sda, /dev/null
/tmp一時ファイル再起動で削除される

設定ファイルの確認

# システム情報
cat /etc/os-release

# ホスト名
cat /etc/hostname

# ネットワーク
cat /etc/hosts
cat /etc/resolv.conf

# ユーザー情報
cat /etc/passwd
cat /etc/group

ファイルの種類

7種類のファイルタイプ

┌─────────────────────────────────────────────────────────────┐
│ ファイルタイプ │
├─────────────────────────────────────────────────────────────┤
│ │
│ - 通常ファイル テキスト、バイナリ │
│ d ディレクトリ ファイルの格納場所 │
│ l シンボリックリンク 別ファイルへの参照 │
│ c キャラクタデバイス 文字単位のデバイス(端末等) │
│ b ブロックデバイス ブロック単位のデバイス(ディスク等) │
│ p 名前付きパイプ プロセス間通信 │
│ s ソケット プロセス間通信 │
│ │
└─────────────────────────────────────────────────────────────┘

確認方法

# ls -l の最初の文字でタイプを確認
ls -l /
# drwxr-xr-x → d = ディレクトリ
# -rw-r--r-- → - = 通常ファイル
# lrwxrwxrwx → l = シンボリックリンク

# ファイルタイプの詳細
file /bin/ls
file /etc/passwd
file /dev/null

# stat コマンド
stat /etc/passwd

特殊なファイル

# /dev/null - 出力を捨てる
echo "discard" > /dev/null

# /dev/zero - ゼロを出力
dd if=/dev/zero of=zeros.bin bs=1M count=10

# /dev/random, /dev/urandom - 乱数生成
head -c 32 /dev/urandom | base64

# /dev/stdin, /dev/stdout, /dev/stderr
echo "hello" | cat /dev/stdin

マウント

マウントとは

マウントとは、ストレージデバイス(HDD、SSD、USBメモリなど)やファイルシステムを、ディレクトリツリーの特定の場所(マウントポイント)に接続し、アクセス可能にする操作です。

WindowsやmacOSでは、USBメモリを挿すと自動的にドライブとして認識されますが、Linuxでは明示的に「このデバイスをこのディレクトリで使う」と指定する必要があります。

┌─────────────────────────────────────────────────────────────┐
│ マウントの仕組み │
├─────────────────────────────────────────────────────────────┤
│ │
│ 【マウント前】 │
│ │
│ 物理デバイス ディレクトリツリー │
│ ┌─────────────┐ / │
│ │ /dev/sda1 │ ├── bin │
│ │ (ext4) │ ├── etc │
│ │ 100GB │ ├── home │
│ └─────────────┘ └── mnt │
│ └── data (空) │
│ ┌─────────────┐ │
│ │ /dev/sdb1 │ ← まだアクセスできない │
│ │ (ext4) │ │
│ │ 500GB │ │
│ └─────────────┘ │
│ │
│ 【マウント後】 mount /dev/sdb1 /mnt/data │
│ │
│ 物理デバイス ディレクトリツリー │
│ ┌─────────────┐ / │
│ │ /dev/sda1 │ ├── bin │
│ │ (ext4) │──────────────►├── etc │
│ │ 100GB │ ├── home │
│ └─────────────┘ └── mnt │
│ └── data ◄──────┐ │
│ ┌─────────────┐ │ │ │
│ │ /dev/sdb1 │────────────────────────┘ │ │
│ │ (ext4) │ ← /mnt/data でアクセス可能に ─────┘ │
│ │ 500GB │ │
│ └─────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘

なぜマウントが必要か

理由説明
柔軟性どのデバイスをどこに配置するか自由に決められる
抽象化アプリケーションはデバイスを意識せずパスでアクセス
セキュリティ読み取り専用、実行禁止などのオプションを指定可能
動的な管理必要なときだけ接続、不要なら切断

マウントポイント

マウントポイントは、デバイスを接続するディレクトリです。このディレクトリは事前に存在している必要があります。

# マウントポイントを作成
sudo mkdir /mnt/usb

# デバイスをマウント
sudo mount /dev/sdb1 /mnt/usb

# これで /mnt/usb 以下にデバイスの内容が見える
ls /mnt/usb

マウント操作

# 現在のマウント状況を確認
mount # 全マウント一覧
df -h # ディスク使用量と共に表示
lsblk # ブロックデバイスの階層表示
findmnt # ツリー形式で表示

# 基本的なマウント
sudo mount /dev/sdb1 /mnt/data

# オプション付きマウント
sudo mount -o ro /dev/sdb1 /mnt/data # 読み取り専用(read-only)
sudo mount -o rw /dev/sdb1 /mnt/data # 読み書き可能(read-write)
sudo mount -o noexec /dev/sdb1 /mnt/data # 実行禁止
sudo mount -o nosuid /dev/sdb1 /mnt/data # SetUID禁止
sudo mount -t ext4 /dev/sdb1 /mnt/data # ファイルシステム種別を指定
sudo mount -o remount,rw /mnt/data # 既存マウントの再マウント

# アンマウント(取り外し)
sudo umount /mnt/data
sudo umount /dev/sdb1 # デバイス名でも可
sudo umount -l /mnt/data # lazy unmount(使用中でも強制)
sudo umount -f /mnt/data # 強制アンマウント

/etc/fstab(自動マウント設定)

システム起動時に自動的にマウントするデバイスを設定するファイルです。

cat /etc/fstab

# 形式: デバイス マウントポイント タイプ オプション dump pass
#
# デバイス: /dev/sda1 または UUID=xxx
# マウントポイント: マウント先ディレクトリ
# タイプ: ext4, xfs, nfs など
# オプション: defaults, ro, noexec など
# dump: バックアップ対象か(通常0)
# pass: fsckの順序(ルートは1、他は2、チェック不要は0)

# 例:
# /dev/sda1 / ext4 defaults 0 1
# /dev/sdb1 /data ext4 defaults 0 2
# UUID=abcd-1234 /backup xfs defaults,nofail 0 2
# //server/share /mnt/share cifs credentials=/etc/samba/creds 0 0

仮想ファイルシステム

物理デバイスではなく、カーネルが提供する仮想的なファイルシステムです。

# procfs - プロセスとカーネル情報
mount | grep proc
# proc on /proc type proc

cat /proc/cpuinfo # CPU情報
cat /proc/meminfo # メモリ情報
cat /proc/1/status # PID 1のプロセス情報
ls /proc/ # 数字のディレクトリ = プロセスID

# sysfs - カーネル・デバイス情報
mount | grep sysfs
# sysfs on /sys type sysfs

ls /sys/class/net/ # ネットワークインターフェース
cat /sys/class/net/eth0/address # MACアドレス
ls /sys/block/ # ブロックデバイス

# tmpfs - メモリ上のファイルシステム(高速、再起動で消える)
mount | grep tmpfs
df -h /tmp
df -h /run

inode

inodeとは

inode(アイノード) は、ファイルやディレクトリのメタデータ(属性情報)を格納するデータ構造です。ファイルシステム上のすべてのファイルには、固有のinode番号が割り当てられます。

重要なポイント:ファイル名はinodeに含まれません。ファイル名は「ディレクトリエントリ」に保存され、inode番号と紐づけられています。

┌─────────────────────────────────────────────────────────────┐
│ ファイルの実体とは │
├─────────────────────────────────────────────────────────────┤
│ │
│ ファイル = ファイル名 + inode + データブロック │
│ │
│ ディレクトリエントリ inode データ │
│ ┌─────────────────┐ ┌──────────────┐ ┌──────────┐ │
│ │ ファイル名 │ │ inode番号 │ │ │ │
│ │ "report.txt" │───►│ 12345 │───►│ Hello │ │
│ │ │ │ │ │ World │ │
│ │ inode番号: 12345│ │ タイプ: 通常 │ │ ... │ │
│ └─────────────────┘ │ 権限: 644 │ │ │ │
│ │ 所有者: user │ └──────────┘ │
│ │ サイズ: 1234 │ │
│ │ 更新日時: ...│ │
│ │ ブロック: → │ │
│ └──────────────┘ │
│ │
│ ディレクトリ = ファイル名とinode番号の対応表 │
│ │
└─────────────────────────────────────────────────────────────┘

inodeに含まれる情報

項目説明
ファイルタイプ通常ファイル、ディレクトリ、シンボリックリンクなど
パーミッション読み取り、書き込み、実行の権限
所有者UID(ユーザーID)、GID(グループID)
サイズファイルのバイト数
タイムスタンプatime(アクセス)、mtime(変更)、ctime(属性変更)
リンクカウントこのinodeを参照しているファイル名の数
ブロックポインタ実データが格納されているディスクブロックの位置

含まれないもの: ファイル名、ファイルの内容(データ)

タイムスタンプの違い

種類名前更新されるタイミング
atimeAccess timeファイルを読んだとき
mtimeModify timeファイルの内容を変更したとき
ctimeChange timeファイルの属性(権限、所有者など)を変更したとき

inode情報の確認

# inode番号の確認
ls -i file.txt
# 12345678 file.txt

# 同じディレクトリ内のファイルのinode
ls -li
# 12345678 -rw-r--r-- 1 user group 1234 Dec 23 10:00 file.txt
# 12345679 drwxr-xr-x 2 user group 4096 Dec 23 10:00 subdir

# 詳細情報(statコマンド)
stat file.txt
# Output:
# File: file.txt
# Size: 1234 Blocks: 8 IO Block: 4096 regular file
# Device: 801h/2049d Inode: 12345678 Links: 1
# Access: (0644/-rw-r--r--) Uid: ( 1000/user) Gid: ( 1000/user)
# Access: 2024-01-15 10:00:00.000000000 +0900
# Modify: 2024-01-15 09:00:00.000000000 +0900
# Change: 2024-01-15 09:00:00.000000000 +0900
# Birth: 2024-01-01 00:00:00.000000000 +0900

# ファイルシステムのinode使用状況
df -i
# Filesystem Inodes IUsed IFree IUse% Mounted on
# /dev/sda1 6553600 234567 6318033 4% /

inodeが枯渇するケース

ディスク容量が残っていても、inodeを使い切るとファイルを作成できなくなります。

# よくある原因:大量の小さなファイル
# 例:メールスプール、セッションファイル、キャッシュ

# 確認方法
df -i

# IUse% が 100% だとファイル作成不可
# "No space left on device" エラーが出るが df -h では空きがある

リンク

リンクとは

リンクとは、既存のファイルに別名(エイリアス)をつける仕組みです。Linuxには2種類のリンクがあります。

種類説明
ハードリンク同じinodeを指す別のファイル名
シンボリックリンク(ソフトリンク)別のファイルへのパスを記録したファイル

ハードリンク

ハードリンクは、同じinodeを指す別のファイル名です。つまり、1つのファイルの実体に対して複数の名前をつけることができます。

┌─────────────────────────────────────────────────────────────┐
│ ハードリンクの仕組み │
├─────────────────────────────────────────────────────────────┤
│ │
│ ディレクトリエントリ │
│ ┌────────────────┐ │
│ │ original.txt │────┐ │
│ │ inode: 12345 │ │ │
│ └────────────────┘ │ inode 12345 │
│ │ ┌──────────────┐ │
│ ┌────────────────┐ ├───►│ リンク数: 2 │ │
│ │ hardlink.txt │────┘ │ 権限: 644 │ │
│ │ inode: 12345 │ │ サイズ: 1234 │ │
│ └────────────────┘ │ ブロック → ──┼──► データ │
│ └──────────────┘ │
│ │
│ どちらのファイル名からも同じデータにアクセス │
│ どちらかを削除しても、もう一方は残る │
│ リンク数が0になったときにデータが解放される │
│ │
└─────────────────────────────────────────────────────────────┘

ハードリンクの特徴:

  • 同じinode番号を持つ
  • どちらが「本物」という区別はない(対等)
  • 一方を削除しても、もう一方は残る
  • ファイルシステムをまたげない(同一パーティション内のみ)
  • ディレクトリにはハードリンクを作成できない(循環参照防止)

シンボリックリンク(ソフトリンク)

シンボリックリンクは、別のファイルへのパスを内容として持つ特殊なファイルです。ショートカットやエイリアスに近い概念です。

┌─────────────────────────────────────────────────────────────┐
│ シンボリックリンクの仕組み │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌────────────────┐ inode 99999 │
│ │ symlink.txt │ ┌──────────────┐ │
│ │ inode: 99999 │──►│ タイプ: link │ │
│ └────────────────┘ │ 内容: │ │
│ │ "original.txt"│ │
│ └──────┬───────┘ │
│ │ │
│ │ パス解決 │
│ ▼ │
│ ┌────────────────┐ inode 12345 │
│ │ original.txt │ ┌──────────────┐ │
│ │ inode: 12345 │──►│ タイプ: 通常 │───► データ │
│ └────────────────┘ │ サイズ: 1234 │ │
│ └──────────────┘ │
│ │
│ symlink.txt を開く → "original.txt" を読む → 本体を開く │
│ │
│ original.txt を削除すると: │
│ symlink.txt は残るが、リンク切れになる(dangling link) │
│ │
└─────────────────────────────────────────────────────────────┘

シンボリックリンクの特徴:

  • 独自のinodeを持つ(元ファイルとは異なる)
  • パス文字列を内容として持つ
  • ファイルシステムをまたげる(異なるパーティションも可)
  • ディレクトリにも作成可能
  • 元ファイルを削除するとリンク切れになる
  • 相対パス・絶対パスどちらでも指定可能

比較表

特徴ハードリンクシンボリックリンク
inode同じ異なる
本体との区別なし(対等)あり(リンクは別ファイル)
ファイルシステム跨ぎ不可可能
ディレクトリに作成不可可能
元ファイル削除時データは残るリンク切れになる
サイズ元ファイルと同じパス文字列の長さ
主な用途バックアップ、スナップショットパスのエイリアス、バージョン切り替え

リンクの作成と確認

# ハードリンクの作成
ln original.txt hardlink.txt

# inode番号を確認(同じ番号)
ls -li original.txt hardlink.txt
# 12345678 -rw-r--r-- 2 user group 1234 Dec 23 10:00 hardlink.txt
# 12345678 -rw-r--r-- 2 user group 1234 Dec 23 10:00 original.txt
# ^ リンク数が2になっている

# シンボリックリンクの作成
ln -s original.txt symlink.txt

# 確認(-> で参照先が表示される)
ls -l symlink.txt
# lrwxrwxrwx 1 user group 12 Dec 23 10:00 symlink.txt -> original.txt
# ^ 先頭が 'l' = シンボリックリンク

# inode番号を確認(異なる番号)
ls -li original.txt symlink.txt
# 12345678 -rw-r--r-- 2 user group 1234 Dec 23 10:00 original.txt
# 99999999 lrwxrwxrwx 1 user group 12 Dec 23 10:00 symlink.txt -> original.txt

# リンク先の確認
readlink symlink.txt
# original.txt

# 絶対パスでリンク先を確認
readlink -f symlink.txt
# /home/user/original.txt

# リンク切れの確認
ls -l symlink.txt # ファイルが存在しない場合、赤く表示されることが多い
file symlink.txt # "broken symbolic link" と表示される

# リンクの削除(元ファイルには影響なし)
rm symlink.txt
# または
unlink symlink.txt

よくある使用例

# バージョン切り替え(シンボリックリンク)
ln -s /opt/java/jdk-17 /opt/java/current
# /opt/java/current を参照するようにしておけば、
# リンク先を変えるだけでバージョン切り替え可能

# 設定ファイルの共有
ln -s /shared/config/app.conf /etc/myapp/app.conf

# ライブラリのバージョン管理
ls -l /lib/x86_64-linux-gnu/libc.so*
# libc.so.6 -> libc-2.31.so

ファイルシステムの種類

主なファイルシステム

FS説明用途
ext4Linux標準、ジャーナリング一般的なLinux
xfs高性能、大容量向けRHEL標準、大規模
btrfsCoW、スナップショット先進的な機能
zfs高機能、データ保護ストレージサーバー
tmpfsメモリベース/tmp, /run
overlayfsレイヤー構造Docker

ファイルシステム操作

# ファイルシステムの作成
sudo mkfs.ext4 /dev/sdb1
sudo mkfs.xfs /dev/sdb2

# ファイルシステムの確認
sudo fsck /dev/sdb1

# チューニング
sudo tune2fs -l /dev/sdb1 # ext4の情報
sudo xfs_info /dev/sdb2 # xfsの情報

コンテナでのファイルシステム

レイヤー構造

┌─────────────────────────────────────────────────────────────┐
│ コンテナのファイルシステム │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Container Layer (Read-Write) │ │
│ │ └── 実行時の変更がここに書き込まれる │ │
│ └─────────────────────────────────────────────────────┘ │
│ ↑ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Image Layer 3: アプリケーション (Read-Only) │ │
│ └─────────────────────────────────────────────────────┘ │
│ ↑ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Image Layer 2: 依存ライブラリ (Read-Only) │ │
│ └─────────────────────────────────────────────────────┘ │
│ ↑ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Image Layer 1: ベースOS (Read-Only) │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘

コンテナのマウント

# ボリュームマウント
docker run -v myvolume:/data alpine

# バインドマウント
docker run -v /host/path:/container/path alpine

# 読み取り専用
docker run -v /config:/app/config:ro alpine

# tmpfs マウント
docker run --tmpfs /tmp alpine

# コンテナ内のマウント確認
docker exec container-name df -h
docker exec container-name mount

まとめ

重要なポイント

  • すべてはファイル(デバイスも)
  • FHSに従ったディレクトリ構造
  • inode がファイルのメタデータを管理
  • マウントでデバイスをディレクトリに接続
  • コンテナはOverlayFSでレイヤー構造を実現

次のステップ


参考リソース