为什么bash循环部署脚本似乎只工作一次?

时间:2010-04-13 07:52:43

标签: deployment shell

我有一些简单的脚本,用于菊花链连接在一组服务器上运行特定脚本,所有服务器都列在文件中,每行一个。

单服务器部署脚本包含以下内容:

  1 #!/bin/bash
  2 
  3 file=$1
  4 host=$2
  5 
  6 scp ${file} ${host}:/tmp/
  7 USER=`whoami`
  8 ssh -t -t $USER@${host} /tmp/${file}
  9 
 10 ssh "${host}" /bin/rm /tmp/${file}
 11 exit

它在我所拥有的脚本上工作正常,yum安装tomcat和symlinks hadoop / hbase配置到共享类目录。

第二个主要文件是deploy-all.sh,用于解析主机列表并对所有主机运行部署脚本:

  1 #!/bin/bash
  2 
  3 script=$1
  4 
  5 cat dumbo-hosts | while read fileline
  6 do
  7 echo ${fileline}
  8 ./deploy.sh ${script} ${fileline}
  9 
 10 sleep 10
 11 done

发生的事情是脚本运行一次,然后for循环被破坏......我得到类似下面的输出:

$ ./deploy-all.sh setup-tomcat.sh 
line is hadoop01.myhost
setup-tomcat.sh                               100%  455     0.4KB/s   00:00    
tcgetattr: Inappropriate ioctl for device
hadoop02.myhost
hadoop03.myhost
hadoop04.myhost
<succesful output of hadoop01 task>
...
Connection to hadoop01.myhost closed.

如果我注释掉ssh命令,循环会在所有4个主机上成功运行,所以我认为这是sd一旦ssh发生时stdio被切断的事情。另外tcgatattr错误让我有点担心。

我该如何解决这个问题?究竟是什么导致tcgetattr错误(我甚至不确定它是否相关)? 没有真正用shell脚本做很多事情,很抱歉,如果我遗漏了一些非常明显的东西,我们将不胜感激。

2 个答案:

答案 0 :(得分:1)

当作为子进程的一部分运行时,ssh重用stdin文件描述符是一个问题。

解决方法是在从非终端上下文调用ssh时使用'-n'。

option=-n
tty -s 2>/dev/null && option=

scp ${file} ${host}:/tmp/
ssh $option -t ${host} /tmp/${file}
ssh $option ${host} rm /tmp/${file}

答案 1 :(得分:0)

我通过使用bash数组暂时将行存储到数组中以避免stdin中断来解决这个问题...但是感觉不对...如果有人有更好的解决方法,请告诉我。< / p>

这是我的解决方案:

  1 #/bin/bash
  2 
  3 #myscript = $1
  4 count=0
  5 
  6 declare -a lines
  7 
  8 while read line
  9 do
 10   lines[$count]=$line
 11   ((count++))
 12 done < dumbo-hosts
 13 
 14 for i in "${lines[@]}"
 15 do
 16   echo "$i"
 17   ./deploy.sh "$1" "${i}"
 18 done