先看有问题的代码:
#!/bin/bash
cat file.txt | while read eachline ; do
echo $eachline
done
上例中,while代码块的输入流已经被管道符重定向至cat的输出,
所以如果在while代码块内,有sed、awk、ssh 等命令时,会在第一次循环时,一次性读取输入流内容的所有行。
这样read命令在第二次运行时,输入流的内容已经是空的,read就读取不到内容,从而结束循环。
为了避免上面的问题,可以参考这样的处理方式:
假如,/etc/hosts的内容有
192.168.12.6 host_a
192.168.12.9 host_b
192.168.12.18 host_c
192.168.12.19 host_d
用这段代码处理:
cat /etc/hosts | grep host | while read v1 v2
do
exec 8<& 0 0< /dev/null
ssh $v2 "hostname"
exec 0<& 8 8<& -
done
运行以上代码后,输出结果为:
host_a
host_b
host_c
host_d
FD=文件标示符(File Descriptor)
exec 8<& 0 0< /dev/null
这句会将FD=8的输入重定向到FD=0所使用的输入设备,然后将FD=0的输入重定向到/dev/null。
这样,ssh就不会影响到read在下一次要读取的内容。
exec 0<& 8 8<& -
这句会将FD=0的输入重定向到FD=8所使用的输入设备(也就是cat的输出内容),然后关闭FD=8的输入,使其他程序可以使用FD=8。