如何在没有端口号的情况下检查远程主机是否已启动?除了使用常规 ping 之外,还有其他方法可以检查吗?
远程主机可能会丢弃 ping 数据包
这对我来说效果很好:
SOMEHOST = 'localhost'
HOST_UP = os.system(f"ping -c 1 {SOMEHOST}") is 0
注:
SOMEHOST
变量不应来自任何潜在的恶意输入。协议级 PING 是最好的,即连接到服务器并以不执行实际工作的方式与其交互。这是因为这是确保 service 正常运行的唯一真正方法。 ICMP ECHO(又名 ping)只会告诉您另一端的网络接口已启动,即使如此也可能被阻止; FWIW,我见过所有用户进程都被阻塞但仍然可以 ping 通的机器。在当今的应用程序服务器中,即使获得网络连接也可能不够。如果托管应用程序已关闭或无法运行怎么办?正如我所说,对您感兴趣的实际服务说些甜言蜜语是最好、最可靠的方法。
许多防火墙配置为丢弃 ping 数据包而不响应。此外,某些网络适配器将在没有操作系统网络堆栈输入的情况下响应 ICMP ping 请求,这意味着操作系统可能已关闭,但主机仍会响应 ping(通常,如果您重新启动服务器,您会注意到,例如,它会在操作系统实际启动和其他服务启动之前的某个时间开始响应 ping)。
确定主机已启动的唯一方法是实际尝试通过一些众所周知的端口(例如 Web 服务器端口 80)连接到它。
为什么需要知道主机是否“启动”,也许有更好的方法来做到这一点。
HOST_UP = True if os.system("ping -c 5 " + SOMEHOST.strip(";")) is 0 else False
要删除讨厌的脚本执行,只需添加 .strip(";")
-c 5
增加 ping 请求的数量,如果全部通过则为 True
PS。仅适用于 Linux,在 Windows 上始终返回 True
你能做的最好的事情是:
许多站点都会阻止 ICMP(用于 ping 站点的端口),因此您必须事先知道相关主机是否启用了 ICMP。
连接到端口会告诉您混合信息。这实际上取决于您想知道什么。端口可能是开放的,但站点实际上已挂起,因此您可能会得到误报。更严格的方法可能涉及使用 HTTP 库对站点执行 Web 请求,并查看是否收到响应。
这实际上完全取决于您需要了解什么。
尝试一些需要 RPC 的东西(例如“任务列表”命令与 ping 结合使用)怎么样?
我会使用端口扫描仪。最初的问题表明您不想使用端口。然后您需要指定要监控的协议(是的,这需要端口):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