如何在访问远程机器时在 heredoc 中 运行 for 循环

How to run for loop inside heredoc while accessing remote machine

这是我的脚本,其中我使用 heredoc 在远程机器中使用本地变量。但是 heredoc 下的循环只取第一个变量值。循环 运行 在 heredoc 中很好,但具有相同的值。

#!/bin/bash
prod_web=($(cat /tmp/webip.txt));
new_prod_app_private_ip=($(cat /tmp/ip.txt));
no_n=($(cat /tmp/serial.txt));
ssh -t -o StrictHostKeyChecking=no ubuntu@${prod_web[0]} -p 2345 -v << EOF
set -xv
for (( x = 0; x < '${#no_n[@]}'; x++ ))
do
sudo su
echo '${no_n[x]}'
echo '${new_prod_app_private_ip[x]}'
curl -fIkSs https://'${new_prod_app_private_ip[x]}':9002 | head -n 1 
done
EOF

所以,我的 ip.txt 文件包含如下值:

10.0.1.0
10.0.2.0
10.0.3.0

我的 serial.txt 文件:

9
10
11

因此,我的循环 运行 仅针对远程计算机中的第一个 IP(存在于 /tmp/ip.txt 中),循环 3 次。我想 运行 它用于所有三个 IP。我的远程 ip 存在于文件 /tmp/webip.txt.

卡住了很长时间,感谢任何帮助。我可以使用其他解决方案吗?

有 2 个环境。在您的本地机器和远程机器上。您需要考虑如何在这些机器之间传输 data/variables/state/objects/handles。 如果您在本地机器上设置了一些东西(即 prod_web=($(cat /tmp/webip.txt));),然后只是 ssh 到远程主机(即 ssh user@host 'echo "${prod_web[@]}"'),变量将不会 visible/exported 到远程机器。您可以:

  • scp 文件 {ip,serial}.txt 并在远程机器上执行整个脚本,然后清理,即。从远程机器中删除 {ip,serial}.txt 文件
  • 以某种方式将文件 {ip,serial}.txt merged/joined/pasted 传递给 ssh 的标准输入,然后在移除机器上读取标准输入
  • 在本地机器上创建 运行 的所有命令,然后将预先准备好的命令传递给远程机器,例如 ssh .... "$(for ...; do; echo curl ...; done)"

我会选择第二个选项,因为我喜欢使用管道传递所有内容并且不喜欢在我之后进行清理 - 删除临时文件以防出现错误可能会很麻烦。

我的脚本可能如下所示:

#!/bin/bash 
set -euo pipefail
read -r host _ <webip.txt
paste serial.txt ip.txt | ssh -t -o StrictHostKeyChecking=no -p 2345 -v ubuntu@"$host" '#!/bin/bash
set -euo pipefail
while read -r no_n ip; do
     for ((i = 0; i < no_n; ++i)); do
         printf "%s\n" "$no_n"
         printf "%s\n" "$ip"
         curl -fIkSs https://"$ip":9002 | head -n 1 
      done
done
'

由于远程脚本会变得越来越大而且 qouting 不太友好,我会把它保存到另一个 remote_scripts.sh 并执行 ssh ... -m remote_scripts.sh.
我不明白你想用那个 sudo su 做什么,这 100% 不符合你的要求。
如果 no_n 幻数是执行该 curl 的次数并且你有 xargs 并且你并不真正关心错误,你可以做一个神奇且令人困惑的 oneliner:

#!/bin/bash 
set -euo pipefail
read -r host _ <webip.txt
paste serial.txt ip.txt | ssh -t -o StrictHostKeyChecking=no -p 2345 -v ubuntu@"$host" 'xargs -n2 -- sh -c "seq 0 \"$1\" | xargs -n1 -- sh -c \"curl -fIkSs https://\\"\$1\\":9002 | head -n 1\" -- \"$2\"" --'

准备所有命令到 运行 可能实际上更具可读性并且可能会节省一些讨厌的 qouting 来解决。但这实际上取决于 serial.txt 和 ip.txt 的大小以及要在远程计算机上执行的命令的大小,因为您希望最小化计算机之间传输的字节数。
这里 运行 的命令是在本地机器上构造的(即“$(...)”传递给 ssh)并在远程机器上执行:

# semi-readable script, not as fast and no xargs
ssh -t -o StrictHostKeyChecking=no -p 2345 -v ubuntu@"$host" "$(paste serial.txt ip.txt | while read -r serial ip; do 
   seq 0 "$serial" | while read -r _; do
         echo "curl -fIkSs \"https://$ip:9002\" | head -n 1"
   done

完成)

HERE-doc 不扩展 shell 命令,因此:

$ cat <<EOF
> echo 1
> EOF
echo 1

但您可以使用命令替换 $( ... ):

$ cat <<EOF
> $(echo 1)
> EOF
1