3.41. shell实现多并发控制

3.41.1. 1.不并发

#!/usr/bin/env bash
#usage:xxx
#scripts_name:xxx.sh
shutdown_instance_array=($(nova list | grep SHUTOFF | awk -F "|" '{print $2}'))
shutdown_instance_Name=($(nova list | grep SHUTOFF | awk -F "|" '{print $3}'))
declare -A array_instance

# 设置关联数组
for i in ${!shutdown_instance_array[@]}; do array_instance[${shutdown_instance_Name[$i]}]=${shutdown_instance_array[$i]}; done

name_arry=(${!array_instance[@]}) #key -name
id_arry=(${array_instance[@]})    #value -id

for ((i = 0; i < ${#shutdown_instance_array[@]}; i++)); do
{
#     echo ${name_arry[$i]}
    map_dev=$(rbd map ${id_arry[$i]}_disk -p vms)
    echo -e "xfs_repair -L $map_dev > ${name_arry[$i]}.log 2>&1 &"
  } &
    sleep 1
done
wait

stop_time=$(date +%s) #定义脚本运行的结束时间
echo "TIME:`expr $stop_time - $start_time`"

3.41.2. 2.控制并发

2.1 控制并发示例1

#!/usr/bin/env bash
#usage: To repair the virtual machine hard disk, the virtual machine must be off
source /etc/kolla/admin-openrc.sh
start_time=$(date +%s)

Nproc=5

shutdown_instance_array=($(nova list | grep SHUTOFF | awk -F "|" '{print $2}'))
shutdown_instance_Name=($(nova list | grep SHUTOFF | awk -F "|" '{print $3}'))
declare -A array_instance

# 设置关联数组
for i in ${!shutdown_instance_array[@]}; do array_instance[${shutdown_instance_Name[$i]}]=${shutdown_instance_array[$i]}; done
name_arry=(${!array_instance[@]}) #key -name
id_arry=(${array_instance[@]})    #value -id


[ -e /tmp/fifo.$$ ] || mkfifo /tmp/fifo.$$
exec 3<>/tmp/fifo.$$
rm -f /tmp/fifo.$$

for ((i = 0; i < $Nproc; i++)); do
  echo >&3
done

for ((i = 0; i < ${#shutdown_instance_array[@]}; i++)); do
  {
    read -u3
    sleep 1
    echo "xfs_repair instamceName: ${name_arry[$i]} instamceID: ${id_arry[$i]} "
    device_name=$(rbd map ${id_arry[$i]}_disk -p vms)
    xfs_repair -L ${device_name} > ${name_arry[$i]}_$$.log 2>&1
    echo "instamceName: ${name_arry[$i]} instamceID: ${id_arry[$i]}" >> repairInformationSummary.log
    echo >&3 #执行到最后,把令牌放回管道

  }&
done
wait

stop_time=$(date +%s)
echo "TIME:$(expr $stop_time - $start_time)"

exec 3<&-

2.2 控制并发示例2

#!/usr/bin/env bash
#usage:xxx
#scripts_name:xxx.sh

thread=5
tmp_fifofile=/tmp/$$.fifo

mkfifo $tmp_fifofile
exec 8<> $tmp_fifofile
rm $tmp_fifofile

for i in `seq $thread`
do
    echo $i &> 8
done

for i in {1..245}
do
    read -u8
    {
        ip=192.168.122.$i
        ping -c1 -W1 $ip &>/dev/null
        if [ $? -eq 0 ];then
            echo "$ip is down!"
        else
            echo "$ip is up"
        fi
        echo $i >& 8
    }&
done
wait
exec 8 <&-
echo "all finished......"

2.3 控制并发示例3

#!/bin/bash
date

DIR=/test/log/

FILE_NAME=65535_`date +"%Y%m%d"`;
FILE_NAME_LAST_DAY=`date -d "yesterday" +"%Y%m%d"`;

time_of_system=`date +"%Y-%m-%d"`

function multi_processor(){
    [ -e /tmp/fd1 ] || mkfifo /tmp/fd1
    exec 3<>/tmp/fd1
    rm -rf /tmp/fd1
    for ((i=1;i<=30;i++))
    do
        echo >&3
    done

    for file in $1
    do
    read -u3
    {
        grep $3 $file | awk -F"|" '{print $7}' | sort | uniq >> $2;
        echo >&3
    }&
    done
    wait

    exec 3<&-
    exec 3>&-
}

#register 1 day ago
register_file=register_file_1_day_ago_$HOSTNAME.txt
file_modify_time=`stat $register_file | grep Modify | awk '{print $2}'`
files_last_day=`find $DIR -type f -name "$FILE_NAME_LAST_DAY*"`
if [[ $file_modify_time != $time_of_system ]]; then
    echo "$register_file file_modify_time(${file_modify_time}) time_of_system(${time_of_system})"
    rm $register_file
    multi_processor "$files_last_day" "$register_file" "REGISTER"
fi

2.4 控制并发示例4

#!/usr/bin/env bash
#usage:xxx
#scripts_name:xxx.sh
# author:xiaojian

Njob=15 #任务总数

Nproc=5 #最大并发进程数

mkfifo ./fifo.$$ && exec 777<> ./fifo.$$ && rm -f ./fifo.$$ #通过文件描述符777访问fifo文件

for ((i=0; i<$Nproc; i++)); do #向fifo文件先填充等于Nproc值的行数

    echo "init time add $i" >&777

done

for ((i=0; i<$Njob; i++)); do

        {

        read -u 777 #从fifo文件读一行

        echo "progress $i is sleeping for 3 seconds zzz…"

        sleep 3

        echo "real time add $(($i+$Nproc))" >&777 #sleep完成后,向fifo文件重新写入一行

        } &

done

wait

exec 777 >&-
exec 777 <&-
echo -e "time-consuming: $SECONDS seconds"

2.5 控制并发示例5

#!/usr/bin/env bash
#usage:xxx
#scripts_name:${NAME}.sh
# author:xiaojian

CE_HOME="/data/ContentEnginne"
LOG_PATH="/data/logs"

# 控制爬虫数量为8
MAX_SPIDER_COUNT=8

count=`ps -ef|grep -v grep|grep run.py|wc -l`
try_time=0
cd $CE_HOME
while [ $count -lt $MAX_SPIDER_COUNT -a $try_time -lt $MAX_SPIDER_COUNT ]; do
    let try_time +=1
    python run.py >> ${LOG_PATH}/spider.log 2>&1 &
    count=`ps -ef|grep -v grep|grep run.py|wc -l`
done

2.6 控制进程数量的ping脚本

#!/bin/bash
#Version:3.0
#功能描述(Description):控制进程数量的ping测试脚本.
#使用wait命令等待所有子进程结束后再退出脚本.

num=10             #控制进程数量.
net="192.168.4"
pipefile="/tmp/multiping_$$.tmp"

multi_ping() {
    ping -c2 -i0.2 -W1 $1 &>/dev/null && echo "$1 is up." || echo "$1 is down."
}

#创建命名管道文件,创建其文件描述符,通过重定向导入数据到管道文件中.
mkfifo $pipefile
exec 12<>$pipefile
for i in $(seq $num)
do
    echo "" >&12 &
done

#通过循环反复调用函数并将其放入后台并行执行.
#成功读取命名管道中的数据后开启新的进程.
#所有内容读取完后read被阻塞,无法再启动新进程.
#等待前面启动的进程结束后,继续往管道文件中写入数据,释放阻塞,再次开启新的进程.
for j in {1..254}
do
    read -u12
    {
        multi_ping $net.$j
        echo "" >&12
    } &
done
wait
rm -rf $pipfile