标题: 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 | grep -E " (TCP|UDP) "