某些 linux 版本中 netstat 的 bug

之前在 SLES 11 SP2 上观察到 netstat -lntp 时,PID 一列有部分进程显示为 – 。

# netstat -lntp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:42659           0.0.0.0:*               LISTEN      32555/rpc.statd
tcp        0      0 0.0.0.0:4996            0.0.0.0:*               LISTEN      -
tcp        0      0 0.0.0.0:4998            0.0.0.0:*               LISTEN      -
tcp        0      0 0.0.0.0:4999            0.0.0.0:*               LISTEN      -
tcp        0      0 0.0.0.0:111             0.0.0.0:*               LISTEN      2095/rpcbind
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      2445/sshd
tcp        0      0 :::111                  :::*                    LISTEN      2095/rpcbind
tcp        0      0 :::9010                 :::*                    LISTEN      26369/java
tcp        0      0 :::22                   :::*                    LISTEN      2445/sshd
tcp        0      0 ::1:631                 :::*                    LISTEN      2457/cupsd
tcp        0      0 ::1:25                  :::*                    LISTEN      2559/master
tcp        0      0 :::57626                :::*                    LISTEN      32555/rpc.statd

因为是以 root 用户运行的,显然与权限无关。经过 google,发现这是 net-tools 包的一个 bug。当Socket id 大于 2^31 时,会造成无法显示进程信息。这个 bug 不仅仅存在于 SUSE。如:

https://bugs.launchpad.net/ubuntu/+source/net-tools/+bug/1015026
http://lists.alioth.debian.org/pipermail/pkg-net-tools-maintainers/2009-March/000075.html

如果无法通过升级解决,还可以用一个替代命令来查看哪些端口被那个进程使用。

# lsof -n -P -i TCP | gawk '$10=="(LISTEN)"'
rpcbind    2095    root    8u  IPv4     4766      0t0  TCP *:111 (LISTEN)
rpcbind    2095    root   11u  IPv6     4771      0t0  TCP *:111 (LISTEN)
mysqld     2168 demo3ad   13u  IPv4 13203151      0t0  TCP *:4996 (LISTEN)
sshd       2445    root    3u  IPv4     4868      0t0  TCP *:22 (LISTEN)
sshd       2445    root    4u  IPv6     4870      0t0  TCP *:22 (LISTEN)
cupsd      2457    root    1u  IPv6     6482      0t0  TCP [::1]:631 (LISTEN)
master     2559    root   12u  IPv6     7254      0t0  TCP [::1]:25 (LISTEN)
mysqld    12060 demo1ad   13u  IPv4  6956029      0t0  TCP *:4999 (LISTEN)
mysqld    23358 test1ad   13u  IPv4  6967097      0t0  TCP *:4998 (LISTEN)
java      26369    root   55u  IPv6  4321975      0t0  TCP *:9010 (LISTEN)
rpc.statd 32555    root    9u  IPv4   339698      0t0  TCP *:42659 (LISTEN)
rpc.statd 32555    root   11u  IPv6   339706      0t0  TCP *:57626 (LISTEN)

如果需要增加过滤条件,也可以直接在 gawk 中进行如

# lsof -n -P -i TCP | gawk '$1=="mysqld" && $10=="(LISTEN)"'

清理未正确删除的逻辑卷

最近在一个项目中用到了光存储设备,服务器使用多路径软件实现高可用和负载均衡,并在路径合并后的块设备上使用 LVM 来管理。

有一回因为存储设备上的逻辑单元(LU)先删除了,服务器上的逻辑卷就无法再用 lvremove 之类命令删除了,就连 lvs 之类命令也会卡死。于是就直接删除了那些逻辑卷对应的块设备文件。结果是,用 lvs、vgs、pvs 等命令都已经无法看到逻辑卷,似乎是正常了,但是多路径软件却无法删除设备,认为该设备仍然在使用中。说明这样的删除操作是不对的,还留下了些不干净的东西。但是用 LVM 相关命令已经找不到任何东西了。想到 LVM 是通过 device mapper 实现的,那么用 device mapper 相关的命令也许能看出点啥。

于是试试 dmsetup ls ,果然看到了之前那个没删干净的逻辑卷

# dmsetup ls
lv_demo1dat       (253, 8)
...
...

用 dmsetup remove lv_demo1dat 把它干掉,之后就一切正常了。