我正在寻找一个简单的脚本来同时在许多主机上执行 SSH 命令,以及哪些主机是由另一个脚本生成的。问题是,当我使用像 sed 这样的 sometihng 运行脚本时,它无法正常工作。
它应该像 sshall.sh {anything here}
一样运行,它将在列表中的所有节点上运行 {anything here}
部分。
sshall.sh
#!/bin/bash
NODES=`listNodes | grep "node-[0-9*]" -o`
echo "Connecting to all nodes and running: ${@:1}"
for i in $NODES
do
:
echo "$i : Begin"
echo "----------------------------------------"
ssh -q -o "StrictHostKeyChecking no" $i "${@:1}"
echo "----------------------------------------"
echo "$i : Complete";
echo ""
done
当它用 whoami
之类的东西运行时它可以工作但是当我运行时:
[root@myhost bin]# sshall.sh sed -i '/^somebeginning/ s/$/,appendme/' /etc/myconfig.conf
Connecting to all nodes and running: sed -i /^somebeginning/ s/$/,appendme/ /etc/myconfig.conf
node-1 : Begin
----------------------------------------
sed: -e expression #1, char 18: missing command
----------------------------------------
node-1 : Complete
node-2 : Begin
----------------------------------------
sed: -e expression #1, char 18: missing command
----------------------------------------
node-2 : Complete
…
请注意,当发送到远程客户端时,sed 命令中的引号会消失。
- 我该如何修复我的 bash 命令?
- 有没有更好的方法来实现这一目标?
最佳答案
将您的命令的 eval
安全引用版本替换为 heredoc:
#!/bin/bash
# ^^^^- not /bin/sh; printf %q is an extension
# Put your command into a single string, with each argument quoted to be eval-safe
printf -v cmd_q '%q ' "$@"
while IFS= read -r hostname; do
# run bash -s remotely, with that string passed on stdin
ssh -q -o 'StrictHostKeyChecking no' "$hostname" "bash -s" <<EOF
$cmd_q
EOF
done < <(listNodes | grep -o -e "node-[0-9*]")
为什么这能可靠地工作(而其他方法不能):
printf %q
知道如何引用要由同一个 shell 评估的内容(因此将始终支持空格、通配符、各种本地引用方法等)。- 提供给
ssh
的参数 不会单独传递给远程命令! 相反,它们被连接成一个字符串,传递给sh -c
。 - 但是:
printf %q
的输出不能移植到所有 POSIX 派生的 shell!它保证与本地使用的相同 shell 兼容——ksh 将始终在 ksh 中解析来自printf '%q'
的输出,bash 将解析来自的输出bash 等中的 printf '%q'
;因此,您不能安全地将此字符串传递到远程参数向量,因为它是/bin/sh
—— 而不是bash
—— 在那里运行。 (如果你知道你的远程/bin/sh
是由 bash 提供的,那么你可以安全地运行ssh "$hostname""$cmd_q"
,但仅在这种情况下)。 bash -s
从 stdin 读取要运行的脚本,这意味着将您的命令传递到那里——而不是在参数向量上——确保它将被解析为参数逃脱它的同一个 shell 是 shell 安全的。
关于linux - Bash 命令行参数通过 ssh 传递给 sed,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41453540/