【问题标题】:Check if remote host is up in Python检查远程主机是否在 Python 中启动
【发布时间】:2011-02-01 20:46:28
【问题描述】:

如果没有端口号,我如何检查远程主机是否已启动?除了使用常规 ping 之外,我还有什么其他方法可以检查。

远程主机可能会丢弃 ping 数据包

【问题讨论】:

  • 你能举个例子吗?您可以遍历给定主机的所有端口(或至少是公共端口),但这开始接近黑帽。
  • 快速浏览一下答案,我得出结论,您的问题有些含糊。如果您还说明您的最终/高级目标是什么,您可能会得到更好的答案:例如您想监控服务的可用性还是想编写某种网络安全检查工具来发现“启动”的主机?

标签: python network-programming network-protocols


【解决方案1】:

我会使用端口扫描器。原始问题表明您不想使用端口。然后您需要指定要监控的协议(是的,这需要一个端口):HTTP、VNC、SSH 等。如果您想通过 ICMP 进行监控,您可以使用子进程和控制 ping 参数、ping 次数、超时、大小等。

import subprocess 
    try:
        res = subprocess.Popen(['ping -t2 -c 4 110.10.0.254 &> /dev/null; echo $?'],shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
        out, err = res.communicate()
        out = out.rstrip()
        err = err.rstrip()
        print 'general.connectivity() Out: ' + out
        print 'general.connectivity() Err: ' + err
        if(out == "0"):
            print 'general.connectivity() Successful'
            return True
        print 'general.connectivity() Failed'
        return False
    except Exception,e:
        print 'general.connectivity() Exception'
        return False

如果你想要一个端口扫描器

import socket
from functools import partial
from multiprocessing import Pool
from multiprocessing.pool import ThreadPool
from errno import ECONNREFUSED

NUM_CORES = 4

def portscan(target,port):
    try:
        # Create Socket
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        socketTimeout = 5
        s.settimeout(socketTimeout)
        s.connect((target,port))
        print('port_scanner.is_port_opened() ' + str(port) + " is opened")
        return port
    except socket.error as err:
        if err.errno == ECONNREFUSED:
            return False

# Wrapper function that calls portscanner
def scan_ports(server=None,port=None,portStart=None,portEnd=None,**kwargs):
    p = Pool(NUM_CORES)
    ping_host = partial(portscan, server)
    if portStart and portStart:
        return filter(bool, p.map(ping_host, range(portStart, portStart)))
    else:
        return filter(bool, p.map(ping_host, range(port, port+1)))

# Check if port is opened
def is_port_opened(server=None,port=None, **kwargs):
    print('port_scanner.is_port_opened() Checking port...')
    try:
        # Add More proccesses in case we look in a range
        pool = ThreadPool(processes=1)
                     try:
                        ports = list(scan_ports(server=server,port=int(port)))
                        print("port_scanner.is_port_opened() Port scanner done.")
                        if len(ports)!=0:
                            print('port_scanner.is_port_opened() ' + str(len(ports)) + " port(s) available.")
                            return True
                        else:
                            print('port_scanner.is_port_opened() port not opened: (' + port  +')')
                            return False
                    except Exception, e:
                        raise
                
    except Exception,e:
        print e
        raise

【讨论】:

    【解决方案2】:
    HOST_UP  = True if os.system("ping -c 5 " + SOMEHOST.strip(";")) is 0 else False
    

    要删除讨厌的脚本执行,只需添加 .strip(";")

    -c 5 
    

    增加 ping 请求的数量,如果都通过则大于 True

    PS。仅适用于 Linux,在 Windows 上始终返回 True

    【讨论】:

      【解决方案3】:

      这对我来说很好用:

      HOST_UP  = True if os.system("ping -c 1 " + SOMEHOST) is 0 else False
      

      【讨论】:

      • 警告。如果SOMEHOST 来自用户输入,这可能会引入安全漏洞。例如,如果SOMEHOST = google.com; echo "nasty command",那么用户的恶意命令将在 ping 完成后运行。
      • ICMP 请求可以在远程主机上被阻止,因此您可以在主机启动时获得 HOST_UP = False。
      【解决方案4】:

      尝试一些需要 RPC 的东西,比如 'tasklist' 命令和 ping 结合使用怎么样?

      【讨论】:

        【解决方案5】:

        协议级别的 PING 是最好的,即连接到服务器并以一种不做实际工作的方式与之交互。这是因为它是确保服务 已启动的唯一真正方法。 ICMP ECHO(又名 ping)只会告诉您另一端的网络接口已启动,即使这样也可能被阻止; FWIW,我见过所有用户进程都被阻塞但仍然可以ping通的机器。在应用服务器时代,即使获得网络连接也可能不够;如果托管应用程序关闭或无法正常运行怎么办?正如我所说,对您感兴趣的实际服务说甜言蜜语是最好、最可靠的方法。

        【讨论】:

          【解决方案6】:

          许多防火墙被配置为丢弃 ping 数据包而不响应。此外,一些网络适配器会在没有来自操作系统网络堆栈的输入的情况下响应 ICMP ping 请求,这意味着操作系统可能已关闭,但主机仍会响应 ping(通常您会注意到,如果您重新启动服务器,例如,它会在操作系统实际启动和其他服务启动之前的某个时间开始响应 ping。

          确定主机已启动的唯一方法是实际尝试通过某个众所周知的端口(例如 Web 服务器端口 80)连接到它。

          为什么你需要知道主机是否“启动”,也许有更好的方法。

          【讨论】:

            【解决方案7】:

            你能做的最好的就是:

            • 尝试连接已知端口(例如,HTTP 或 HTTPS 的端口 80 或 443);或
            • ping 站点。见Ping a site in Python?

            许多站点会阻止 ICMP(用于 ping 站点的端口),因此您必须事先知道相关主机是否启用了它。

            连接到端口会告诉您混合信息。这真的取决于你想知道什么。端口可能已打开,但该站点实际上已挂起,因此您可能会得到误报。更严格的方法可能涉及使用 HTTP 库对站点执行 Web 请求并查看您是否收到响应。

            这完全取决于你需要知道什么。

            【讨论】:

              猜你喜欢
              • 2021-08-21
              • 2020-06-15
              • 1970-01-01
              • 2016-07-29
              • 2011-06-08
              • 1970-01-01
              • 2010-10-25
              • 2012-10-02
              • 1970-01-01
              相关资源
              最近更新 更多