案例1 通过文件描述符控制并发数
function mima(){
openssl rand -base64 40 >> ssf.txt
}
if [ -e /tmp/$$.fifo ];then
rm -rf /tmp/$$.fifo
fi
fifo_file=/tmp/$$.fifo
mkfifo $fifo_file
exec 6<>"$fifo_file"
process_num=10
for ((i=0;i<$process_num;i++))
do
echo
done >&6
for ((a=0;a<10;a++))
do
read -u6
{
mima
sleep 3
echo >&6
} &
done
wait
exec 6>&-
案例2 通过xargs命令实现多线程并发
xargs命令解析
-0:如果输入的stdin含有特殊字符,例如反引号`、反斜杠\、空格等字符时,xargs可以将它还原成一般字符。为xargs的默认选项。
-e <flag>,-E <flag>,--eof=<eof-str>:eof是end of file string的意思。flag可以是一个字符串或者是由空格分隔的多个字符串,当xargs分析到这个flag时,就会停止工作。
-p:当每次执行一个argument的时候询问一次用户。
-n <num>:表示命令在执行的时候一次使用的argument的个数,由num指定,默认是用所有的参数。
-t:表示先打印命令,然后再执行。
-a <file>:从文件中读入作为sdtin。
-i,-I:其中-I某些Linux版本不支持。将xargs的输出每一项参数,单独赋值给后面的命令,参数需要用{}代替。
-r:或者--no-run-if-empty,当xargs的输入为空的时候则停止xargs,不用再去执行后面的命令了,-r是xargs的默认选项。
-s <num>:命令行的最大字符数,指的是xargs后面那个命令的最大命令行字符数,包括命令、空格和换行符。每个参数单独传入xargs后面的命令。
-L <line_num>:设置标准输入中最大的行数作为命令每一次执行的参数。
-d <delim>, --delimiter=<delim>: xargs处理标准输入默认是按换行符和空格作为分隔符,输出arguments的分隔符是空格,这里修改xargs处理标准输入时的分隔符。
-x:eXit的意思,主要是配合-s使用,当命令行字符数大于-s指定的数值时,退出xargs。
-P:修改最大的进程数,默认是1,为0时候为as many as it can。
实例1
all_num=10
thread_num=5
a=$(date +%H%M%S)
seq 1 ${all_num} | xargs -n 1 -I {} -P ${thread_num} sh -c "sleep 1;echo {}"
b=$(date +%H%M%S)
echo -e "startTime:\t$a"
echo -e "endTime:\t$b"
实例2
vim name.txt
ssf 11
vaedit 12
zhangsan 13
seq 1 20 |xargs -n 1 -P 10 sh test.sh
cat test.sh
echo $1
sleep 2
实例3
seq 1 20 |xargs -i -P 10 sh test.sh {}
seq 1 20 |xargs -I {} -P 10 sh test.sh {}
cat test.sh
echo $1
sleep 2
案例3 使用GNU parallel命令控制并发数
yum install epel-release -y
yum install parallel -y
echo -e "will cite\n" | parallel --bibtex
parallel -j 5 "sleep 1;echo {}" ::: `seq 1 10`
find . -name "*jpeg" | parallel -I% --max-args 1 convert % %.png
这是两条命令的组合:find 命令,用于收集需要操作的对象;parallel 命令,用于对象排序并确保每个对象按需处理。
find . -name "*jpeg" 查找当前目录下以 jpeg 结尾的所有文件。
parallel 调用 GNU Parallel。
-I% 创建了一个占位符 %,代表 find 传递给 Parallel 的内容。如果不使用占位符,你需要对 find 命令的每一个结果手动编写一个命令,而这恰恰是你想要避免的。
--max-args 1 给出 Parallel 从队列获取新对象的速率限制。考虑到 Parallel 运行的命令只需要一个文件输入,这里将速率限制设置为 1。假如你需要执行更复杂的命令,需要两个文件输入(例如 cat 001.txt 002.txt > new.txt),你需要将速率限制设置为 2。
convert % %.png 是你希望 Parallel 执行的命令。
管道输出的每一行对应 parallel 的一个参数,所有参数构成参数行
ls -1 | parallel --max-args=2 cat {1} {2} ">" {1}_{2}.person
{.} 表示去掉文件.后缀
{\} 表示去掉文件目录相当于basename
{\\} 去掉第一层目录后,剩下的目录
{\.} 表示去掉文件目录后,把文件名的.后缀去掉
{
--null 会把管道传入的每一行的参数通过空格合并到一行变成一个参数
::: 后面表示要传入的参数,可以用这个替代管道符传入参数,还是按行分割
-L 每次读取的参数行数
cat jobs2run
bzip2 oldstuff.tar
oggenc music.flac
opusenc ambiance.wav
convert bigfile.tiff small.jpeg
ffmepg -i foo.avi -v:b 12000k foo.mp4
xsltproc --output build/tmp.fo style/dm.xsl src/tmp.xml
bzip2 archive.tar
parallel --jobs 6 < jobs2run
cat name.txt
vaedit 11
vaedit1 22
vaedit2 33
vaedit3 44
cat name.txt |parallel -j 2 --max-args=1 sh test.sh {1}
cat test.sh
a=$1
a1=`echo $a|awk '{print $1}'`
a2=`echo $a|awk '{print $2}'`
echo "名字是 $a1"
echo "年龄是 $a2"
sleep 1
cat bigfile.txt | parallel --block 10M --pipe grep 'pattern'
cat num1000000 | parallel --pipe --block 2M wc -l
cat bigfile.txt | parallel --pipe wc -l | awk '{s+=$1} END {print s}'