在我的 php-app 中,我需要端口 80 上连接的所有 IP 的列表。我选择这样做:
<?php
$ips = exec("netstat -an |grep 'tcp\|udp' | awk '{print $5}' | cut -d: -f1 | sort | uniq -c", $info);
?>
但它在我的 VPS FreeBSD 服务器上不起作用。当我启动时,netstat -an
出现一条通知,但输出中没有连接:
netstat: kvm not available: /dev/mem: No such file or directory
我尝试将其添加device mem
到 conf,但我的 /usr/src/sys 为空。我到了需要重建核心的地步。))
netstat
当用户是 root 时(从控制台)可以正常工作。我在类似的 CentOS 托管平台上没有遇到过这样的问题。
/dev/mem: No such file or directory
我尝试过解决这个问题mknod -m 660 /dev/mem c 1 1
,但它调用了一个mknod: /dev/mem: Operation not permitted
我有以下用户pw showuser
owl:*:1000:1003:default:0:0:owl:/home/owl/data:/bin/csh
root:*:0:0::0:0:Charlie &:/root:/bin/csh
摘要:
当我netstat
以owl
- 身份运行时,它返回一个空的连接列表
当我netstat
以- 身份运行时root
,它返回通知netstat: kvm not available: /dev/mem: No such file or directory
和 IP
有人能帮我吗?还有其他方法可以解决这个任务吗?谢谢
答案1
我相信您的cut
行为不符合您的预期,因为在netstat
的输出中,IP 和端口由点而不是冒号分隔。
netstat: kvm not available: /dev/mem: No such file or directory
当我在我管理的一些 jail 中运行时,我也遇到了错误netstat -an
,但尽管出现了这个错误,我仍然从 netstat 获得了预期的结果。我还没有研究为什么会发生这种情况,所以我倾向于认为这是一个转移注意力的借口。
就命令行而言,您可以通过将更多功能打包到 awk 脚本中来减少管道:
netstat -an | \
awk '/^(tcp|udp)/{ip=$5; sub(/.[0-9]+$/,"",ip); list[ip]++;} END{for(ip in list){printf("%7d %s\n",list[ip],ip)}}'
为了便于阅读,将其拆分开来,这个 awk 脚本如下:
# Only work on tcp/udp lines...
/^(tcp|udp)/ {
ip=$5;
sub(/.[0-9]+$/,"",ip);
list[ip]++; # Populate an array of counters-per-IP
}
# After data are gathered, print the results.
END {
for (ip in list) {
printf("%7d %s\n",list[ip],ip);
}
}
但是由于您在 PHP 中执行此操作,因此我会在 PHP 中执行更多此类文本处理。
<?php
# Gather our data...
exec("netstat -an", $out);
# Easy access to the output we want (for isset() below)
$permit = array("udp4"=>1,"tcp4"=>1);
foreach ($out as $line) {
$a = preg_split("/[[:space:]]+/", $line);
# Only work on tcp4/udp4 lines...
if (isset($permit[$a[0]])) {
# Populate an array of counters...
$ip = substr($a[4], 0, strrpos($a[4],".")-1);
$list[$ip]++;
}
}
# And print the results.
foreach ($list as $ip => $count) {
printf("%7s\t%s\n", $count, $ip);
}
这看起来似乎需要做更多工作,但实际上可能比生成一组管道更快。
请注意,您sockstat
在 FreeBSD 中也有该命令,因此请根据 Chris S 的建议:
<?php
exec("sockstat -4", $out);
$permit = array("udp4"=>1,"tcp4"=>1);
foreach ($out as $line) {
$a = preg_split("/[[:space:]]+/", $line);
if (isset($permit[$a[4]])) {
preg_match("/^[^:]+/", $a[6], $ip);
$list[$ip[0]]++;
}
}
foreach ($list as $ip => $count) {
printf("%7s\t%s\n", $count, $ip);
}
更新:
我也遇到了关于 kvm 错误的古老注释. 由于路由表信息通常可用,您应该联系您的 VPS 提供商,了解他们是否故意限制您访问此主机上的路由表数据。如果您不在监狱里,那么我怀疑向 FreeBSD 邮件列表之一发帖会得到结果。irc.freenode.net 上还有一个 ##FreeBSD 频道,知识渊博的人经常在这里闲逛。