我的子网上有一组 Linux 服务器,我希望能够从主机远程关闭它们。我不希望非主机必须提前与主机协调,即知道其 IP 地址等。因此,基于广播或多播消息的方法似乎是一种显而易见的方法。
我已经实施了一个解决方案,socat
但我想知道是否存在更好的、不那么临时的解决方案,例如使用已建立的多播感知服务之一,如 SNMP 或 Bonjour?
我的解决方案如下。在所有非主机上,我运行:
$ socat UDP4-RECVFROM:6666,broadcast,fork SYSTEM:'hostname; shutdown now'
这告诉socat
在端口 6666 上监听广播消息,当它收到消息时,它会回显主机名并关闭机器。
现在,同一子网上的任何机器都可以使用以下命令关闭所有运行此命令的机器(它等待输入,因此请输入任何内容,例如bye
):
$ socat STDOUT UDP4-DATAGRAM:255.255.255.255:6666,broadcast
bye
这将广播该消息(在本例中bye
),socat
然后输出所有在端口 6666 上监听广播消息的机器回显的主机名。
这种方法显然不安全 - 如果同一子网上的任何机器向端口 6666 广播任何内容,系统就会关闭。可以添加一个简单的额外层 - 除了运行之外,hostname; shutdown now
还可以运行一个脚本,该脚本实际上会检查广播的内容,并且仅在看到例如只有相关方才知道的长随机数时才关闭。
答案1
仅当看到只有相关方才知道的长随机数时才会关闭。
好吧,如果您对这种程度的协调没有意见,那么只需让主主机通过 SSH 连接到所有其他服务器并shutdown
以此方式运行命令即可。服务器只需要知道一个长随机数,即主主机的公钥。
(相应的私钥不限于单个主密钥;您可以将文件复制~/.ssh/id_*
到任何需要的地方。)
Bonjour/Avahi 纯粹是一种发现机制,不支持广播命令,但您可以在此处使用它来列出子网中的所有机器(通过通用的“工作站”服务,或通过自定义的服务)。
答案2
由于您必须在“非主服务器”上执行命令,我假设主服务器和非主服务器之间存在某种协调。因此,您可以使用 ssh 和 ssh 密钥对身份验证来远程执行命令,如下所示:
ssh -i /path/to/pubkey @server 'shutdown -H now'