nfs が umount できなかった。kill できないプロセスができちゃった。
えー結論からすると nfs を使ってるときには以下の3点に注意。
1. nfs client 側で umount せずに nfs server が動いているマシンを停止させない。
2. 上記状態になってしまったときに df -k など mount された状態を前提としたコマンドを実行させない。
3. 実行してしまって STAT が D の状態になってしまったプロセスが生まれてしまったらリブートしか解決方法はない。
です。では、何故こんな状態になってしまったか、ポカミスについて備忘録として情報公開です。
まず一番の原因として nfs client の接続を切らずに nfs server が動いているサーバを停止しちゃいました。これが前日にやったこと。バッチ処理で df -k の実行が走りました。
この通りロードアベレージが急上昇しました。df -k によって本来 mount されている nfs server 上のマウントポイントにアクセスできないので、df -k が disk sleep 状態に陥ります。ps aux でみるとこんな感じ。
[root@dev000 root]# ps aux USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND ・・・ root 19242 0.0 0.0 35040 628 ? D 04:02 0:00 df -h ・・・
プロセスの状態が ”D” つまり割り込み不可のスリープ状態になってしまっています。/proc/プロセスID/status で詳細状態を確認できます。
[root@dev000 root]# cat /proc/19242/status Name: df State: D (disk sleep) Tgid: 19242 Pid: 19242 PPid: 19241 TracerPid: 0 Uid: 0 0 0 0 Gid: 0 0 0 0 FDSize: 256 Groups: 0 1 2 3 4 6 10 VmSize: 35040 kB VmLck: 0 kB VmRSS: 628 kB VmData: 160 kB VmStk: 32 kB VmExe: 32 kB VmLib: 2368 kB SigPnd: 0000000000000100 ShdPnd: 0000000000000100 SigBlk: fffffffffffffeff SigIgn: 0000000000000000 SigCgt: 0000000000000000 CapInh: 0000000000000000 CapPrm: 00000000fffffeff CapEff: 00000000fffffeff
STAT が D のプロセスはどうやっても kill できません。というか kill シグナルすら受け取れません。結果 I/O 待ち状態のプロセスになります。ロードアベレージの計算上、実際には全然負荷がかかっていない状態にもかかわらず、ロードアベレージがぐーんと上がった状態になります。これは精神上良くない。
なんてことを調べる前に fuser を実行してファイルやソケットを使用しているプロセスを特定しようとしたら更にプロセスがささってしまう。その時点でロードアベレージは計算上更にあがることに・・・なので2段階に上昇になっています。
[root@dev000 root]# ps aux USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND ・・・ root 13569 0.0 0.0 41184 1580 ? D 11:34 0:00 -bash root 15465 0.0 0.0 35028 448 ? D 11:42 0:00 fuser -v /mnt/dev001 ・・・ [root@dev000 root]# cat /proc/15465/status Name: fuser State: D (disk sleep) Tgid: 15465 Pid: 15465 PPid: 1 TracerPid: 0 Uid: 0 0 0 0 Gid: 0 0 0 0 FDSize: 256 Groups: 0 1 2 3 4 6 10 VmSize: 35028 kB VmLck: 0 kB VmRSS: 448 kB VmData: 156 kB VmStk: 36 kB VmExe: 20 kB VmLib: 2368 kB SigPnd: 0000000000000100 ShdPnd: 0000000000020103 SigBlk: fffffffffffffeff SigIgn: 0000000000000000 SigCgt: 0000000000000000 CapInh: 0000000000000000 CapPrm: 00000000fffffeff CapEff: 00000000fffffeff
結局、割り込み不可のスリープ状態のプロセスを正常な状態に戻すにはサーバのリブートしか選択肢はありませんでした。
リブートする前に、あれこれ試してみました。
まず umount について。nfs client 側で umount せずに nfs server が動いているマシンを停止すると umount -f も効かない。
umount -f /mnt/dev001 Cannot MOUNTPROG RPC: RPC: ポートマッパーの失敗です - RPC: 受け取れません umount2: デバイスもしくはリソースがビジー状態です umount: /mnt/dev001: デバイスを使用中です [root@dev000 root]# mount /dev/sda2 on / type ext3 (rw) none on /proc type proc (rw) none on /dev/pts type devpts (rw,gid=5,mode=620) usbdevfs on /proc/bus/usb type usbdevfs (rw) /dev/sda1 on /boot type ext3 (rw) none on /dev/shm type tmpfs (rw) devweb:/usr/local/src/share on /mnt/dev001 type nfs
どうやらこんな時には umount -l が有効のようです。エラーは出力されるものの、一応 umount されるみたい。
umount -l /mnt/dev001 [root@dev000 root]# umount -l /mnt/dev001 Cannot MOUNTPROG RPC: RPC: ポートマッパーの失敗です - RPC: タイムアウトしました [root@dev000 root]# mount /dev/sda2 on / type ext3 (rw) none on /proc type proc (rw) none on /dev/pts type devpts (rw,gid=5,mode=620) usbdevfs on /proc/bus/usb type usbdevfs (rw) /dev/sda1 on /boot type ext3 (rw) none on /dev/shm type tmpfs (rw)
linux を長年扱ってきましたが、こんなポカミスをしてしまったのは初めてなので STAT が D で刺さってしまったときの対応について初めて学習しました。もう一度(自分に対して)言いますが nfs を使っている場合の注意点。
1. nfs client 側で umount せずに nfs server が動いているマシンを停止させない。
2. 上記状態になってしまったときに df -k など mount された状態を前提としたコマンドを実行させない。
3. 実行してしまって STAT が D の状態になってしまったプロセスが生まれてしまったらリブートしか解決方法はない。
コメントやシェアをお願いします!