プロセスは落とさずに、プロセスが開いてるファイルハンドルをクローズしたいって事がよくありますよね。どうしましょうか。
サーバとして動いているプロセスがたくさんのファイルを開いているのだけど、一つだけファイルを離して欲しい、ってことよくあるじゃないですか。
たとえば、IBM の Domino サーバ(レガシーかよ)で、"example.nsf" ファイルだけをサーバから切り離したい。でもなぜかサーバがちょっと不調で drop all
で全セッション切ったはずなのに目的の "example.nsf" はサーバが掴んだままで困る。Administrator クライアントからの削除コマンドもきかないのでむりやりクローズしたい。
サーバプロセス落とす、すなわち再起動すれば良いのだけど、他にまだ使ってる人がいっぱいいるから落とすに落とせないってこと普通にあります。
そんなときの最後の手段だよ。 Linuxの場合ね。 ノー保証ね。
まずはファイルを掴んでるプロセスのIDを調べよう。fuser コマンドで。
# fuser /local/notesdata/example.nsf
/local/notesdata/example.nsf:23592
上記の場合、このファイルを開いてるプロセスの PID は 23592 だね。メモしておこう。つぎにこの PID のプロセスが開いてる FD を調べよう。
/proc ファイルシステムの下に PID のディレクトリがあり、配下の fd ディレクトリ内にオープンしてるファイルへのリンクがたっぷり列挙されてる。この中から目的のファイルの FD を調べよう。
# ls -la /proc/23592/fd | grep example.nsf
lrwx------ 1 notes notes 64 1月 18 18:00 2017 204 -> /local/notesdata/example.nsf
上記の場合 204 だね。
じゃあ PID 23592 の FD 204 を閉じよう。
gdb を起動して、以下のようなコマンドで外から無理矢理ファイルクローズができる。
# gdb -p 23592
…いっぱい表示される…
(gdb) p close(204)
…ちょこちょこ表示される…
(gdb) q
Quit anyway? (y or n) y
Detaching from program: /opt/ibm/lotus/notes/latest/linux/server, process 23592
無事ファイルハンドルが閉じられました。プロセスから切り離せました。OS上で削除するなりリネームするなり好き勝手に操作できます。安心しました。