通过 Popen 帮助 ping

发布于 2024-10-19 12:14:26 字数 2041 浏览 6 评论 0原文

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

还需要注意的是,我是在 Linux 上运行该软件,因此为了从我的软件中执行 ping 操作,我选择了subporocess.Popen 方式,因为打开套接字需要您以 root 用户身份登录。我不想给每个人对服务器的 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 作业。

我的问题是这样的: 运行时,我得到了完美的毫​​秒延迟结果,但每隔几次 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 并读取结果?

I'm developing a software to monitor communication to different locations.
the principle is simple: send ping every second and display the results in real time (ms delay, packet loss etc)

It's also important to mention that I'm running the software from Linux, so in order to ping from my software i choose the subporocess.Popen way, because opening sockets require you to be logged as root user. And i don't want to give everyone root access to the server..

Here is the class reponsible for the pinging:


 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

I'm using threads because sometimes i need to run multiple ping jobs to different sites.

My problem is this:
when running, i get the ms delay results perfectly, but every few pings i get a not accurate result, higher then what it actually should be.

I know that the results are not accurate, because i run ping from a console at the same time, and there i don't get that ping spike

Example:

ping_ms = 20.0

ping_ms = 21.31

ping_ms = 23.23

ping_ms = 80.2

ping_ms = 23.23

ping_ms = 24.2

I don't understand why this is happening. maybe i need to write the code differently. if someone could help me, it will be much appreciated.

thanks.

i have isolated the problem:

It seems that the problem is not in the code, but in the OS or in the ping command itself.
when i run manually every second in console the command: "ping -c1 xxx.xxx.xxx.xxx" after few attempts i get the same result ,a weird ping spike. but if the ping fluent "ping xxx.xxx.xxx.xxx", there are no spikes.

Is it possible to run fluent ping with Popen from a script and read the results?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

秋凉 2024-10-26 12:14:26

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

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

当然,目前还不清楚你现在所做的事情是否真的有任何问题。由于 ping 时间是从 ping 的输出中解析出来的,所以我们不能归咎于进程生成开销或其他什么。

This looks like a good starting point:

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

Of course, it's not clear that there is any problem with what you're doing now really. Since the ping time is being parsed from the output of ping it's not like we can blame process spawning overhead or something.

空心空情空意 2024-10-26 12:14:26

尝试将 close_fds=True 添加到您的 Popen 调用中(请参阅讨论 此处)。如果您在其他线程中打开了其他管道,则它们可能以某种方式进行交互(强制线程的特定顺序)。考虑使用 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 输出中捕获了准确正确的值?

Try adding close_fds=True to your Popen call (see discussion here). If you have other pipes open in other threads, it may be the case that they are interacting somehow (forcing a particular ordering of threads). Consider using Popen.communicate() rather than reading from the process' stdout stream directly. With that said, it seems unlikely that your ping implementation would return different readings based on how well its output is being buffered.

At a higher level, you should keep in mind that ping timing data is inherently unreliable. If you can't fix the spike, and you're convinced it is an artefact from the Popen call (rather than just random noise), then it is probably reasonable to post-process the data. For example, you could collect 5 datapoints at a time and take the median. (Note that the median is less sensitive to outliers than the average). This is no worse than what ping is already doing.

Update 26/02

Sorry to hear ^ didn't help. Couple of other ideas:

1. It might be helpful if we know a bit more about how you're running ping from the shell. In python, you're using -c1 to limit ping to a single try. I am guessing that, in the shell, you are simply running ping hostname and watching the results in real time -- is this true? If so, please try running a bash script as follows:

#! /bin/bash

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

And look very carefully at the results. It is possible that the spikes are the result of how you're calling ping.

2. Your sample code doesn't have your regex definitions. Are you 100% sure they are capturing the exact right values from ping's output?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文