通过Popen帮助ping

时间:2011-02-26 17:59:26

标签: python linux multithreading popen ping

我正在开发一种软​​件来监控到不同位置的通信。 原理很简单:每秒发送一次ping并实时显示结果(ms延迟,丢包等)

同样重要的是要提到我正在运行Linux软件,所以为了从我的软件ping,我选择subporocess.Popen方式,因为打开套接字需要你以root用户身份登录。而且我不想让每个人都可以根本访问服务器..

以下是ping的责备类:


 class WorkerThread(QThread):
  def __init__(self,receiver,sitename):
    QThread.__init__(self)

    global time_manager
    time_manager[sitename] = [time.time(),0,0] #for statistic purpeses

    self.stopped = 0
    self.receiver = receiver
    self.sitename = sitename


  def run(self):
    icmp_count = 0
    ping_result = ""
    packeloss_result = ""

    while not self.stopped:
       data = subprocess.Popen("ping -c1 "+str(sites[self.sitename]),shell = True,stdout=subprocess.PIPE)
       data.wait()
       time_manager[self.sitename][1] +=1 #counts the icmps sent 
       bufferdata = data.stdout.read() 
       ping_result = ms_pat.findall(bufferdata)
       packeloss_result = packetloss_pat.findall(bufferdata)

       if ping_result:
         ping_ms = ping_result[0][0]
       if packeloss_result:
         time_manager[self.sitename][2] +=1        
         ping_ms = "-1"

       ms_count[self.sitename].append(float(ping_ms))
       time.sleep(1)
       event = QCustomEvent(12345)
       event.setData(self.sitename+ping_ms)
       QApplication.postEvent(self.receiver, event)

  def stop(self):
    self.stopped = 1

我正在使用线程,因为有时我需要在不同的站点上运行多个ping作业。

我的问题是: 在运行时,我得到完美的ms延迟结果,但是每隔几次ping就会得到一个不准确的结果,高于实际应该的结果。

我知道结果不准确,因为我同时从控制台运行ping,并且我没有得到ping峰值

示例:

ping_ms = 20.0

ping_ms = 21.31

ping_ms = 23.23

ping_ms = 80.2

ping_ms = 23.23

ping_ms = 24.2

我不明白为什么会这样。也许我需要以不同的方式编写代码。如果有人可以帮助我,我将非常感激。

感谢。

我已经解决了这个问题:

似乎问题不在代码中,而是在操作系统或ping命令本身中。 当我在控制台中每秒手动运行命令:“ping -c1 xxx.xxx.xxx.xxx”几次尝试后我得到相同的结果,一个奇怪的ping峰值。但如果ping流畅的“ping xxx.xxx.xxx.xxx”,则没有尖峰。

是否可以从脚本中使用Popen运行流畅的ping并读取结果?

2 个答案:

答案 0 :(得分:1)

这看起来是一个很好的起点:

http://pypi.python.org/pypi/ping/0.1

当然,目前尚不清楚你现在正在做什么。由于ping时间是从ping的输出中解析出来的,所以我们不能责怪进程产生的开销或其他事情。

答案 1 :(得分:0)

尝试在close_fds=True电话中添加Popen(请参阅讨论here)。如果你在其他线程中打开了其他管道,则可能是它们以某种方式进行交互(强制线程的特定顺序)。考虑使用Popen.communicate()而不是直接从进程'stdout流中读取。话虽如此,你的ping实现似乎不太可能根据其输出的缓冲程度返回不同的读数。

在更高级别,您应该记住ping时序数据本质上是不可靠的。如果你无法修复尖峰,并且你确信它是来自Popen调用的伪像(而不仅仅是随机噪声),那么后处理数据可能是合理的。例如,您可以一次收集5个数据点并取中位数。 (注意,中位数对异常值的敏感度低于平均值)。这并不比ping已经做的更糟糕。

更新26/02

很抱歉听到^没有帮助。其他一些想法:

1。如果我们更多地了解您如何从shell运行ping,这可能会有所帮助。在python中,您使用-c1ping限制为一次尝试。我猜测,在shell中,你只是运行ping hostname并实时观察结果 - 这是真的吗?如果是这样,请尝试运行bash脚本,如下所示:

#! /bin/bash

for i in {1..50}
do
   ping -c1 somehostname
   # maybe 'sleep 1' here
done

仔细看结果。尖峰可能是您呼叫ping的结果。

2。您的示例代码没有正则表达式定义。您是否100%确定他们从ping的输出中捕获了正确的值?