【发布时间】:2017-05-18 03:17:42
【问题描述】:
我希望编写一个简单的脚本来同时在许多主机上执行 SSH 命令,并且哪些主机是从另一个脚本生成的。问题是当我使用 sed 之类的东西运行脚本时,它不能正常工作。
它应该像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 命令?
- 有没有更好的方法来实现这一点?
【问题讨论】:
-
你可能想说
sshall.sh $(sed -i '/^somebeginning/ s/$/,appendme/' /etc/myconfig.conf)。也就是说,使用命令sed ...的输出来馈送sshall.sh。 -
我不这么认为,我实际上想在每个节点(节点 1-n)上运行
sed命令,而不是我从中运行命令的节点;除非它实际上会在每个节点上运行它? -
嗯,我明白了。但是,这很奇怪:您将完整的 sed 命令作为一组参数传递给脚本。它看起来非常脆弱。另外,
listNodes是什么? -
当您开始转义空格以便可以在远程计算机上运行命令时,它变得太复杂了,创建一个脚本文件几乎肯定会更好,将它复制到目标主机,然后运行它,而不是花时间计算你的命令行被评估了多少次,这样你就可以得到正确的转义量。如果这过于激进,请确保您不需要空格:
sshall.sh sed -i '/^somebeginning/s/$/,appendme/' /etc/myconfig.conf。如果你需要处理空格,那就很难了。 -
有(可能)有办法做到这一点;它们并不容易——根据我的经验,它们也不是万无一失的,因为一些该死的傻瓜(通常是我)找到了一种新的方法来破坏事物。 OTOH,复制脚本并执行它——无需过多努力就可以做到近乎万无一失。 (请注意,
whoami(和who am i)之所以有效,是因为您不必担心在参数中保留空格并且不处理元字符。)