从 bash 脚本中通过 ssh 在远程主机上执行命令
Posted
技术标签:
【中文标题】从 bash 脚本中通过 ssh 在远程主机上执行命令【英文标题】:Execute a command on remote hosts via ssh from inside a bash script 【发布时间】:2012-01-12 15:40:54 【问题描述】:我编写了一个 bash 脚本,它应该从文件中读取用户名和 IP 地址并通过 ssh 对它们执行命令。
这是 hosts.txt :
user1 192.168.56.232
user2 192.168.56.233
这是 myScript.sh :
cmd="ls -l"
while read line
do
set $line
echo "HOST:" $1@$2
ssh $1@$2 $cmd
exitStatus=$?
echo "Exit Status: " $exitStatus
done < hosts.txt
问题是在第一个主机完成后执行似乎停止了。这是输出:
$ ./myScript.sh
HOST: user1@192.168.56.232
total 2748
drwxr-xr-x 2 user1 user1 4096 2011-11-15 20:01 Desktop
drwxr-xr-x 2 user1 user1 4096 2011-11-10 20:37 Documents
...
drwxr-xr-x 2 user1 user1 4096 2011-11-10 20:37 Videos
Exit Status: 0
$
为什么会有这样的行为,我该如何解决?
【问题讨论】:
【参考方案1】:在您的脚本中,ssh
作业与read line
获得相同的标准输入,并且在您的情况下,恰好在第一次调用时吃光了所有行。所以read line
只能看到
输入的第一行。
解决方案:关闭ssh
的标准输入,或者更好地从/dev/null
重定向。 (一些程序
不喜欢关闭标准输入)
while read line
do
ssh server somecommand </dev/null # Redirect stdin from /dev/null
# for ssh command
# (Does not affect the other commands)
printf '%s\n' "$line"
done < hosts.txt
如果您不想为循环内的每个作业从 /dev/null 重定向,您也可以尝试以下方法之一:
while read line
do
commands...
</dev/null # Redirect stdin from /dev/null for all
# commands inside the braces
done < hosts.txt
# In the following, let's not override the original stdin. Open hosts.txt on fd3
# instead
while read line <&3 # execute read command with fd0 (stdin) backed up from fd3
do
commands... # inside, you still have the original stdin
# (maybe the terminal) from outside, which can be practical.
done 3< hosts.txt # make hosts.txt available as fd3 for all commands in the
# loop (so fd0 (stdin) will be unaffected)
# totally safe way: close fd3 for all inner commands at once
while read line <&3
do
commands...
3<&-
done 3< hosts.txt
【讨论】:
【参考方案2】:您遇到的问题是 SSH 进程正在消耗所有标准输入,因此在第一个 ssh 命令运行后 read 看不到任何输入。您可以使用 SSH 的 -n 标志来防止这种情况发生,或者您可以将 /dev/null 重定向到 ssh 命令的标准输入。
有关详细信息,请参阅以下内容: http://mywiki.wooledge.org/BashFAQ/089
【讨论】:
【参考方案3】:确保ssh
命令不会使用ssh -n
从hosts.txt 中读取
【讨论】:
它没有。它只使用 while 循环中的变量:ssh $1@$2 $cmd
然后试试echo|ssh $1@$2 $cmd
@kavakli ...看看会发生什么【参考方案4】:
我觉得你的问题不必要地冗长..
基本上你应该能够重现问题:
while read line
do
echo $line
done < hosts.txt
哪个应该可以正常工作..您编辑了正确的文件吗?里面有特殊字符吗?使用适当的编辑器(例如:vim)检查它。
【讨论】:
他可能无法重现该问题,因为 echo 不读取标准输入。以上是关于从 bash 脚本中通过 ssh 在远程主机上执行命令的主要内容,如果未能解决你的问题,请参考以下文章
怎么在一个shell脚本中执行远程主机的另一个shell脚本?? ssh已经可以无密码登录了。
通过 ssh 会话执行 bash 别名 | Linux 中国