shell 多进程(并发)

#!/bin/bash

# 接受信号2(ctrl+C)
# 关闭fd 6的绑定
# 注意:绑定时可以用 exec <> fifofile; 
# 但关闭时必须分开写:exec 6>&-和exec 6<&- 是关闭fd6
trap "exec 6>&-; exec 6<&-; exit 0" 2

# 管道文件名
tempfile="temp.$$"

# 创建有名管道
# 管道的特点:
# 1. 如果管道中没有数据,则读管道数据的操作会阻塞,直到管道内写入数据
# 2. 管道内有数据,如果没有读取操作也会阻塞,直到读取后才会终止这一操作
mkfifo ${tempfile}

# 绑定文件操作符为管道
exec 6<>${tempfile}

# fd6已绑定成为管道,不再需要管道文件,可直接删除掉
rm -f ${tempfile}

# 并发执行线程数
tnum=10

preip="192.168.100."

# 对文件操作符进行写入操作,通过for循环写入$tnum个空行,即为后台线程数量
for ((i=1; i<=$tnum; i++)); do
{
  echo >&6
}
done

for ip in $(seq 2 254); do
{
  # 从文件操作符读取管道中的一个空行
  read -u 6
  {
    # 并发操作代码块
    sleep 1
    ping -q -c2 -W1 "${preip}$ip" &>/dev/null
    if [ $? -eq 0 ]; then
      echo -e "\033[32m${preip}$ip is alive.\033[0m"  
    else
      echo -e "\033[31m${preip}$ip is down.\033[0m"  
    fi
    
    # 重点:读取完一个空行后,重新向文件操作符写入一个空行,
    # 否则当$tnum个任务放入后台后,由于操作符中没有可读取的空行,导致read -u 6阻塞
    echo >&6
  }&  # 将任务放入后台执行
}
done

# 等待所有线程执行完毕,避免主进程提前退出
wait

# 关闭文件操作符的读写绑定
exec 6>&-
exec 6<&-
posted @ 2020-11-16 17:04  bigtree2pingping  阅读(638)  评论(0编辑  收藏  举报