通过 ssh 发送命令而不是等到离开终端的脚本

通过 ssh 发送命令而不是等到离开终端的脚本

我有几台计算机,通过以太网交换机组合成网络。所有这些都运行 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)。使用后台方法,您必须手动(或使用其他开发的工具)检查命令是否成功,或者是否已完成执行。

相关内容