Python 通过Popen帮助ping
我正在开发一个软件来监控不同地点的通讯。 原理很简单:每秒发送ping并实时显示结果(毫秒延迟、丢包等) 还有一点很重要,我是从Linux运行软件的,所以为了从我的软件ping,我选择subprocess.Popen方式,因为打开套接字需要以root用户身份登录。我不想让每个人都有根用户访问服务器的权限 以下是ping的类责任:Python 通过Popen帮助ping,python,linux,multithreading,popen,ping,Python,Linux,Multithreading,Popen,Ping,我正在开发一个软件来监控不同地点的通讯。 原理很简单:每秒发送ping并实时显示结果(毫秒延迟、丢包等) 还有一点很重要,我是从Linux运行软件的,所以为了从我的软件ping,我选择subprocess.Popen方式,因为打开套接字需要以root用户身份登录。我不想让每个人都有根用户访问服务器的权限 以下是ping的类责任: class WorkerThread(QThread): def __init__(self,receiver,sitename): QThread._
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-c1xxx.xxx.xxx.xxx”几次尝试后,我得到了相同的结果,一个奇怪的ping尖峰。但是如果ping流利的“ping xxx.xxx.xxx.xxx”,就没有尖峰
是否可以从脚本使用Popen运行fluent ping并读取结果?这看起来是一个很好的起点:
当然,你现在所做的事情是否真的有问题还不清楚。由于ping时间是从ping的输出中解析出来的,因此我们不能将其归咎于进程生成开销或其他原因。尝试将
close\u fds=True
添加到您的Popen
调用中(参见讨论)。如果在其他线程中打开了其他管道,则可能是它们以某种方式进行交互(强制执行特定的线程顺序)。考虑使用<代码> Popen。CultAudio()<代码>,而不是直接从进程的“STDUT流”中读取。尽管如此,您的ping实现似乎不太可能根据其输出缓冲的程度返回不同的读数
在更高的层次上,您应该记住ping定时数据本质上是不可靠的。如果您无法修复尖峰,并且确信它是来自Popen
调用的人工制品(而不仅仅是随机噪声),那么对数据进行后处理可能是合理的。例如,您可以一次收集5个数据点并取中值。(请注意,中位数对异常值的敏感度低于平均值)。这并不比ping
已经在做的事情更糟糕
更新26/02
很遗憾,我没能帮上忙。还有一些其他想法:
1。如果我们能从shell中进一步了解您如何运行ping
,可能会有所帮助。在python中,使用-c1
将ping
限制为一次尝试。我猜,在shell中,您只需运行ping hostname
并实时查看结果——这是真的吗?如果是,请尝试运行bash脚本,如下所示:
#! /bin/bash
for i in {1..50}
do
ping -c1 somehostname
# maybe 'sleep 1' here
done
仔细观察结果。这些尖峰可能是您调用ping
的方式造成的
2.示例代码没有正则表达式定义。您是否100%确定他们从ping的输出中捕获了准确的值?为什么您认为延迟峰值不准确?在您和主机之间可能会有大量的延迟点。因为我同时从控制台运行ping,而在那里我没有得到pingspike@Urban48,这对我来说似乎不是很有说服力;我看不出为什么两次ping(即使它们几乎同时发生)必然会产生相同的结果。是的,控制台上的ping非常稳定,没有一个尖峰,而脚本每隔几秒钟就给我一个尖峰。差异非常明显。您是否尝试过在没有shell=True的情况下使用此选项?e、 例如:data=subprocess.Popen([“/bin/ping”、“-c1”、“+str(sites[self.sitename])),stdout=subprocess.PIPE)tnx为您解答。使用open sockets方法比popen更有效。似乎我没有收到ping尖峰。但我尝试避免这种情况。将根赋予python脚本不是很明智。我关于setuid的评论不正确,因此我将其删除。要真正使python脚本以根运行,您还必须将python解释器设置为uid这是个糟糕的主意。对不起:-(谢谢你的回答,close_fds=True,没有帮助。这很奇怪。如果我运行多个ping作业,有时它们都会同时得到这个峰值,有时只是其中的一部分。但是每隔几秒钟就会发生一次。峰值很大:从20毫秒延迟到140毫秒。我考虑过你提供的后期处理,但我需要显示我的结果尽可能实时。因此,我想打开套接字并发送pings手册是一个不错的选择,但在Linux中有点问题。更新了答案,添加了一些额外的想法,可能会帮助您了解问题的真相。祝您好运!您的第一个建议明确指出问题不在代码中!我尝试了您建议的方法h bash脚本,我得到了相同的ping尖峰,这意味着问题在于操作系统或ping命令本身。当ping流畅时,它的尖峰是自由的,当ping与-c或-w一起使用时,我得到了ping尖峰。我该如何处理它?我很高兴听到您能够隔离问题。我建议如下:使用
-c2
运行ping。然后从e在以下情况下的产出: