LoginSignup
17
13

More than 5 years have passed since last update.

cpとmvとinodeの話

Posted at

実行中のファイルに対して、
cpで上書きする場合だと、Text file busyで置き換えられず、
mvだと何も聞かれず置き換えられます。

この挙動の違いについて、まとめと実験。

inodeを見ると、それとなく分かります。

以下引用

リンクを全く持たない inode もありうる。
通常そのようなファイルはディスクから削除され、
そのリソース(ディスクブロック)はファイル削除処理の過程で
再利用のために解放されるが、何らかのプロセスが
そのファイルを使用中ならば、アクセスし続けることができ、
最後にクローズされるときに削除処理が行われる。

このため、プログラムを改版(リコンパイル)するときは、
以前の実行ファイルをまず削除して、新しい版の実行ファイルは
新たな inode で作成されるようにすることが推奨される。
これにより、古い版が実行中であっても何ら問題なく処理を続行することになる。

(訳注:削除しないで上書きすると、実行中の実行ファイルが書き換えられるため、
メモリ管理の実装によってはおかしな状態が発生する)。

引用終わり

つまり、
以下のファイルがあるとして。

・/sa/sbin/org_exec inode=100 inodeの中身=abc
・/sa/sbin/new_exec inode=200 inodeの中身=123

cp /sa/sbin/new_exec /sa/sbin/org_exec

とした場合、inode=100の内容を、
inode=200の内容で上書きするので、
以下のようになる。

・/sa/sbin/org_exec inode=100 inodeの中身=123
・/sa/sbin/new_exec inode=200 inodeの中身=123

org_execを使っている人は、突然abcが123になって、
なんぞ?っとなる。そしてcpコマンドは、こうなるとまずいので、
Text file busyを出して、失敗にする。

mv /sa/sbin/new_exec /sa/sbin/org_exec

とした場合、/sa/sbin/org_exec inode=200となり、
inode=100は、何もファイルパスを指さない状態となるだけになる。

・ファイルパスは無い inode=100 inodeの中身=abc
・/sa/sbin/org_exec inode=200 inodeの中身=123
・/sa/sbin/new_execは無くなった状態になる(org_execにmvしているので)

inode=100はファイルパスはなくなるが、inodeの中身は変わっていないので、
現状誰かが使用していたとしても、問題なくabc、という中身を見ることができる。
なので、実行中のファイルに、別のファイルをmvしても問題ないので、
mvは成功する。

そして、inode=100の内容は、それを使っているプロセスが
ファイルをクローズすれば再利用可能な状態に戻る。

以下、実際にやってみた結果。
cpだとエラーがでて失敗し、
mvは成功している。

mvはinodeの内容自体は変えず、
inodeとファイルパスの関連を変えているだけ、
というのが分かるはず。

そしてmvした後も、a.exeは動き続けている。
ただしこれは、mvする前の状態のa.exeである点に
注意が必要。

[root@localhost ~]#
[root@localhost ~]# stat a.exe
File: a.exe'
Size: 6777 Blocks: 16 IO Block: 4096 regular file
Device: 802h/2050d Inode: 790530 Links: 1
Access: (0755/-rwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2015-09-09 13:14:19.642295609 +0900
Modify: 2015-09-09 13:14:18.178283786 +0900
Change: 2015-09-09 13:14:18.178283786 +0900
[root@localhost ~]#
[root@localhost ~]#
[root@localhost ~]#
[root@localhost ~]# stat b.exe
File:
b.exe'
Size: 6800 Blocks: 16 IO Block: 4096 regular file
Device: 802h/2050d Inode: 790537 Links: 1
Access: (0755/-rwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2015-09-09 13:16:20.022259845 +0900
Modify: 2015-09-09 13:16:17.200237245 +0900
Change: 2015-09-09 13:16:17.200237245 +0900
[root@localhost ~]#
[root@localhost ~]#
[root@localhost ~]#
[root@localhost ~]# ./a.exe &
[1] 21205
[root@localhost ~]#
[root@localhost ~]#
[root@localhost ~]#
[root@localhost ~]# cp b.exe a.exe
cp: overwrite a.exe'? y
cp: cannot create regular file
a.exe': Text file busy
[root@localhost ~]#
[root@localhost ~]#
[root@localhost ~]#
[root@localhost ~]# mv b.exe a.exe
mv: overwrite a.exe'? y
[root@localhost ~]#
[root@localhost ~]#
[root@localhost ~]#
[root@localhost ~]# stat a.exe
File:
a.exe'
Size: 6800 Blocks: 16 IO Block: 4096 regular file
Device: 802h/2050d Inode: 790537 Links: 1
Access: (0755/-rwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2015-09-09 13:16:20.022259845 +0900
Modify: 2015-09-09 13:16:17.200237245 +0900
Change: 2015-09-09 13:17:12.565688924 +0900
[root@localhost ~]#
[root@localhost ~]#
[root@localhost ~]# ps aux | grep a.exe
root 21205 0.0 0.0 11736 828 pts/0 S 13:16 0:00 ./a.exe
root 31922 0.0 0.0 103304 884 pts/0 S+ 13:54 0:00 grep a.exe

間違い等あれば、指摘ください。。

17
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
13