现网使用的teastore主机,经业务侧同事反馈通过lsof -i:port进行查看时,耗时非常长,需要支撑定位解决。问题不算是大问题,这里想把lsof 、netstat、ss三个指令串一下,三个指令都可以查看具体某个端口是由什么进程引用。

一、查看所有监听端口信息

三个指令可以通过以下命令实现,功能上一样的:

 1#netstat指令
 2[root@361way.com ~]# netstat -ntlp
 3Active Internet connections (only servers)
 4Proto Recv-Q Send-Q Local Address               Foreign Address             State       PID/Program name
 5tcp        0      0 0.0.0.0:22                  0.0.0.0:*                   LISTEN      11155/sshd
 6tcp        0      0 0.0.0.0:9000                0.0.0.0:*                   LISTEN      6925/hhvm
 7tcp        0      0 0.0.0.0:3306                0.0.0.0:*                   LISTEN      27967/mysqld
 8tcp        0      0 0.0.0.0:80                  0.0.0.0:*                   LISTEN      20211/nginx
 9#ss指令
10[root@361way.com ~]# ss -nlp|column  -t
11State   Recv-Q  Send-Q  Local   Address:Port  Peer                                                           Address:Port
12LISTEN  0       128     *:22    *:*           users:(("sshd",11155,3))
13LISTEN  0       128     *:9000  *:*           users:(("hhvm",6925,17))
14LISTEN  0       20      *:3306  *:*           users:(("mysqld",27967,10))
15LISTEN  0       128     *:80    *:*           users:(("nginx",20211,9),("nginx",20212,9),("nginx",26283,9))
16#lsof指令
17[root@361way.com ~]# lsof -n -P -i           //这里的-p 、 -n是不进行端口和主机反解析,加快结果输出
18COMMAND     PID  USER   FD   TYPE  DEVICE SIZE/OFF NODE NAME
19ntpd        942   ntp   16u  IPv4    8787      0t0  UDP *:123
20ntpd        942   ntp   17u  IPv4    8791      0t0  UDP 127.0.0.1:123
21ntpd        942   ntp   18u  IPv4    8792      0t0  UDP 10.144.189.71:123
22ntpd        942   ntp   19u  IPv4    8793      0t0  UDP 115.28.174.118:123
23hhvm       6925   www   17u  IPv4 8260921      0t0  TCP *:9000 (LISTEN)
24sshd      11155  root    3u  IPv4 5066078      0t0  TCP *:22 (LISTEN)
25sshd      11222  root    3r  IPv4 8346107      0t0  TCP 115.28.174.118:22->219.82.250.218:53236 (ESTABLISHED)
26AliYunDun 13220  root   22u  IPv4 7505729      0t0  TCP 115.28.174.118:60716->140.205.140.205:80 (ESTABLISHED)
27nginx     20211   www    9u  IPv4 6731567      0t0  TCP *:80 (LISTEN)
28nginx     20212   www    9u  IPv4 6731567      0t0  TCP *:80 (LISTEN)
29nginx     26283  root    9u  IPv4 6731567      0t0  TCP *:80 (LISTEN)
30mysqld    27967 mysql   10u  IPv4  770634      0t0  TCP *:3306 (LISTEN)

注:lsof 的协议区分和另个两个不同,lsof是通过-i 参数加protocol 进行指定tcp\udp ,不像netstat和ss 通过-t (tcp)、-u (udp)参数进行指定。所以后面一条lsof 的用法相当于ss -nlutp|column -t (column指令只是为了格式化对齐,看起来更整洁) 和 netstat -nutlp 效果是一样的。

二、lsof -i 功能的实现

上面其实是一点题外话,这里看问题分析。业务侧使用的指令lsof -i:9160 | grep LISTEN ,通过执行确实有4-5分钟左右的时间才有结果(具体需要时可以加 time指令获取时间)。最初想到的可能是连接数过多,因为lsof命令执行的时候会遍历所有打开的文件和服务后再过滤相应的端口,在连接数较多或服务进程过多时处理比较耗时。通过ss 指令查看,发现连接数只几千个,并不多。

1[root@361way.com ~]# ss '( sport = :9160 or sport = :9160 )' |wc -l
28650
3[root@361way.com ~]# ss -a|wc -l
48700

1、netstat指令查看占用某端口的进程

1[root@361way.com ~]# time netstat -ntlp|grep 9160
2tcp        0      0 192.168.21.37:9160      0.0.0.0:*               LISTEN      28894/java
3real    0m0.264s
4user    0m0.004s
5sys     0m0.256s

注:为了便于时间分析,我指令前加了time 统计耗时,发现执行很快。

2、lsof -i 执行的问题

连接数这么少,lsof指令查看也不可能占用这么长时间啊,先优化下先,使用如下命令执行:

1# time lsof -n -P -i :9160|grep LISTEN
2java 28894 ts_up 563u IPv4 608029736 0t0 TCP 192.168.21.37:9160 (LISTEN)
3real 0m0.364s
4user 0m0.128s
5sys 0m0.236s

很快执行出了结果,相对之前的4-5分钟确实快了N倍,问题出在哪里?lsof -i:port命令执行时间会长是因为,其会尝试进行反解析,将主机转化为主机名(域名),将端口转化为对应的服务,当然耗时了。所以平时查询时,最好加上-n -P参数。

3、ss指令使用的问题

在对网络服务连接状况上,三者之间最好的工具是ss --- 因为其执行速度最快,条件过滤丰富(但也有缺点,输出不美观,需column再格式化),为什么把这个指令放在最后,是有原因的。因为最初通过ss 实现lsof -i:port功能时,发现未能有想要的结果输出。如下:

1[root@361way.com ~]# ss -lp|grep 9160
2[root@361way.com ~]# ss -ap|grep 9160
3[root@361way.com ~]# ss '( sport = :9160 or sport = :9160 )'|more
4State      Recv-Q Send-Q      Local Address:Port          Peer Address:Port
5ESTAB      0      0           192.168.21.37:apani1       192.168.17.74:58108
6ESTAB      0      0           192.168.21.37:apani1       192.168.17.82:46564
7………………………………

有没有发现问题,grep时,发现查询不到9160端口,通过指定端口查看连接时,发现又有连接。为什么呢?其实同样是IP反解析域名、端口反解析成服务出的问题,这里本该显示为端口9160的地方显示成了apani1,通过查看services文件发现如下:

1# cat /etc/services |grep 9160
2apani1             9160/tcp     # apani1  [Neal_Taylor]
3apani1             9160/udp     # apani1  [Neal_Taylor]

取消端口转换为服务名后,执行结果如下:

1# time ss -lnp|grep 9160
20      50                 192.168.21.37:9160                          *:*      users:(("java",28894,563))
3real    0m0.284s
4user    0m0.088s
5sys     0m0.192s

三、其他

啰嗦了一大堆,发现本篇并没有一个特别的主题,无非是一个类似七拼八凑的总结,索性再大杂烩一下。

lsof 常用方法:

1You can also look for files opened by a given user:
2# lsof -n -P -u USER
3List files opened by a specified command:
4# lsof -n -P -c COMMAND

ss 指令的更多用法,可以参看Linux网络状态工具ss命令使用详解

netstat日常使用最多的指令,这里不再介绍。