在循环中通过ssh执行远程bash脚本

时间:2014-07-08 09:56:06

标签: bash loops ssh stdin

我遇到的问题非常具体:

我有一个脚本无限期地浏览服务器列表,并在每个脚本上执行自身的副本(带有特定的参数集)。应捕获远程脚本stdout以及执行它所花费的时间。这是一个非常简单的例子:

export TIMEFORMAT="%0E seconds"
server1=localhost
index=1

if [ "$1" != "" ]
then
 cd /home
 mv -n test _test &>/dev/null
 sleep 10
 echo $1
 mv -n _test test &>/dev/null
else
 i=0
 while [ $i -lt $index ]
 do
  ((i++))
  server="server$i"
  time=/tmp/time
  echo "${!server} is doing stuff..."
  result=$((time ssh ${!server} "$(basename $0) argument" 2>/dev/null </dev/null) 2>$time)
  echo "Done in $(<$time), the result is $result"
  rm $time
 done
fi

因此,如果脚本收到一个参数,它会在本地执行(例如,重命名文件并在10秒内不执行任何操作);否则,它循环遍历服务器列表(例如,列表中只有一个服务器)并在远程主机上调用自身。 2>$timetime的stderr捕获到一个文件中,2>/dev/null让错误保持安静,</dev/null阻止ssh窃取stdin ,所以它可以安全地在循环中运行。

问题是,当用户使用ctrl+c终止脚本时,脚本的副本应该仍然优雅地终止在远程主机上(即文件重命名为初始名称),但事实并非如此。在没有循环的情况下做同样的事情很好 - 用户终止脚本,远程拷贝仍在运行并且优雅地结束,用户只是没有看到输出,这很好。我的理论是,问题与ssh处于循环中有关,</dev/null阻止它窃取stdin,但我想不出绕过这个的方法。任何建议都非常感谢。

1 个答案:

答案 0 :(得分:0)

user2303197的建议非常有意义 - 使远程脚本免受挂断信号的影响,但不幸的是,它不会影响脚本的行为。但是这个建议激发了我完全相反 - nohup ssh调用,如下所示:

result=$((time nohup ssh ${!server} "$(basename $0) argument" & 2>/dev/null </dev/null) 2>$time)

它使ssh不受ctrl+c的影响,但它会在它完成后立即打破它运行的循环,这正是我需要它做的。

编辑: 经过一周的测试,结果发现这个脚本没有按照我的意愿执行。删除与远程主机的连接后,远程脚本不会正常结束。有任何建议如何解决这个问题?

相关问题