标题: x64/FreeBSD 10.3/12.0中lsof的替代方案
创建: 2019-06-13 14:29 更新: 2019-06-17 18:06 链接: https://scz.617.cn/unix/201906131429.txt
现在用FreeBSD的很少,估计比SPARC/Solaris多点。
在*nix中经常用lsof查看网络端口与进程之间的关联。Linux的netstat有增强,-p参 数会显示进程信息。
在FreeBSD 10.3/12.0中欲达此目的,仍然可以使用lsof:
$ pkg install lsof $ lsof -lnPR -i $ lsof -lnPR -i4 $ lsof -lnPR -i TCP
有时没有条件安装、使用lsof,只能寻找其他替代方案。
1) sockstat
FreeBSD 10.3/12.0有个sockstat:
$ sockstat $ sockstat -4 -l $ sockstat -4
2) sockstat.pl
在FreeBSD 4.x时sockstat还是个perl脚本,从5.x起变成ELF了。如果系统被裁剪过 而没有ELF版sockstat,可以去下载perl版sockstat.pl:
http://sources.freebsd.org/releng/4.9/usr.bin/sockstat/sockstat.pl
$ perl sockstat.pl $ perl sockstat.pl -4
3) 手工模拟sockstat.pl
裁剪过的系统很可能没有perl解释器,此时sockstat.pl也不能用。可以尝试手工模 拟sockstat.pl,下面解释一下sockstat.pl的内在原理。
下面用到的fstat、netstat、awk都是系统自带工具。
$ fstat | grep "internet " root sshd 4014 3 internet stream tcp fffff80002bb8408 scz sshd 720 3 internet stream tcp fffff80002bb9000 root sshd 718 3 internet stream tcp fffff80002bb9000 root sendmail 624 3 internet stream tcp fffff80002bb9408 root sshd 621 4 internet stream tcp fffff80002bb9810 root syslogd 494 7 internet dgram udp fffff80002a237a8 unbound unbound 348 5 internet dgram udp fffff80002a23ab8 unbound unbound 348 6 internet stream tcp fffff80002bba408
$ netstat -naA | grep -E "(tcp|udp)4" fffff80002bb8408 tcp4 0 52 192.168.65.133.22 192.168.65.1.32103 ESTABLISHED fffff80002bb9000 tcp4 0 0 192.168.65.133.22 192.168.65.1.23977 ESTABLISHED fffff80002bb9408 tcp4 0 0 127.0.0.1.25 . LISTEN fffff80002bb9810 tcp4 0 0 .22 . LISTEN fffff80002bba408 tcp4 0 0 127.0.0.1.53 . LISTEN fffff80002a237a8 udp4 0 0 .514 . fffff80002a23ab8 udp4 0 0 127.0.0.1.53 .
fstat输出的最后一列是进程用到的协议控制块(PCB),netstat的-A参数使得第一列 输出对应PCB。以PCB为key求fstat、netstat输出的交集即可。
$ fstat | grep "internet " > fstat.txt $ netstat -naA | grep -E "(tcp|udp)4" > netstat.txt $ awk 'NR==FNR{xxx[$8]=$0;next}$1 in xxx{printf("%s %s\n",substr(xxx[$1],1,25),substr($0,18));}' fstat.txt netstat.txt root sshd 4014 tcp4 0 52 192.168.65.133.22 192.168.65.1.32103 ESTABLISHED root sshd 718 tcp4 0 0 192.168.65.133.22 192.168.65.1.23977 ESTABLISHED root sendmail 624 tcp4 0 0 127.0.0.1.25 . LISTEN root sshd 621 tcp4 0 0 .22 . LISTEN unbound unbound 348 tcp4 0 0 127.0.0.1.53 . LISTEN root syslogd 494 udp4 0 0 .514 . unbound unbound 348 udp4 0 0 127.0.0.1.53 .
718、720号进程是fork()导致的父子进程,PCB一样。上述awk方案没有处理多个PCB 一样的情形,最后一个PCB所在行被留存,awk输出中720号进程消失了。
netstat的PCB只有一份,不会重复,fstat的PCB才会重复。换个更好的awk方案:
$ awk 'NR==FNR{xxx[$1]=$0;next}$8 in xxx{printf("%s %s\n",substr($0,1,25),substr(xxx[$8],18));}' netstat.txt fstat.txt root sshd 4014 tcp4 0 52 192.168.65.133.22 192.168.65.1.32103 ESTABLISHED scz sshd 720 tcp4 0 0 192.168.65.133.22 192.168.65.1.23977 ESTABLISHED root sshd 718 tcp4 0 0 192.168.65.133.22 192.168.65.1.23977 ESTABLISHED root sendmail 624 tcp4 0 0 127.0.0.1.25 . LISTEN root sshd 621 tcp4 0 0 .22 . LISTEN root syslogd 494 udp4 0 0 .514 . unbound unbound 348 udp4 0 0 127.0.0.1.53 . unbound unbound 348 tcp4 0 0 127.0.0.1.53 . LISTEN
这次同时看到718、720号进程。
如果是x86/FreeBSD,substr()的参数要变一下:
$ awk 'NR==FNR{xxx[$1]=$0;next}$8 in xxx{printf("%s %s\n",substr($0,1,25),substr(xxx[$8],10));}' netstat.txt fstat.txt
4) procstat
FreeBSD 10.3/12.0有个procstat:
$ procstat -f -a | grep " s -"
$ procstat -f -a | grep -E " (TCP|UDP) "
$ procstat -f