想要从跃点服务器到服务器列表运行“for 循环”。如果我在单个服务器中运行 for 循环,它工作正常,但我不知道如何嵌套它并使其在跃点服务器上工作。
For 各个主机的循环输出:
$ for i in {a..b}; do echo Volume: /dev/sd$i; sudo /usr/sbin/smartctl -a /dev/sd$i | egrep -i "model|serial"; done
Volume: /dev/sda
Device Model: TOSHIBA THNSNJ256GCSU
Serial Number: 35FS109IT88W
Volume: /dev/sdb
Model Family: Seagate Constellation ES.3
Device Model: ST4000NM0033-9ZM170
Serial Number: Z1Z7EK85
$
下面是我通常如何从跃点服务器运行“for 循环”:
$ for i in `cat hostlist`;do echo $i;ssh $i "uptime";echo " ";done
请建议!
答案1
您可能正在寻找类似的东西:
while IFS= read -r host
do {
printf "%s\n" "$host"
ssh -t -- "$host" '
for i in a b
do
printf "%s\n" "Volume: /dev/sd$i"
sudo smartctl -a "/dev/sd$i" | grep -Ei "model|serial"
done'
} 0<&3
done 3<&0 <hostlist
我假设hostlist
文件中列出了主机,每行一个。IFS=
和-r
在这里可能是不必要的,因为主机名不太可能包含空白字符或反斜杠;不过,它们不应该受到伤害。同样,在这种情况下,在循环hostlist
中读取您的for
内容可能没问题,但使用while
循环是一个好习惯。看为什么我的 shell 脚本会因为空格或其他特殊字符而卡住?了解更多相关信息。
对于每个主机,都会使用强制在远程主机上分配伪终端的选项来ssh
调用,需要输入将询问您的密码(除非您将其配置为不这样做)。-t
sudo
打开一个新的文件描述符 ( 3<&0
),复制外部标准输入的文件描述符,以使后者可用于循环体({
}
由于这个原因而被包装)。ssh
否则将读取您的信息hostlist
并无法与您互动(例如,当sudo
需要您的密码时)。
我替换echo
为printf
因为后者是更稳健(即使这里并不是严格必要的)。我替换egrep
为grep -E
因为(查看 GNU 手册)前者已被弃用并且仅提供向后兼容性。
最后,我将大括号扩展 ( {a..b}
)替换为a b
,以使脚本能够在任何 POSIX shell 中运行,包括那些不支持该功能的 shell(例如dash
)。