Shell脚本调用ssh:如何解释远程服务器上的通配符

时间:2014-03-06 11:16:28

标签: shell ssh ksh

我每天都在某个客户环境中工作,由5台AIX服务器组成,有时候我需要在所有5台服务器上发出相同的命令。

所以我在服务器之间设置了基于SSH密钥的身份验证,并启动了一个向所有服务器广播命令的ksh脚本:

#!/usr/bin/ksh

if [[ $# -eq 0 ]]; then
        print "broadcast.ksh - broadcasts a command to the 5 XXXXXXXX environments and returns output for each"
        print "usage:                   ./broadcast.ksh command_to_issue"
        exit
fi

set -A CUST_HOSTS aaa bbb ccc ddd eee

for host in ${CUST_HOSTS[@]}; do

        echo "============ $host ================"

        if [[ `uname -n` = $host ]]; then
                $*
                continue
        fi

        ssh $host $*

done

echo "========================================="
echo "Finished"

现在,这很好用,直到我想在远程端使用通配符,例如:

./broadcast.ksh ls -l java*

因为'*'在本地系统上展开而不是遥控器。

现在,如果使用ssh远程命令,我可以通过使用单引号来解决这个问题:

ssh user@host ls -l java*    <-- will _not_ work as expected, since asterisk will be interpreted locally
ssh user@host 'ls -l java*'   <-- _will_ work as expected, since asterisk will be interpreted on the remote end

现在,我已经尝试将其合并到我的脚本中,并尝试创建一个由单引号括起来的$ *内容组成的$命令变量,但是已经淹没在逃避反斜杠和ksh中的连接尝试的海洋中,无济于事。

我确信这有一个简单的解决方案,但我找不到它,所以我想出来问问。

谢谢,

詹姆斯

2 个答案:

答案 0 :(得分:1)

如您所见,将星号作为参数传递给您的脚本不起作用,因为shell会在处理参数之前展开它。尝试使用双引号$*并在脚本调用中使用反斜杠转义星号/分号等,或单引号命令。

for host in ${CUST_HOSTS[@]}; do
    echo "============ $host ================"
    if [[ `uname -n` = $host ]]; then
        "$*"
        continue
    fi
    ssh $host "$*"
done

$ ./broadcast.ksh ls -l java\*

$ ./broadcast.ksh 'ls -l java*; ls -l *log'

答案 1 :(得分:1)

我想发表评论但仍然太低,但Josh的单引号建议应该有效。

  • 我用/ tmp:/ tmp / foo1和/ tmp / foo2
  • 中的两个文件分别发了几个vms
  • 然后使用了脚本的变体
root@jdsdrop1:~# cat foo.sh
#!/usr/bin/ksh

if [[ $# -eq 0 ]]; then
        print "broadcast.ksh - broadcasts a command to the 5 XXXXXXXX environments and returns output for each"
        print "usage:                   ./broadcast.ksh command_to_issue"
        exit
fi

set -A CUST_HOSTS jdsdropfed1 jdsdropfed2-2

for host in ${CUST_HOSTS[@]}; do

        echo "============ $host ================"

        if [[ `uname -n` = $host ]]; then
                $*
                continue
        fi

        ssh $host $*

done

echo "========================================="
echo "Finished"
root@jdsdrop1:~# ./foo.sh 'ls /tmp/foo*'
============ jdsdropfed1 ================
/tmp/foo1
/tmp/foo2
============ jdsdropfed2-2 ================
/tmp/foo1
/tmp/foo2
=========================================
Finished
root@jdsdrop1:~# ssh jdsdropfed1 "ls /tmp/foo*"
/tmp/foo1
/tmp/foo2
root@jdsdrop1:~# ssh jdsdropfed2-2. "ls /tmp/foo*"
/tmp/foo1
/tmp/foo2