コンテナから参照しているファイルがVim編集後に追従しない原因を調べた(inode差分)

コンテナから参照しているファイルがVim編集後に追従しない原因を調べた(inode差分)

背景

ホスト側のファイルをコンテナから参照する構成で作業していた際、ホストで vim により編集・保存した直後に、参照側(コンテナ側)が更新内容を期待通りに拾えない事象がありました。
切り分けのために inode を確認したところ、vim 保存後に inode 番号が変わっていることを確認できました。一方で cat > file による上書きでは inode が変わらず、同一 inode のまま内容が更新される挙動でした。

なぜVimはinodeを変えることがあるのか

Vim の保存時の挙動は backupcopy オプション(auto/yes/no)によって決まります。

  • no(新規作成方式): 新しいファイルを作成 → 元のファイルをバックアップとしてリネーム → 新ファイルを元のファイル名にリネーム。この場合 inode が変わる
  • yes(上書き方式): 元のファイルを直接上書き。inode は変わらない
  • auto(デフォルト): ファイルの状態(ハードリンク・シンボリックリンクの有無、所有者など)を見て yesno を自動選択。

今回の検証では backupcopy=auto の環境で inode が変化したため、Vim が no 相当の動作を選択したと考えられます。

なぜコンテナ側で追従しないのか

inode が変わると、以下のような仕組みで「追従しない」事象が起きる可能性があります。

  • bind mount: ホスト側のディレクトリをマウントしている場合、パス経由のアクセスは通常追従する。ただし、コンテナ内プロセスが起動時にファイルを開いたままの場合、古い inode(=古いファイル実体)を参照し続ける。
  • ファイルディスクリプタ(FD): プロセスがファイルを開くと FD は inode に紐づく。inode が変わると、開いたままの FD は古い内容を指し続ける。
  • inotify: ファイル監視が inode ベースで行われている場合、inode が変わると監視対象から外れ、変更イベントを受け取れなくなる。

今回のケースでは、これらのいずれか(または複合)が原因と推測されます。


inodeの確認方法

inode は ls -li または stat で確認できます。

# inode を表示(先頭の数字が inode)
ls -li target.conf

# inode を明示的に表示(確実)
stat -c 'inode=%i  size=%s  mtime=%y  path=%n' target.conf

検証手順

検証用ファイル target.conf を作成し、以下の順で inode を比較しました。

  1. 編集前の inode を確認
  2. vim で編集して保存し、inode を再確認
  3. cat > target.conf で上書きし、inode を再確認

実行ログ(重要部分のみ抜粋)

1) 初期状態(作成直後)

$ ls -li target.conf
31468393 -rw-r--r-- 1 root root 24 Feb  1 10:08 target.conf

$ stat -c 'inode=%i  size=%s  mtime=%y  path=%n' target.conf
inode=31468393  size=24  mtime=2026-02-01 10:08:40.782008816 +0000  path=target.conf

2) Vimで編集・保存後(inodeが変化)

$ ls -li target.conf
31468395 -rw-r--r-- 1 root root 24 Feb  1 10:10 target.conf

$ stat -c 'inode=%i path=%n' target.conf
inode=31468395 path=target.conf

(内容確認)

$ cat target.conf
line1=after
line2=keep

3) catで上書き後(inodeは変わらない)

$ stat -c 'inode=%i path=%n' target.conf
inode=31468395 path=target.conf

$ cat > target.conf <<'EOF'
line1=written-by-cat
line2=keep
EOF

$ stat -c 'inode=%i path=%n' target.conf
inode=31468395 path=target.conf

(内容確認)

$ cat target.conf
line1=written-by-cat
line2=keep

まとめ

  • 本検証では、vim で編集・保存したあとに inode が 31468393 → 31468395 に変化しました。
  • 一方、cat > target.conf による上書きでは inode は 31468395 のままで、内容のみ更新されました。
  • ファイルパスが同じでも、編集方法によっては「同一 inode の更新」ではなく「別 inode のファイルへの置き換え」が起きる場合があります。
    参照・監視方式によっては inode を追跡していることがあるため、コンテナやファイル監視が絡む場合は注意が必要だと学びました。

対処法

Vim で inode を維持したまま保存したい場合は、以下の設定を .vimrc に追加します。

set backupcopy=yes

この設定により、Vim は「元のファイルを直接上書き」する方式で保存するようになり、inode が変わらなくなります。ただし、保存中のクラッシュ時にファイルが壊れるリスクがあるため、用途に応じて使い分けてください。

Last modified: 2026-02-01

Author