红联Linux门户
Linux帮助

Shell脚本中&与&&的优先级

发布时间:2016-10-25 09:52:45来源:linux网站作者:p_fly
命令介绍
& 放在启动参数后面表示设置此进程为后台进程
command &
&& 用于控制命令的执行顺序,一般形式为:
command1 && command2
命令的详细介绍网上有很多文档,在此就不详细列举了。
但不知道有没有人考虑过,如下命令的执行顺序是什么?在某些场景下是否存在副作用?
command1 && command2 &
 
实验分析
例一 验证命令执行顺序
创建脚本 test_a.sh:
#!/bin/bash
echo "test_a.sh begin"
sleep 5 && echo "sleep 5" &
echo "test_a.sh end"
运行 sh test_a.sh,执行结果:
root@ubuntu:/home/permitted# sh test_a.sh
test_a.sh begin
test_a.sh end
root@ubuntu:/home/permitted# sleep 5
结果分析:
通过脚本实测可以发现,命令的执行顺序为 (command1 && command2) &,即
sleep 5 && echo "sleep 5"
被整体放在后台执行,所以现象为 “test_a.sh begin” 和 “test_a.sh end” 的打印几乎同时出现,而 “sleep 5” 的打印等待了5秒钟才出现。
 
例二 command2为周期任务时的副作用
创建脚本 test_b.sh
#!/bin/bash
echo "test_b.sh begin"
[ -f test_c.sh ] && sh test_c.sh &
echo "test_b.sh end"
创建脚本 test_c.sh
#!/bin/bash
echo "test_c.sh running"
while [ true ]
do
sleep 5
#此处可以添加周期任务的具体操作
done
运行 sh test_b.sh,执行结果:
root@ubuntu:/home/permitted# sh test_b.sh
test_b.sh begin
test_b.sh end
root@ubuntu:/home/permitted# test_c.sh running
从执行结果表面上来看,脚本test_b.sh已经完成了功能,脚本test_c.sh的后台周期任务也已经启动,似乎一切没有什么问题。
但如果用ps命令查看当前的进程,可以惊喜的发现test_b.sh的脚本并没有释放:
root@ubuntu:/home/permitted# ps aux | grep test_ | grep -v grep
root     12244  0.0  0.1   4208   644 pts/1    S    02:30   0:00 sh test_b.sh
root     12245  0.3  0.2   4204  1272 pts/1    S    02:30   0:00 sh test_c.sh
对此,个人理解为command1 && command2同时在后台执行时,因为command2为周期任务不会退出,那么整个&&的表达式的结果就没法返回,而test_b.sh需要等待所有命令结束后才能退出,故此时test_b.sh会一直存在,没有结束。
我们对 test_c.sh 进行如下修改:
#!/bin/bash
echo "test_c.sh running"
while [ true ]
do
if [ -f test_exit.ini ]
then
exit
fi
sleep 5
#此处可以添加周期任务的具体操作
done
此时重复上述操作,当我们创建test_exit.ini的文件时,test_b.sh和test_c.sh均正常结束,可见test_b.sh在等待test_c.sh完成后才退出。
 
实际中遇到的问题
问题现象
对设备进行恢复出厂设置,即:
umount掉U盘上的用户配置分区
将这部分用户配置分区进行格式化
但在第一步时出现Device is busy,恢复出厂设置失败。
 
问题定位过程
首先分析出现Device is busy的原因:某个程序正在使用U盘上的目录,造成该目录不能卸载
通过leof命令抓取该目录的占用进程,发现是启动脚本,而启动脚本居然在启动结束后没有退出
通过调试启动脚本发现其问题代码如下:
cd /conf                                #该目录为U盘目录,此时该路径被占用
[ -f ntp.conf ] && sh ntp_task.sh &     #此处造成启动脚本未结束,即U盘路径始终被占用
 
总结
1.路径也是一种资源,当进入其它路径处理完问题后应该退回到原有路径下
2.定位目录或文件资源未释放的问题时,可以使用leof命令抓取文件资源情况进行分析
3.以前一直以为Shell的运行顺序为从左到右依次执行,实际上并不是,以后使用&&或||等命令时需要特别注意
 
本文永久更新地址:http://www.linuxdiyf.com/linux/25370.html