Chinaunix首页 | 论坛 | 博客
  • 博客访问: 399250
  • 博文数量: 119
  • 博客积分: 25
  • 博客等级: 民兵
  • 技术积分: 1061
  • 用 户 组: 普通用户
  • 注册时间: 2012-10-14 12:48
个人简介

醉心于技术。

文章分类

全部博文(119)

文章存档

2018年(34)

2016年(1)

2015年(4)

2014年(6)

2013年(74)

我的朋友

分类: 系统运维

2013-09-03 22:04:02


我们用while read对文件里面的内容读取然后执行ssh远程命令的时候,会碰到while read只能对文件里面的第一行执行操作,之后会就跳出来。例如:


  1. [nanhuang@nanhuang etc]$ cat hostlist | while read i ;do sshpass -p 'anything' ssh -l root $i 'date';done
  2. Tue Sep 3 13:52:18 GMT 2013
  3. [nanhuang@nanhuang etc]$

解决办法如下:

1. 回避使用cat,利用while read i;do ;done< filename.txt代替。例如:

  1. [nanhuang@nanhuang etc]$ while read i;do sshpass -p 'anything' ssh -e '|' -l root $i 'date';done < hostlist
  2. Tue Sep 3 14:00:39 GMT 2013
  3. Tue Sep 3 14:00:40 GMT 2013
  4. Tue Sep 3 14:00:41 GMT 2013
  5. ...


另外,在while之后可以设置IFS,如果要回避特殊字符转义,可以使用 read -r代替单独的 read。


2. 使用for i in $();do;done代替cat | while read。例如:

  1. [nanhuang@nanhuang etc]$ for i in `cat hostlist`;do sshpass -p 'anything' ssh -l root $i 'date';done
  2. Tue Sep 3 15:10:54 GMT 2013
  3. Tue Sep 3 15:10:55 GMT 2013
  4. ...

3. 但是如果没有文件只有echo返回的值呢?不论cat还是echo,while read读取管道传过来的值都只能执行一行。所有的read参数都不能解决这个问题。最终解决方法!

根本原因:
究其原因,是因为管道后相当于一个子程序,这里是while子程序。而SSH执行的远程命令则是while子程序的子程序。相当于while子程序下跑了另一个子程序。相反,while readi;do;done
解决办法 : 子程序的子程序SHELL依旧支持,只是在子程序的子程序还没有获得结果的时候,上一级子程序就已经退出了。所以,我们只能看到一行的返回结果。如果我们把子程序包在 ()&里,并且后面跟wait。那么父程序要等到子程序完成后才退出。如果()& wait和do...done循环合用的话。)&和wait之间不能加分号';'。

例如:
  1. [nanhuang@nanhuang etc]$ echo '
  2. hostname2server-china01.china.online.com
  3. hostname2server-china02.china.online.com
  4. hostname2server-china03.china.online.com
  5. hostname2server-china04.china.online.com
  6. hostname2server-china05.china.online.com
  7. hostname2server-china06.china.online.com
  8. hostname2server-china07.china.online.com
  9. hostname2server-china08.china.online.com
  10. hostname2server-china09.china.online.com
  11. hostname2server-china10.china.online.com
  12. hostname2utl01.china.online.com' | grep -oE '[^ ]*\.com' | while read i;do(sshpass -p 'anything' ssh -l root $i 'date')& wait ;done
这样,while子程序要等到()&里的所有程序结束才能退出。


参考
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
read [-ers] [-a aname] [-d delim] [-i text] [-n nchars] [-N nchars] [-p prompt] [-t timeout] [-u fd] [name ...]
              One  line  is  read  from the standard input, or from the file descriptor fd supplied as an argument to the -u option, and the first word is assigned to the first name, the second word to the second name, and so on, with leftover
              words and their intervening separators assigned to the last name.  If there are fewer words read from the input stream than names, the remaining names are assigned empty values.  The characters in IFS are used to split  the  line
              into words.  The backslash character (\) may be used to remove any special meaning for the next character read and for line continuation.  Options, if supplied, have the following meanings:
              -a aname
                     The words are assigned to sequential indices of the array variable aname, starting at 0.  aname is unset before any new values are assigned.  Other name arguments are ignored.
              -d delim
                     The first character of delim is used to terminate the input line, rather than newline.
              -e     If the standard input is coming from a terminal, readline (see READLINE above) is used to obtain the line.  Readline uses the current (or default, if line editing was not previously active) editing settings.
              -i text
                     If readline is being used to read the line, text is placed into the editing buffer before editing begins.
              -n nchars
                     read returns after reading nchars characters rather than waiting for a complete line of input, but honor a delimiter if fewer than nchars characters are read before the delimiter.
              -N nchars
                     read  returns  after reading exactly nchars characters rather than waiting for a complete line of input, unless EOF is encountered or read times out.  Delimiter characters encountered in the input are not treated specially
                     and do not cause read to return until nchars characters are read.
              -p prompt
                     Display prompt on standard error, without a trailing newline, before attempting to read any input.  The prompt is displayed only if input is coming from a terminal.
              -r     Backslash does not act as an escape character.  The backslash is considered to be part of the line.  In particular, a backslash-newline pair may not be used as a line continuation.
              -s     Silent mode.  If input is coming from a terminal, characters are not echoed.
              -t timeout
                     Cause read to time out and return failure if a complete line of input is not read within timeout seconds.  timeout may be a decimal number with a fractional portion following the decimal point.  This option is only  effec-
                     tive  if  read is reading input from a terminal, pipe, or other special file; it has no effect when reading from regular files.  If timeout is 0, read returns success if input is available on the specified file descriptor,
                     failure otherwise.  The exit status is greater than 128 if the timeout is exceeded.
              -u fd  Read input from file descriptor fd.

              If no names are supplied, the line read is assigned to the variable REPLY.  The return code is zero, unless end-of-file is encountered, read times out (in which case the return code is  greater  than  128),  or  an  invalid  file
              descriptor is supplied as the argument to -u.











阅读(4626) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~