我有这个脚本:
#!/bin/sh
SERVERLIST=hosts
ICMD='cat /etc/redhat-release'
while read SERVERNAME
do
ssh $SERVERNAME $ICMD
done < "$SERVERLIST"
就像hosts
:
hostname
hostname
hostname
当我运行脚本时,./run.sh
它仅转到单个主机并停止。为什么它不读取整个主机列表?
答案1
ssh 假设远程作业需要一些数据来预读取 stdin,这样可以加快启动速度。因此,第一项工作会占用主机列表中的其余部分。
您可以使用该ssh -n
选项或通过重定向(如 )来防止这种情况发生ssh < /dev/null
。作为一个严格要求的人,我两件事都做ssh -n < /dev/null <other ssh options>
:
如果您确实希望远程作业从本地系统读取某些内容,则需要为每次迭代对其进行管道传输或在此处对其进行文档化。即使使用for <host>
,ssh 也会为每个主机启动从 stdin 读取不确定数量的数据。
在通过 ssh 访问远程主机之前,我总是会 ping 远程主机以获取状态。 IIRCping -W
具有硬超时选项,ssh
对于未知或死亡的主机,可能会在 DNS 中挂起或连接超过 90 秒。
答案2
您也可以使用pdsh
它,它允许在多个主机上并行运行命令。
pdsh -w ^hostlist.txt -R ssh "cat /etc/redhat-release"
^
定义一个包含主机名列表的文件,也可以使用逗号分隔的列表:
pdsh -w host1,host2,host3,... -R ssh "cat /etc/redhat-release"
结果如下:
pdsh, -w raspi,raspi.local,192.168.0.3,localhost,127.0.0.1 -R ssh "cat /etc/issue"
raspi: Raspbian GNU/Linux 10 \n \l
raspi:
raspi.local: Raspbian GNU/Linux 10 \n \l
raspi.local:
192.168.0.3: Raspbian GNU/Linux 10 \n \l
192.168.0.3:
localhost: Debian GNU/Linux 10 \n \l
localhost:
127.0.0.1: Debian GNU/Linux 10 \n \l
127.0.0.1: