4月
09
flock(1) というコマンドがあります。flock(2) を使い、コマンドを排他制御して実行します。
$ flock /path/to/lockfile command...
これで lockfile をロックファイルとしてコマンドを排他制御実行します。
これが「普通の」使い方なわけですが、もう1つ、 Linux だとファイルディスクリプタ番号を指定する使い方があります(Linux 以外で使えるかどうかは調べてない)
#!/bin/sh ( flock 100 command... ) 100>>/path/to/lockfile
これも lockfile を ロックファイルとして後続のコマンド群(丸かっこで囲った部分)を排他制御実行します。実際には
#!/bin/sh exec {LOCKFD}>>/path/to/lockfile flock $LOCKFD command...
などとして空いているファイルディスクリプタ番号をカーネルに選ばせる方が安全ですが。
ともあれ、こっちの方が柔軟性がある(たとえばスクリプトの途中でアンロックすることもできる)わけですが、これ flock はロックに成功したらすぐ返ってくる(そうでないと後続のコマンドが実行できない)わけで、なんでそれで排他制御できているのか5分ほど悩みました。
なんで排他制御できるのかというと、
- flock を実行する際、ファイルディスクリプタテーブルはコピーされる。上記のスクリプトで言う 100 番は恐らく close on exec フラグは立ってないので、子プロセスである flock にも継承される。
- flock が 100 番をロックする。この時、ロックはファイルディスクリプタ番号自体ではなく、ファイルディスクリプタが指すカーネル内の構造に対してかかるため、親プロセスとロック所有権を共有している形になる。
- flock が終了し、親プロセス(だけ)がロックを持っている状態になる。
という原理です。
しかし最近シェルスクリプト書いてないな(ワンライナーならそれなりに書いてるけど)。
no comment untill now