Помогите с пингом через попен - PullRequest
0 голосов
/ 26 февраля 2011

Я разрабатываю программное обеспечение для мониторинга связи в разных местах.Принцип прост: отправляйте пинг каждую секунду и отображайте результаты в режиме реального времени (задержка мс, потеря пакета и т. д.)

Также важно отметить, что я запускаю программное обеспечение из Linux, поэтому для пингаИз моего программного обеспечения я выбираю способ subporocess.Popen, потому что для открытия сокетов вам необходимо войти в систему как пользователь root.И я не хочу давать всем root доступ к серверу ..

Вот класс, отвечающий за пинг:


 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_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 xxx.xxx.xxx.xxx", спайков нет.

Можно ли запустить беглый пинг с Popen из скрипта и прочитать результаты?

Ответы [ 2 ]

1 голос
/ 26 февраля 2011

Это выглядит как хорошая отправная точка:

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

Конечно, не ясно, что есть какие-то проблемы с тем, что вы делаете сейчас на самом деле.Так как время ping анализируется с вывода ping, мы не можем обвинять процессные издержки или что-то в этом роде.

0 голосов
/ 26 февраля 2011

Попробуйте добавить close_fds=True к вашему Popen вызову (см. Обсуждение здесь ).Если в других потоках открыты другие каналы, возможно, они как-то взаимодействуют (вызывая конкретное упорядочение потоков).Подумайте об использовании Popen.communicate() вместо непосредственного чтения из потока stdout процесса.С учетом вышесказанного кажется маловероятным, что ваша реализация ping выдаст разные показания в зависимости от того, насколько хорошо буферизуется ее вывод.

На более высоком уровне вы должны иметь в виду, что данные синхронизации ping по своей природе ненадежны.Если вы не можете исправить всплеск и убеждены, что это артефакт от вызова Popen (а не просто случайный шум), то, вероятно, разумно пост-обработать данные.Например, вы можете собрать 5 точек данных за раз и взять медиану.(Обратите внимание, что медиана менее чувствительна к выбросам, чем в среднем).Это не хуже, чем то, что ping уже делает.

Обновление 26/02

Сожалею, что ^ не помог.Пара других идей:

1. Может быть полезно, если мы узнаем немного больше о том, как вы запускаете ping из оболочки.В python вы используете -c1, чтобы ограничить ping одной попыткой.Я предполагаю, что в оболочке вы просто запускаете ping hostname и смотрите результаты в режиме реального времени - это правда?Если это так, попробуйте запустить скрипт bash следующим образом:

#! /bin/bash

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

И внимательно посмотрите на результаты.Возможно, что спайки являются результатом того, как вы звоните ping.

2. В вашем примере кода нет определений регулярных выражений.Вы на 100% уверены, что они получают точные правильные значения из вывода ping?

...