使用充当UDP回送的程序确定服务器可用性

时间:2015-09-15 13:48:43

标签: python linux perl ping availability

我在ubuntu中使用Xen Hypervisor,我有一台VM。当将vm实时迁移到另一个主机时,vm将在大约几毫秒到不超过几秒的顶部范围内不可用(取决于环境)。我需要能够尽可能准确地确定短时间。所以我需要'以某种方式'检查vm说每100毫秒。以及我连续找到vm UNAVAILABLE的次数乘以100,将是我的虚拟机停机时间的总毫秒数。

ping不起作用,因为它不准确,并且在vm不可用的情况下,ping命令等待并重试发送ICMP数据包,这破坏了目标,以确定服务器是否在该确认检查时可用。另外我在here中问了一个问题,反馈是“不要使用ping!” 所以不使用PING!

我需要在python / perl / whathever中编写我自己的一段代码才能完成这项工作。我怎么能这样做?

2 个答案:

答案 0 :(得分:1)

  

ping不起作用,因为它不准确,并且在vm不可用的情况下,ping命令等待并重试发送ICMP数据包

这是默认设置,但您可以告诉它只发送一个。

$ ping -q -c 1 9.9.9.9 >/dev/null

$ echo $?
1

$ ping -q -c 1 8.8.8.8 >/dev/null

$ echo $?
0

所以

while ! ping -q -c 1 -W 1 x.x.x.x >/dev/null ; do true ; done
  

另外我在这里问了一个问题,反馈是“不要使用ping!”   所以没有使用PING!

然而,您要求(基于UDP)ping而不是检查所需服务是否已启动的方法。

答案 1 :(得分:0)

这是一个ZeroMQ UDP ping功能,从UDP discovery, model 1 in Python改编,通过禁用广播,只ping一个IP地址,在第一次回复后返回,添加计数器以限制ping尝试次数并在消息期间添加额外的错误处理接收。后者完成了,因为我网中的一个主机强行关闭导致socket.error的连接:[Errno 10054]。它经过测试,发现可以与Python 2.7.10和3.4.3一起使用。

from __future__ import print_function
import os
import socket
import sys
import time
import zmq

def udpping(ip):
    PING_PORT_NUMBER = 9999
    PING_MSG_SIZE = 1
    PING_INTERVAL = 1 # once per second, sets minimum initial timeout

    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
    # uncomment the line below for broadcast to 255.255.255.255
    # sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
    sock.bind(('', PING_PORT_NUMBER))
    poller = zmq.Poller()
    poller.register(sock, zmq.POLLIN)
    ping_at = time.time()

    limit = 5 # only limit ping attempts will be made
    count = 0
    while True:
        count += 1
        timeout = ping_at - time.time()
        if timeout < 0:
            timeout = 0
        try:
            events = dict(poller.poll(1000* timeout))
        except KeyboardInterrupt:
            return (1,None,None)
        try:
            if sock.fileno() in events:
                msg, addrinfo = sock.recvfrom(PING_MSG_SIZE)
                return (2,"found %s:%d" % addrinfo,None)
        except socket.error as e:
            return (3,'error during msg receive:',e)
        if time.time() >= ping_at:
            # the line below is for broadcasting
            # sock.sendto(b'!', 0, ("255.255.255.255", PING_PORT_NUMBER))
            sock.sendto(b'!', 0, (ip, PING_PORT_NUMBER))
            ping_at = time.time() + PING_INTERVAL
        if count == limit:
            return (4,limit,None)

ip = '192.168.159.21'
c,m,e = udpping(ip)

下面显示了输出处理。对于二进制决策,只有在c == 2时才能成功。

if c == 1:
    print('ping attempt stopped by KeyboardInterrupt')
elif c == 2:
    print(m)
elif c == 3:
    print(m,e)
elif c == 4:
    print('no response from',ip,'after',m,'attempts')

# prints 'found 192.168.159.21:9999' immediately in my net