我有几台计算机,通过以太网交换机组合成网络。所有这些都运行 Fedora 服务器并连接到互联网。
我需要的是一个脚本,其中:
- 连接到列表中的所有节点
- 发送命令或命令包(例如更新全部或安装某些包)
- 关闭连接,但保持命令在目标计算机上运行
目前,脚本是:
#!/bin/bash
targets_username='username'
targets_password='password'
targets_IPs=( 192.168.1.100 192.168.1.101 192.168.1.102 )
SCRIPT1='dnf update -y'
SCRIPT2='dnf update -y && poweroff'
for IP in ${targets_IPs[@]}; do
export SSHPASS=$targets_password
script="nohup sh -c \"( ( $SCRIPT1 & > /dev/null) &)\""
echo $IP
echo $script
sshpass -e ssh -o StrictHostKeyChecking=no -l $targets_username@$IP $script
done
问题是:
- 一旦连接关闭,命令就会停止运行
- 如果命令包含额外的命令,例如
reboot
或者poweroff
它被转发到主计算机,该脚本从该主计算机启动。
如何解决这个问题?
答案1
这些类型的调用总是很棘手,因为您必须确保在正确的位置评估事物。 IE。添加正确数量的反斜杠。
如果你这样做
script="sh -c \"nohup sh -c '$SCRIPT1' > /dev/null 2>&1 & \""
sshpass -e ssh -n -o StrictHostKeyChecking=no -l $targets_username $IP "$script"
它应该做你想做的事(注意-n
保持标准输入关闭)。您可以通过time
在 sshpass 命令之前添加或运行netstat
并$SCRIPT1
检查打开的连接来验证 ssh 连接是否确实关闭。
您需要确保 stdin、stdout 和 stderr 都已关闭,否则ssh
将一直等到它们关闭,即使进程已进入后台。
如果上述方法不起作用,则可能会对命令行参数进行额外的评估sshpass
。此外,使用单引号$SCRIPT1
会延迟内部(例如 shell 变量)的扩展,$SCRIPT1
直到远程端。
现在,即使您可以使用这种方法完成任务,我还是建议您使用专用于这种自动化的工具,例如 Ansible (https://docs.ansible.com/ansible/latest/index.html)。使用后台方法,您必须手动(或使用其他开发的工具)检查命令是否成功,或者是否已完成执行。