针对以下两条命令,先给自己的结论吧:加-p是指定进程,不加-p的是线程
(脚本小白,没找着出处,是根据数据观察的,欢迎各位大佬指正)
最近,系统出了一次问题,导致所有页面都打不开,接口都访问失败,当然作为运维小白,显然是不咋会看Linux的一些资源占用情况的,然后看了提交记录没改啥影响全局的东西,就埋头去看错误日志了,额,,,显然错误日志也不少,还没在错误日志的信息里提取出主要原因,大佬就说:我看了一下,文件句柄数超过默认的1024了。你看看是不是这个原因,果然日志文件里:java.io.IOException:Too many open files。然后就自己检查哪些打开流没关的,问题解决。
很久之后,领导:最近系统很慢啊,你把Linux的一些资源占用情况定时入库吧。我嘴上:好的。内心:这是要写jio本吗?我不会吖?╥﹏╥...。然后就开始各种翻博客,cpu、内存啥啥的,查到了,嗯,用top很顺利,优秀的文章又多,终于,到了文件句柄了,基本上都是:
统计各进程打开句柄数(执行结果:第一列是数量,第二列是pid):
lsof -n|awk '{print $2}'|sort|uniq -c |sort -nr|more
统计单个进程打开句柄数(执行结果:只有数量):
lsof -p pid |wc -l
执行:
[root@localhost ~]# lsof -p 11211 |wc -l
437
[root@localhost ~]# lsof -n|awk '{print $2}'|sort|uniq -c |sort -nr|more
90688 11211
46368 11055
...
这,不对啊,指定pid统计结果437,不指定pid统计结果90688,就算它时刻在变化,复制粘贴前后时间相差一秒,也没这么大变化吧,我网上搜啊搜啊,也搜不出为啥,不会是文件句柄打开没关导致泄露吧,跟领导汇报完,领导:不可能,60%都是你危言耸听,你再查查看。网上我是搜不到了,然后就把详细信息打出来对比了:
[root@localhost ~]# lsof -p 11211
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
java 11211 root cwd DIR 253,0 64 101221120 /n....
java 11211 root rtd DIR 253,0 281 64 /
java 11211 root txt REG 253,0 7734 100879130 /usr/...
....
#脚本大意:输出包含11211的行(不是很会脚本,表头是我单独执行lsof复制过来的,尴尬)
[root@localhost ~]# lsof |grep 11211
COMMAND PID TID USER FD TYPE DEVICE SIZE/OFF NODE NAME
java 11211 root 231u IPv6 128887212 0t0 TCP localhost...
java 11211 root 232u IPv6 128887213 0t0 TCP localhost...
java 11211 root 233u IPv6 128886515 0t0 TCP localhost...
java 11211 root 234r REG 253,0 3866653 102282 /usr/java/....
java 11211 root 235r REG 253,0 2245827 102282 /usr/java/....
java 11211 root 236u unix 0xfff 0t0 128879 socket
java 11211 root 237u unix 0xfff 0t0 128879 socket
java 11211 11212 root cwd DIR 253,0 64 101221 /n..
java 11211 11212 root rtd DIR 253,0 281 64 /
...
乍一看,这不一样的吗,再仔细看,咦,第二个多了一列,第三列的TID(线程ID),然后统计了一下TID的重复次数:
#脚本大致意思:只输出包含11211的行,读出每行的第三列,统计相同TID出现次数,排序
[root@localhost ~]# lsof |grep 11211 |awk '{print $3}'|sort|uniq -c |sort -nr|more
436 root
436 28785
436 28784
436 18749
436 18748
436 18747
436 18746
436 18741
436 18740
436 18699
436 18698
436 18697
...
欸,你发现没,每个线程重复次数都是一样的,这表明什么,不晓得,但是这么一致肯定是有问题的,再回想一下,当年葛大爷(教操作系统的最严厉的老师)的话:进程持有资源,线程基本不持有资源,共享进程所持有的资源。再翻了一下,找到一张图(有时候图会显示不出来,手动转成了表格):
线程共享 | 线程独享 |
---|---|
地址空间 | 程序计数器 |
全局变量 | 寄存器 |
打开的文件 | 栈 |
子进程 | 状态字 |
闹钟 | |
信号及信号服务成勋 | |
记账信息 |
其他的看不懂没关系,但是我看到了 打开的文件 属于 线程共享 ,再统计这个进程的线程数:
#统计11211进程的线程数
[root@localhost ~]# ps -T -p 11211 |wc -l
209
436*209不就约等于9万多,啊~~~~意思是每个打开文件算是线程共享,所以一个进程有多少个线程就重复了多少次?自我感觉大概就是这意思吧(小声逼逼:虽然也不晓得对不对,毕竟脚本小白,也没找着出处)
好了,根据以上我的结论是:
lsof -p 18088 |wc -l这个脚本统计的是指定进程的文件句柄打开数
lsof -n|awk '{print $2}'|sort|uniq -c |sort -nr|more这个脚本我当然不敢说是错的,但不是我想要的,起码如果进程不是只有单个线程的话,不是统计的各进程打开句柄数