最近完善优化inotify脚本,由于队列长时会有很长等待,于是考虑多线程实现。
由于所要执行的程序本身就是在循环里面的,所以以下面脚本示例:
[root@Test ~]# vim t.sh
#!/bin/bash get_time () { date +%H:%M:%S | awk -F : '{print $1*3600 + $2*60 + $3}' } pre_time=`get_time` for i in {1..10} do last_time=`get_time` sleep 3 now_time=`get_time` dint=$((${now_time} - ${last_time})) echo cycle $i use time $dint total use time $((${now_time} - ${pre_time})) done
[root@Test ~]# chmod +x t.sh [root@Test ~]# ./t.sh cycle 1 use time 3 total use time 3 cycle 2 use time 3 total use time 6 cycle 3 use time 3 total use time 9 cycle 4 use time 3 total use time 12 cycle 5 use time 3 total use time 15 cycle 6 use time 3 total use time 18 cycle 7 use time 3 total use time 21 cycle 8 use time 3 total use time 24 cycle 9 use time 3 total use time 27 cycle 10 use time 3 total use time 30
可以看到循环10次用了30秒,shell脚本中实现多线程的方法其实是将需要多线程执行的任务放入后台执行:
[root@Test ~]# vim t.sh
#!/bin/bash get_time () { date +%H:%M:%S | awk -F : '{print $1*3600 + $2*60 + $3}' } pre_time=`get_time` for i in {1..10} do { last_time=`get_time` sleep 3 now_time=`get_time` dint=$((${now_time} - ${last_time})) echo cycle $i use time $dint total use time $((${now_time} - ${pre_time})) } & done
[root@Test ~]# ./t.sh ; ps PID TTY TIME CMD 5005 pts/0 00:00:00 bash 5736 pts/0 00:00:00 t.sh 5738 pts/0 00:00:00 sleep 5741 pts/0 00:00:00 t.sh 5743 pts/0 00:00:00 sleep 5746 pts/0 00:00:00 t.sh 5748 pts/0 00:00:00 sleep 5751 pts/0 00:00:00 t.sh 5753 pts/0 00:00:00 sleep 5756 pts/0 00:00:00 t.sh 5758 pts/0 00:00:00 sleep 5761 pts/0 00:00:00 t.sh 5763 pts/0 00:00:00 sleep 5766 pts/0 00:00:00 t.sh 5768 pts/0 00:00:00 sleep 5771 pts/0 00:00:00 t.sh 5773 pts/0 00:00:00 sleep 5776 pts/0 00:00:00 t.sh 5778 pts/0 00:00:00 sleep 5781 pts/0 00:00:00 t.sh 5782 pts/0 00:00:00 sleep 5783 pts/0 00:00:00 ps cycle 1 use time 3 total use time 3 cycle 2 use time 3 total use time 3 cycle 3 use time 3 total use time 3 cycle 4 use time 3 total use time 3 cycle 5 use time 3 total use time 3 cycle 6 use time 3 total use time 3 cycle 7 use time 3 total use time 3 cycle 8 use time 3 total use time 3 cycle 9 use time 3 total use time 3 cycle 10 use time 3 total use time 3
可以看到,10次循环全部一起执行了。
如需有效控制后台进程数量,需要使用mkfifo、exec这两个命令。
- mkfifo 使用指定的文件名创建FIFO(也称为”命名管道”).
“FIFO”是一种特殊的文件类型,它允许独立的进程通讯. 一个进程打开FIFO文件进行写操作,而另一个进程对之进行读操作, 然后数据便可以如同在shell或者其它地方常见的的匿名管道一样流线执行.
如,创建一个fifo文件,将screen log“记录”到里面,在另一个终端上查看:
[root@Test ~]# mkfifo sc.log [root@Test ~]# script -f sc.log
之后屏幕是处于等待状态,要有另一个进程在读方可正常,打开另一个终端进程查看:
[root@Test ~]# cat sc.log Script started on 2016年07月18日 星期一 13时39分43秒
这时便已开始记录。
这进第二个终端是处于查看状态,是不接受命令的,在第一个终端使用CRTL+D可进行退出:
- exec介绍:http://blog.csdn.net/cyberrusher/article/details/7253385
exec和source都属于bash内部命令(builtins commands),source命令是在当前进程中执行参数文件中的各个命令,而不是另起子进程(或sub-shell)。exec命令在执行时会把当前的shell process关闭,然后换到后面的命令继续执行。
举个栗子:
可以看到,执行完exec ls之后自动退出了。
[root@Test ~]# ls 1.sh anaconda-ks.cfg apache-tomcat-8.0.28.tar.gz inotify.sh inotify-tools-3.14.tar.gz install.log install.log.syslog jdk-8u91-linux-x64.tar.gz t.sh [root@Test ~]# exec > test [root@Test ~]# ls [root@Test ~]# pwd [root@Test ~]# echo "hello world" [root@Test ~]# exec > /dev/tty [root@Test ~]# ls 1.sh anaconda-ks.cfg apache-tomcat-8.0.28.tar.gz inotify.sh inotify-tools-3.14.tar.gz install.log install.log.syslog jdk-8u91-linux-x64.tar.gz test t.sh [root@Test ~]# cat test 1.sh anaconda-ks.cfg apache-tomcat-8.0.28.tar.gz inotify.sh inotify-tools-3.14.tar.gz install.log install.log.syslog jdk-8u91-linux-x64.tar.gz test t.sh /root hello world [root@Test ~]#
exec >text 是将当前shell的标准输出都打开到text文件中。
exec I/O重定向, I/O重定向通常与 FD文件描述符有关,shell的FD通常为10个,即 0~9;在/dev/fd/目录下可以看到系统预定义的FD。
[root@Test ~]# ll /dev/fd/ 总用量 0 lrwx------. 1 root root 64 7月 18 11:12 0 -> /dev/pts/0 lrwx------. 1 root root 64 7月 18 11:12 1 -> /dev/pts/0 lrwx------. 1 root root 64 7月 18 11:12 2 -> /dev/pts/0 lr-x------. 1 root root 64 7月 18 11:12 3 -> /proc/8511/fd [root@Test ~]#
0为标准输入,通常为键盘。
1为标准输出
2为标准错误输出
3为当前进程
创建一个新的描述附FD,可以使用exec 4>point命令,这样就相当于创建了一个fd4的管道,如:
[root@Test ~]# exec 4>/root/point [root@Test ~]# ls 1.sh apache-tomcat-8.0.28.tar.gz inotify-tools-3.14.tar.gz install.log.syslog point anaconda-ks.cfg inotify.sh install.log jdk-8u91-linux-x64.tar.gz t.sh [root@Test ~]# ll /dev/fd/ 总用量 0 lrwx------. 1 root root 64 7月 18 11:37 0 -> /dev/pts/0 lrwx------. 1 root root 64 7月 18 11:37 1 -> /dev/pts/0 lrwx------. 1 root root 64 7月 18 11:37 2 -> /dev/pts/0 lr-x------. 1 root root 64 7月 18 11:37 3 -> /proc/8572/fd l-wx------. 1 root root 64 7月 18 11:37 4 -> /root/point [root@Test ~]#
这时向管道4里丢入数据,都会重定向到point文件中,关闭这个FD使用exec 4>&-命令:
[root@Test ~]# w >&4 [root@Test ~]# ls >&4 [root@Test ~]# cat point 11:43:47 up 36 days, 13 min, 3 users, load average: 0.00, 0.00, 0.00 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT root tty1 - 12Jun16 35days 0.26s 0.26s -bash root pts/0 172.16.*.182 11:34 0.00s 0.08s 0.04s w root pts/1 172.16.*.182 11:22 20:56 0.02s 0.02s -bash 1.sh anaconda-ks.cfg apache-tomcat-8.0.28.tar.gz inotify.sh inotify-tools-3.14.tar.gz install.log install.log.syslog jdk-8u91-linux-x64.tar.gz point t.sh [root@Test ~]# exec 4>&- [root@Test ~]# ll /dev/fd/ 总用量 0 lrwx------. 1 root root 64 7月 18 11:45 0 -> /dev/pts/0 lrwx------. 1 root root 64 7月 18 11:45 1 -> /dev/pts/0 lrwx------. 1 root root 64 7月 18 11:45 2 -> /dev/pts/0 lr-x------. 1 root root 64 7月 18 11:45 3 -> /proc/8579/fd [root@Test ~]#
通道4已关闭。
上面是小插曲,言归正转,控制后台进程数量:
[root@Test ~]# vim t.sh
#!/bin/bash thread=2 get_time () { date +%H:%M:%S | awk -F : '{print $1*3600 + $2*60 + $3}' } # 创建FIFO文件 fifofile="/tmp/$.fifo" mkfifo ${fifofile} # 定义FD4并指向此文件 exec 4<>${fifofile} rm -rf ${fifofile} # 向FD4中放置了${thread}个空格 for ((p=0;p<${thread};p++)) do echo done>&4 pre_time=`get_time` for i in {1..10} do { # 从FD4中读取(占用)一个空行,FD4中没有空行时就会停在此处,从而控制线程数量 read -u 4 last_time=`get_time` sleep 3 now_time=`get_time` dint=$((${now_time} - ${last_time})) echo cycle $i use time $dint total use time $((${now_time} - ${pre_time})) # 补充回一个空行 echo >&4 } & done exec 4>&-
为了方便理解,我将上面的几条单独拿出来执行,即可看到现象:
执行我们的脚本:
[root@Test ~]# ./t.sh cycle 1 use time 3 total use time 3 cycle 2 use time 3 total use time 3 cycle 10 use time 3 total use time 6 cycle 3 use time 3 total use time 6 cycle 7 use time 3 total use time 9 cycle 6 use time 3 total use time 9 cycle 4 use time 3 total use time 12 cycle 9 use time 3 total use time 12 cycle 8 use time 3 total use time 15 cycle 5 use time 3 total use time 15 [root@Test ~]#
已达预期效果,后台线程每两个两个进行执行。