Linux shell中的wait命令的使用
- 一:wait命令作用
- 二:使用格式
- 三:举例
- 3.1 案例一
- 3.2 案例二:函数中使用wait
- 3.3 案例三
- 3.4 案例四
- 四:串行执行与并行执行
- 4.1 串行执行
- 4.2 并行执行
- 4.3 串行与并行执行效率对比
一:wait命令作用
wait是用来阻塞当前进程的执行,直至指定的子进程执行结束后,才继续执行。使用wait可以在bash脚本“多进程”执行模式下,起到一些特殊控制的作用。
二:使用格式
1 2 | wait [进程号 或 作业号] eg:wait 23 or wait %1 |
如果wait后面不带任何的进程号或作业号,那么wait会阻塞当前进程的执行,直至当前进程的所有子进程都执行结束后,才继续执行。
wait命令用来等待指令的指令,直到其执行完毕后返回终端。
该指令常用于shell脚本编程中,待指定的指令执行完成后,才会继续执行后面的任务。如果该指令等待作业时,在作业标识号前必须添加备份号"%"。
三:举例
以下案例均在CentOS7上执行
1 2 | [root@node01 server]# cat /etc/redhat-release CentOS Linux release 7.4.1708 (Core) |
3.1 案例一
1 2 3 4 5 6 7 8 | [root@node01 server]# cat 1.sh #!/bin/bash echo "1" sleep 5 & echo "3" echo "4" wait # 会等待wait所在bash上的所有子进程的执行结束,本例中就是sleep 5这句 echo "5" |
3.2 案例二:函数中使用wait
1 2 3 4 5 6 7 8 9 10 11 12 | #!/bin/bash fun() { echo "fun is begin.timeNum: $1" local timeNum=$1 sleep $timeNum & wait echo "fun is end.timeNum: $timeNum" } fun 10 & fun 5 & wait # 如果fun里面没有wait,则整个脚本立刻退出,不会等待fun里面的sleep,fun里的sleep语句依然会在后台执行完 echo "all is ending" |
1:加上两个wait的执行结果
1 2 3 4 5 | fun is begin.timeNum:10 fun is begin.timeNum:5 fun is end.timeNum:5 fun is end.timeNum:10 all is ending # 这句话等最后一个“fun is end.timeNum:10”打印完毕后才会输出 |
2:不加两个wait的执行结果
1 2 3 4 5 6 | all is ending [root@node01 server]# fun is begin.timeNum: 10 fun is end.timeNum: 10 fun is begin.timeNum: 5 fun is end.timeNum: 5 # 注意:这里不是特地加了一个空行,而是脚本执行完成以后光标就一直停在这里 |
3.3 案例三
1 2 3 4 5 6 7 | command wait echo "$?" # 脚本里这么写echo "$?"打印的是wait命令的执行结果,不是command的执行结果,因为wait本身是一个命令; command wait "$PID" echo "$?" |
3.4 案例四
1 2 3 4 5 6 7 | cat test1 | uniq > newtest1 & cat test2 | uniq > newtest2 & wait diff newtest1 newtest2 # 为了比较newtest1和newtest2的不同,必须先让以上的两个cat命令成功并执行完成并生成newtest1和newtest2,否则diff的执行将 # 错误。。。而wait就是保证以上命令执行完成之后才执行diff命令....在以上命令执行完成之前是不会执行diff命令的 |
四:串行执行与并行执行
我们知道shell中的命令都是串行执行的,如果想要充分利用服务器的资源,就需要些小技巧了。
假定业务上多个业务逻辑没有先后关系,每个脚本的执行时间也很长 ,推荐并行执行。
4.1 串行执行
使用1.sh和2.sh两个脚本模拟业务逻辑
1 2 3 4 5 6 | [root@node01 server]# cat 1.sh #!/bin/bash echo '1.sh 开始执行......' echo '模拟业务逻辑,sleep 5秒,duang duang duang ~~~' sleep 5s echo '1.sh 执行结束......' |
1 2 3 4 5 6 | [root@node01 server]# cat 2.sh #!/bin/bash echo "2.sh 开始执行....." echo "模拟业务逻辑,sleep 5秒, duang duang duang~~~" sleep 5s echo "2.sh 执行结束....." |
我们将脚本放到 call_seria.sh脚本中
1 2 3 4 5 6 | [root@node01 server]# cat call_seria.sh #!/bin/bash #当前目录下执行如下脚本 相对路径 ./1.sh ./2.sh echo "继续执行剩下的逻辑..." |
执行 call_seria.sh脚本(注意给脚本加上执行权限)

由上面的 call_seria.sh脚本执行结果可知为串行执行
4.2 并行执行
使用&和wait改造
在每个进程中使用&符号进行让脚本在后台运行,无需等待当前进程结束。
为了确保每个进程都执行完成,最后务必使用wait关键字,用来确保每一个子进程都执行完成。
1 2 3 4 5 6 7 | [root@node01 server]# cat call_seria.sh #!/bin/bash #当前目录下执行如下脚本 相对路径 ./1.sh & ./2.sh & wait echo "继续执行剩下的逻辑..." |
执行看下效果:

由上面的 call_parallel.sh 脚本执行结果可知为并行执行
通过上述的改造,可以大大的提高多个进程并发执行的效率。 对于可以同时执行的业务逻辑,可以充分利用主机资源,减少等待时间。
4.3 串行与并行执行效率对比
串行执行的时间
1 2 3 4 5 6 7 8 9 10 11 12 13 | [root@node01 server]# cat seria.sh #!/bin/bash beginTime=`date +%s` num=1 for i in `seq 1 3` do echo $i "业务逻辑 开始执行,当前时间:" `date "+%Y-%m-%d %H:%M:%S"` sleep 2s echo $i "业务逻辑 执行完成,当前时间:" `date "+%Y-%m-%d %H:%M:%S"` echo "-----------------------------------------------------------" done endTime=`date +%s` echo "总共耗时:" $(($endTime-$beginTime)) "秒" |
执行结果

从执行结果来看,串行,每个进程都要耗时2秒,3个进程6秒处理完成
使用&和wait关键字来改造上上述脚本,使其并行执行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | [root@node01 server]# cat parallel.sh #!/bin/bash beginTime=`date +%s` num=1 for i in `seq 1 3` do { echo $i "业务逻辑 开始执行,当前时间:" `date "+%Y-%m-%d %H:%M:%S"` sleep 2s echo $i "业务逻辑 执行完成,当前时间:" `date "+%Y-%m-%d %H:%M:%S"` echo "-----------------------------------------------------------" # 结尾的&确保每个进程后台执行 } & done # wait关键字确保每一个子进程都执行完成 wait endTime=`date +%s` echo "总共耗时:" $(($endTime-$beginTime)) "秒" |
执行结果:

从执行结果来看,并行,同时启动3个进程,3个进程2秒处理完成。