はじめに
lsofはプロセスがアクセスしているファイル(デバイス、ポートも含む)を表示するコマンドです。今回はlsofによるロック用ファイルを開放しないプロセスの調査方法を記載します。
環境:CentOS7.5
準備
疑似的にロック用ファイルを掴んだ状態を作成します。
今回はLVMのロック用ファイルを対象に排他ロックを掛けます。
flock -x [ロックファイル名] [コマンド名]
[root@localhost]# flock -x /run/lock/lvm/V_centos vgs
File descriptor 3 (/run/lock/lvm/V_centos) leaked on vgs invocation. Parent PID 17262: flock
この状態で別コンソールを開き、lvm参照系のコマンドを打つとlvmのロックファイルを掴めないため、応答が返ってこなくなります。
[root@localhost]# vgdisplay
(応答がない状態)
調査方法
まずは応答が返ってこないコマンドがアクセスしているファイルを調べます。
lsof -c [コマンド名]
[root@localhost]# lsof -c vgdisplay
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
vgdisplay 17306 root cwd DIR 0,3 0 319244 /proc/16275 (deleted)
vgdisplay 17306 root rtd DIR 253,0 224 64 /
vgdisplay 17306 root txt REG 253,0 2174664 325504 /usr/sbin/lvm
vgdisplay 17306 root mem REG 253,0 106070960 25393963 /usr/lib/locale/locale-archive
vgdisplay 17306 root mem REG 253,0 402384 48206 /usr/lib64/libpcre.so.1.2.0
vgdisplay 17306 root mem REG 253,0 68192 48344 /usr/lib64/libbz2.so.1.0.6
vgdisplay 17306 root mem REG 253,0 157424 48334 /usr/lib64/liblzma.so.5.2.2
vgdisplay 17306 root mem REG 253,0 90664 48129 /usr/lib64/libz.so.1.2.7
vgdisplay 17306 root mem REG 253,0 99944 48351 /usr/lib64/libelf-0.170.so
vgdisplay 17306 root mem REG 253,0 19896 48186 /usr/lib64/libattr.so.1.1.0
vgdisplay 17306 root mem REG 253,0 174576 48174 /usr/lib64/libtinfo.so.5.9
vgdisplay 17306 root mem REG 253,0 660136 48185 /usr/lib64/libsepol.so.1
vgdisplay 17306 root mem REG 253,0 155784 48205 /usr/lib64/libselinux.so.1
vgdisplay 17306 root mem REG 253,0 20112 48341 /usr/lib64/libuuid.so.1.3.0
vgdisplay 17306 root mem REG 253,0 88720 84 /usr/lib64/libgcc_s-4.8.5-20150702.so.1
vgdisplay 17306 root mem REG 253,0 297360 253772 /usr/lib64/libdw-0.170.so
vgdisplay 17306 root mem REG 253,0 1139680 12122 /usr/lib64/libm-2.17.so
vgdisplay 17306 root mem REG 253,0 20032 48191 /usr/lib64/libcap.so.2.22
vgdisplay 17306 root mem REG 253,0 44448 12144 /usr/lib64/librt-2.17.so
vgdisplay 17306 root mem REG 253,0 144792 12140 /usr/lib64/libpthread-2.17.so
vgdisplay 17306 root mem REG 253,0 2173512 12114 /usr/lib64/libc-2.17.so
vgdisplay 17306 root mem REG 253,0 285240 48352 /usr/lib64/libreadline.so.6.2
vgdisplay 17306 root mem REG 253,0 356120 253766 /usr/lib64/libdevmapper.so.1.02
vgdisplay 17306 root mem REG 253,0 261456 48343 /usr/lib64/libblkid.so.1.1.0
vgdisplay 17306 root mem REG 253,0 19776 12120 /usr/lib64/libdl-2.17.so
vgdisplay 17306 root mem REG 253,0 91256 253789 /usr/lib64/libudev.so.1.6.2
vgdisplay 17306 root mem REG 253,0 24200 287071 /usr/lib64/libdevmapper-event.so.1.02
vgdisplay 17306 root mem REG 253,0 164240 12107 /usr/lib64/ld-2.17.so
vgdisplay 17306 root mem REG 253,0 43245 372129 /etc/selinux/targeted/contexts/files/file_contexts.homedirs.bin
vgdisplay 17306 root mem REG 253,0 1357405 372127 /etc/selinux/targeted/contexts/files/file_contexts.bin
vgdisplay 17306 root 0u CHR 136,1 0t0 4 /dev/pts/1
vgdisplay 17306 root 1u CHR 136,1 0t0 4 /dev/pts/1
vgdisplay 17306 root 2u CHR 136,1 0t0 4 /dev/pts/1
vgdisplay 17306 root 3u unix 0xffff95b5a926e400 0t0 326725 socket
vgdisplay 17306 root 4u REG 0,19 0 325511 /run/lock/lvm/V_centos
[root@localhost]#
最終行で/run/lock/lvm/V_centos
を読み書き状態で掴みにいっているのが確認できます。
次に/run/lock/lvm/V_centosを掴んでいるプロセスを特定します。
lsof [ファイル名]
[root@localhost]# lsof /run/lock/lvm/V_centos
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
flock 17262 root 3rW REG 0,19 0 325511 /run/lock/lvm/V_centos
vgs 17263 root 4u REG 0,19 0 325511 /run/lock/lvm/V_centos
vgdisplay 17306 root 4u REG 0,19 0 325511 /run/lock/lvm/V_centos
flockが/run/lock/lvm/V_centos
に対して書き込みロック(W)を掛けていることが判りました。
解消したい場合は、対象プロセスをkillしてやればOKです。
kill -9 17262
プロセスをkillすると応答の無かったvgdisplayから応答が返ってくることが確認できます。
[root@localhost]# vgdisplay
--- Volume group ---
VG Name centos
System ID
Format lvm2
Metadata Areas 1
Metadata Sequence No 3
VG Access read/write
VG Status resizable
MAX LV 0
Cur LV 2
Open LV 2
Max PV 0
Cur PV 1
Act PV 1
VG Size 11.60 GiB
PE Size 4.00 MiB
Total PE 2970
Alloc PE / Size 2970 / 11.60 GiB
Free PE / Size 0 / 0
VG UUID XHFQp5-AH24-zrb9-J21A-1lvf-cTlc-moUSXI
補足
/proc/[プロセスID]/stackを確認することで対象プロセスの内部動作を確認することも可能。
[root@localhost]# cat /proc/17262/stack
[<ffffffff8ba97176>] do_wait+0x1f6/0x260
[<ffffffff8ba98290>] SyS_wait4+0x80/0x110
[<ffffffff8c11f7d5>] system_call_fastpath+0x1c/0x21
[<ffffffffffffffff>] 0xffffffffffffffff
[root@localhost]# cat /proc/17263/stack
[<ffffffff8bc770d5>] flock_lock_inode_wait+0x1a5/0x310
[<ffffffff8bc7725e>] locks_lock_inode_wait+0x1e/0x40
[<ffffffff8bc78140>] SyS_flock+0x1d0/0x1f0
[<ffffffff8c11f7d5>] system_call_fastpath+0x1c/0x21
[<ffffffffffffffff>] 0xffffffffffffffff
[root@localhost]# cat /proc/17306/stack
[<ffffffff8bc770d5>] flock_lock_inode_wait+0x1a5/0x310
[<ffffffff8bc7725e>] locks_lock_inode_wait+0x1e/0x40
[<ffffffff8bc78140>] SyS_flock+0x1d0/0x1f0
[<ffffffff8c11f7d5>] system_call_fastpath+0x1c/0x21
[<ffffffffffffffff>] 0xffffffffffffffff
以上