前言
在工作中常遇到如下场景:
系统未接入日志中心,系统本身使用集群部署,那么再查找日志的时候只能一台一台的去搜索关键字,后来运维同学发现这样一台一台效率太低了,于是有了升级版,升级之后的方式还是一台一台去搜索只不过这次换成了脚本去执行,原理上还是需要在一台上搜索完成之后再去另一台搜素。如果遇到日志相当多的情况,那这种也会很慢。
下面介绍一种今天新学到的技能,就是使用“多线程”的方式去执行脚本,但是这种多线程并不是类似java中的那种多线程,而是触发了多个进程,这里的多线程可以理解为多进程。
管道
在介绍多进程前,先来学习一下管道,一般说到管道,常使用Linux的同学首先会想到“|”,这个管道的意思是将前面的输出通过管道做为后面的输入,可以理解为是一种传输介质,是Linux的一种通信方式,比如ps -ef | grep test 。
那么还有一种管道是FIFO文件,这种文件也可以完成类似上面的工作,比如 ps -ef > .fifo写入文件, 同时在开个客户端就可以获取到通过如下命令获取到数据,grep test .fifo,实际操作一次会发现在写入文件后,如果另一个客户端不对.fifo做任何操作,那么第一个客户端会阻塞住,直到第二个客户端操作了之后第一个才会结束。
FIFO管道文件和普通文件的区别
1、创建方式不同
FIFO管道文件是通过mkfifo命令创建出来的,而普通文件是通过touch命令创建出来的
2、普通文件写入后不会阻塞,FIFO文件写入后会阻塞
3、普通文件时保存在磁盘上的,而FIFO文件是保存在内存中的
“多线程”的实现思路
初级版本:使用&符配合wait实现,这种适用于确定循环次数并且循环次数不是太多。
for ((i=0;i<5;i++));do
echo 1
{
sleep 3;
echo "done!"
}&
done
wait
echo "执行完毕!!!"
升级版本:利用FiFO管道来控制进程数,达到了“多线程”且线程数可控的目的。
如下脚本中的open_thread()函数还可以封装成一个单独的脚本,使用的时候通过source xxx引入来使用,这样看起来更优雅一些。
#!/usr/bin/env bash
###################################################
# Describe: grep指定文件夹中的所有文本中的指定关键字 #
# Version: v1.0 #
# Author: cz #
###################################################
# 开启多线程操作
open_thread() {
# 最大进程数
PROCESS_NUM=$1
# 使用mkfifo命令可以使用指定的名称创建先进先出文件(FIFO)
# 创建一个fifo文件
FIFO_FILE=./$.fifo
mkfifo $FIFO_FILE
# 关联fifo文件和fd6
exec 6<>$FIFO_FILE # 将fd6指向fifo类型
rm $FIFO_FILE
# 向fd6中输入$PROCESS_NUM个回车
echo ${PROCESS_NUM}
for((idx=0;idx<${PROCESS_NUM};idx++))
do
echo
done >&6
}
# 指定文件夹下的文件并行读取
# 支持 grep key_word file_name
#
#
grep_specified_folder () {
echo $1
echo $2
echo $3
# 获取指定文件夹
folder=$1
# 需要grep的关键字
key_word=$2
# 定义线程数,如果未定义则默认为5,如何判断是未定义呢,通过参数个数来判断
PROCESS_NUM=$3
# 临时文件名
temporary_file_name='~jef_temp_file'
# 开启多线程
open_thread $3
for filename in $(ls $folder)
do
read -u6
# 每个线程处理一个gerp
{
result=`grep $key_word $folder/$filename`
# 将结果追加到文件中
echo "=============="$filename"===========" >> $temporary_file_name
echo "$result" >> $temporary_file_name
# 当进程结束以后,再向fd6中加上一个回车符,即补上了read -u6减去的那个
echo >&6
}&
done
# 等待所有的任务执行完毕
wait
# 关闭fd6
exec 6>&-
cat $temporary_file_name
rm $temporary_file_name
}
grep_specified_folder $1 $2 $3