在 shell 脚本上使用变量循环 for

Avi*_*ión 3 shell ssh shell-script

我有以下脚本,它使用密钥通过 SSH 连接到服务器,并在那里制作了很多东西。

#!/usr/bin/env bash

ssh -i mykey.pem myuser@SERVER_IP << 'ENDSSH'
[A LOT OF STUFF]
ENDSSH
Run Code Online (Sandbox Code Playgroud)

(我用它运行它sh scriptname.sh

现在我想以同样的另一台服务器,所以我到SSH到两个不同的服务器(ip_1ip_2)有两个不同的.pem文件(mykey1.pemmykey2.pem)。

到目前为止,我知道如何按如下方式循环 ip:

#!/usr/bin/env bash

ip_list="ip_1 ip_2"

for ip in $ip_list; do
ssh -i mykey.pem myuser@$ip << 'ENDSSH'
[A LOT OF STUFF]
ENDSSH
done
Run Code Online (Sandbox Code Playgroud)

但现在我也想循环以获得正确的 pem 文件。我该如何存档?也许还有另一个清单?有人可以为我提供一个优雅的解决方案吗?

  • ip_1 应该使用 mykey1.pem
  • ip_2 应该使用 mykey2.pem

提前致谢

ter*_*don 6

由于您使用的是 bash,您可以使用关联数组

#!/usr/bin/env bash

declare -A ip_list=(["ip_1"]="mykey1.pem" ["ip_2"]="mykey2.pem")

for ip in "${!ip_list[@]}"; do
  ssh -i  "${ip_list[$ip]}" myuser@"$ip" << 'ENDSSH'
[A LOT OF STUFF]
ENDSSH
done
Run Code Online (Sandbox Code Playgroud)

请注意,关联数组与常规索引数组不同,不会以特定顺序保存,因此不能保证ip_1会在ip_2.


如果您需要使用一个简单的、兼容 POSIX 的 shell,请创建一个包含 ip 和密钥文件的文件,每行一个:

$ cat iplist.txt
ip1 mykey1.pem
ip2 mykey2.pem
Run Code Online (Sandbox Code Playgroud)

然后,使用这个脚本:

#!/bin/sh

while read -r ip key; do
    ssh -i "$key" myuser@"$ip" << 'ENDSSH'
[A LOT OF STUFF]
ENDSSH
done 
Run Code Online (Sandbox Code Playgroud)

并运行它:

sh /path/to/script <  /path/to/iplist.txt
Run Code Online (Sandbox Code Playgroud)

但如果你走那条路,Stéphane 的方法会更好。

  • @Avión你是什么意思?你的脚本中有 `#!/usr/bin/env bash`。只需使脚本可执行(`chmod a+x /path/to/script`)然后直接运行它:`/path/to/script`。或者,使用`bash /path/to/script` 运行它。你使用 `sh` 的唯一原因是你使用 `sh /path/to/script` 调用它。 (3认同)

Sté*_*las 6

一种方法是while IFS=, read -r在 csv here-document 上使用循环。

#! /bin/sh -
while IFS=, read <&3 -r ip key; do
  ssh -i "$key" "$ip" << ENDSSH
  ...
ENDSSH
done 3<< ENDCSV
10.0.0.1,p1.pem
10.0.0.2,p2.pem
ENDCSV
Run Code Online (Sandbox Code Playgroud)

然后你甚至不需要要求用户安装 bash。如果不考虑可移植性,您可以zsh改用它支持循环多个变量。

#! /usr/bin/env zsh
for ip key (
  10.0.0.1 p1.pem
  10.0.0.2 p2.pem
) ssh -i $key $ip << ENDSSH
  ...
ENDSSH
Run Code Online (Sandbox Code Playgroud)