shell脚本编写过程中的一个问题
今天在写一个shell脚本的时候,使用到了ssh这个命令,在实际操作过程中遇到了一个问题,这里我把问题重新复现一下,首先,我们创建一个文件test.lst里面写上四条记录,然后是使用一个脚本循环的去调用这个文件里面的四条记录,如下:
[dba_mysql ~]$cat test.lst
111 aaa
222 bbb
333 ccc
444 ddd
[dba_mysql ~]$cat sshtest.sh
#/bin/bash
function sshtest()
{
while read line
do
array=$line
num=`echo $line | awk '{print $1}'`
letter=`echo $line | awk '{print $2}'`
echo 'num='$num,'letter='$letter
ssh -p 20022 192.168.7.194 "sudo date"
done < test.lst
}
sshtest
[dba_mysql ~]$sh sshtest.sh
num=111,letter=aaa
Tue Mar 19 23:45:37 CST 2019
我们可以看到,最终的结果中只输出了一条记录,而我们的脚本实际上是让它循环执行的,这其中的原因一开始我也搞不清楚,于是查询了一下网上的资料,然后才明白.
首先我们需要明白while循环中使用了重定向机制,test.lst 文件中的全部信息都已经读入并重定向给了while语句。所以当我们在while循环中再一次调用read语句,就会读取到下一条记录。问题就出在这里,ssh语句正好会读取输入中的所有东西,所以这个line的值一次性被ssh读完了,也就没有了下一次循环的缓存。
要想解决这个问题,我们需要通过/dev/null的方式对ssh进行重定向,或者通过ssh的-n参数进行重定向,如下:
[dba_mysql ~]$cat sshtest.sh
#/bin/bash
function sshtest()
{
while read line
do
array=$line
num=`echo $line | awk '{print $1}'`
letter=`echo $line | awk '{print $2}'`
echo 'num='$num,'letter='$letter
ssh -p 20022 192.168.x.xxx "sudo date" < /dev/null
done < test.lst
}
sshtest
[dba_mysql ~]$sh sshtest.sh
num=111,letter=aaa
Tue Mar 19 23:55:42 CST 2019
num=222,letter=bbb
Tue Mar 19 23:55:42 CST 2019
num=333,letter=ccc
Tue Mar 19 23:55:42 CST 2019
num=444,letter=ddd
Tue Mar 19 23:55:42 CST 2019
可以看到,通过使用/dev/null,我们让这个脚本循环执行了,见第11行代码。
除了使用显示的/dev/null方法,我们也可以使用ssh的-n参数来实现,这里不再试验,有兴趣可以尝试下。