inode番号の変化の挙動を確認してみた。


はじめに

実行中のスクリプトに対して更新処理を行ったところ想定外の処理が発生して、ファイルシステム上のデータが消失するといった事故があったので、改めてinodeの挙動を確認した結果を纏めました。
inodeに関する挙動については知りたい方は参考サイトに載せたサイトをご覧ください。

環境

Ubuntu20.04で動作を確認しましたが、他のLinux OSでも大差ないと思っています。
ちなみにUbuntu20.04は、MacOS上でVagrant+VirtualBoxを利用して立ち上げています。

確認結果

cpコマンド、mvコマンドを中心に実行結果を記載します。
なお、ファイルの配置状況は以下のようになっています。

vagrant@ubuntu2004:~$ ls -li
total 8
70233 -rw-rw-r-- 1 vagrant vagrant 7 Dec 29 15:02 test01.txt
70089 -rw-rw-r-- 1 vagrant vagrant 7 Dec 29 15:02 test02.txt

1. cpコマンドによる単純コピー

cpコマンドでtest01.txtをコピーして、test03.txtファイルを作成します。

vagrant@ubuntu2004:~$ ls -li
total 12
70233 -rw-rw-r-- 1 vagrant vagrant 7 Dec 29 15:02 test01.txt
70089 -rw-rw-r-- 1 vagrant vagrant 7 Dec 29 15:02 test02.txt
19210 -rw-rw-r-- 1 vagrant vagrant 7 Dec 29 15:04 test03.txt

当然ですが、test03.txtのinode(19210)は、test01.txtのinode(70233)と違う値となります。

2. cpコマンドによるファイルの上書き

cpコマンドでtest01.txtをtest02.txtに上書きします。

vagrant@ubuntu2004:~$ cp test01.txt test02.txt 
vagrant@ubuntu2004:~$ ls -li
total 12
70233 -rw-rw-r-- 1 vagrant vagrant 7 Dec 29 15:02 test01.txt
70089 -rw-rw-r-- 1 vagrant vagrant 7 Dec 29 15:05 test02.txt
19210 -rw-rw-r-- 1 vagrant vagrant 7 Dec 29 15:04 test03.txt

実行の結果、test02.txtのinode(70089)は変化しません。
同じinodeですが、ファイルの中身は変更されている状態となります。
実行中のスクリプトに対して、cpコマンドでファイルを上書きすると、実行中のスクリプトの動作が変更されますので注意が必要です。

3. mvコマンドによるファイルの上書き

mvコマンドでtest01.txtをtest03.txtに上書きします。

vagrant@ubuntu2004:~$ ls -li
total 8
70089 -rw-rw-r-- 1 vagrant vagrant 7 Dec 29 15:05 test02.txt
70233 -rw-rw-r-- 1 vagrant vagrant 7 Dec 29 15:02 test03.txt

実行の結果、test03.txtのinodeはtest01.txtのinode(70233)を引き継ぐ形となります。
上書き前のtest03.txtのinode(19210)から変化するため、スクリプトが実行中の間は上書き後のファイル(inode:70233)を読み込むことはありません。
これはディレクトリエントリからtest03.txt(inode:19210)をアンリンクするだけで、実行中のスクリプト自体は残っているためです。もし実行中のスクリプトをどうしてもファイルの上書き変更したい場合は、mvコマンドを使う方法が安全だと思われます。
なお、スクリプトの実行が終了した状態で他のプロセス等からも参照されていない状態となったら元のファイルが削除されます。

4. mvコマンドによるファイルリネーム

mvコマンドでtest02.txtをtest04.txtにリネームします。

vagrant@ubuntu2004:~$ mv test02.txt test04.txt
vagrant@ubuntu2004:~$ ls -li
total 8
70233 -rw-rw-r-- 1 vagrant vagrant 7 Dec 29 15:02 test03.txt
70089 -rw-rw-r-- 1 vagrant vagrant 7 Dec 29 15:05 test04.txt

実行の結果、test02.txtのinode(70089)は変化しません。

5. vimコマンドによるファイル内容の変更

vimコマンドでtest03.txtの内容を変更して、保存します。

vagrant@ubuntu2004:~$ vim test03.txt
vagrant@ubuntu2004:~$ ls -li
total 8
70234 -rw-rw-r-- 1 vagrant vagrant 14 Dec 29 15:10 test03.txt
70089 -rw-rw-r-- 1 vagrant vagrant  7 Dec 29 15:05 test04.txt

実行の結果、test03.txtのinodeは変化します(70233→70234)。
これはvimが一旦別で書き出した後、リネームしてファイルを上書きするためだと思われます。
そのため、ちょっとした変更だけなら実行中のスクリプトをvimコマンドで修正しても問題ないと思われます。
もしinodeを使い回したい場合は、backupcopyをyesに設定すれば良いと思います。

6. rsyncコマンドによるファイルの上書き

rsyncコマンドでtest03.txtをtest04.txtに上書きします。

vagrant@ubuntu2004:~$ rsync test03.txt test04.txt 
vagrant@ubuntu2004:~$ ls -li
total 8
70234 -rw-rw-r-- 1 vagrant vagrant 14 Dec 29 15:10 test03.txt
69766 -rw-rw-r-- 1 vagrant vagrant 14 Dec 29 15:34 test04.txt

実行の結果、test04.txtのinodeは変化します(70089→69766)。
test03.txtのinodeとは全く違った新しいinodeがtest04.txtに振られています。
あまりrsyncでファイルを上書きすることはないかもしれませんが、mvコマンド以外にも実行中のスクリプトを上書きする方法があることは覚えておいてもいいのかなと思っています。

まとめ

確認結果を以下に纏めます。

# 処理 inodeの状態
1 cpコマンドによる単純コピー 新規inodeが割り当てられる
2 cpコマンドによるファイル上書き inodeは変化しない
3 mvコマンドによるファイル上書き 元ファイルのinodeを引き継ぐ
4 mvコマンドによるファイルリネーム inodeは変化しない
5 vimコマンドによる内容変更 inodeは変化する(新規inodeを割り当て)
6 rsyncコマンドによるファイル上書き 新規inodeが割り当てられる

実行中のスクリプトを変更する必要が出てきた場合は、cpコマンドによるファイル上書きだけは避けましょう。

参考サイト

inodeから見たmvやcpの動き