linux shell 中 for 和 while 遇到的问题

案例1: while 循环体中有ssh 时,只执行一次就退出了


假设 ips 里的内容如下

192.168.0.3
192.168.0.4
192.168.0.5
192.168.0.6
...

执行ssh脚本检查这些机器的运行时间

while read ip ; do ssh $ip "uptime"; done < ips 
# 10:45:29 up 969 days, 12:44,  0 users,  load average: 2.43, 3.59, 3.35
# 后面没有了

而使用for时

for ip in $(cat running_hosts ) ; do  ssh $ip "uptime" ; done
# 10:43:07 up 969 days, 12:41,  0 users,  load average: 3.43, 3.96, 3.39
# 10:43:07 up 965 days, 20:41,  0 users,  load average: 4.04, 3.73, 3.89
# 10:43:08 up 885 days, 16:41,  0 users,  load average: 1.70, 1.42, 1.47
# 10:43:09 up 882 days, 15:41,  0 users,  load average: 1.49, 1.56, 1.62
# ...
为什么会这样呢?

原因:ssh会从stdin中读取数据,在第一次执行的时候就把stdin中的剩余行都读完了; 然后while循环就读不到数据了,因此循环就退出了。

解决办法
  1. 对ssh的stdin进行重定向,在使用管道的时候特别有效
while read ip ; do ssh $ip "uptime" < /dev/null; done < running_hosts
  1. while不使用stdin,例如使用fd编号为3的管道,或者其他fd
while read ip <&3 ; do ssh  $ip "uptime"; done 3< running_hosts

案例2: 作用域


# temp.txt 里面有100行
 
i=0
cat temp.txt | while read line 
do
    i=$(($i + 1))
done
echo $i # 0,原因是通过管道符,shell帮我启动了一个新的进程,子进程修改的是自己的局部变量,在主进程中不受影响
 
 
j=0
while read line
do
    j=$(($j + 1))
done < temp.txt
echo $j # 100
 
 
k=0
for t in $(cat temp.txt)
do
    k=$(($k + 1))
done
echo $k # 100
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 官网 中文版本 好的网站 Content-type: text/htmlBASH Section: User ...
    不排版阅读 4,499评论 0 5
  • 大纲 一.Socket简介 二.BSD Socket编程准备 1.地址 2.端口 3.网络字节序 4.半相关与全相...
    VD2012阅读 2,460评论 0 5
  • 姓名:袁永辉 学号:17101223423 转载自:http://mp.weixin.qq.com/s/85...
    AliY520阅读 1,525评论 0 0
  • 1. 硬链接和软连接区别 硬连接-------指通过索引节点来进行连接。在Linux的文件系统中,保存在磁盘分区...
    杰伦哎呦哎呦阅读 2,358评论 0 2
  • 信号信号是linux操作系统进程间通信的一种方式,一个应用进程可以接受、发送信号给另一个进程,当进程捕获到某个信号...
    zhile_doing阅读 506评论 0 0