Netstat 无法通过 php 函数 exec() 在 FreeBSD 上运行

Netstat 无法通过 php 函数 exec() 在 FreeBSD 上运行

在我的 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

摘要:
当我netstatowl- 身份运行时,它返回一个空的连接列表
当我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 频道,知识渊博的人经常在这里闲逛。

相关内容