后台数可控是避免资源过度占用的有效控制;子进程里的后台状态检测实现复杂,这里提供一种方式。
1、管道和后台在同一个脚本
cat fifo.sh
#! /bin/bash
ls /proc/self/fd # 获取已用文件操作符
ulimit -n # 可用最多文件操作符个数
mkfifo fifo_1001 # 创建管道文件
# 三个标准文件操作符,分别为 0、1、2; 对应 stdin ,stdout, stderr
exec 1001<>fifo_1001 # 绑定文件操作符和管道文件
rm -rf fifo_1001 # 删除管道文件
# 写 10 个管道
for (( j = 0; j < 10; j++ ));do
echo >&1001
done
# 读一个管道
read -u1002
{
# do something
echo >&1001 # 写管道
} &
wait # 等待所有后台执行结束
exec 1001>&- && exec 1001<&- # 关闭文件操作符
上述脚本可以实现 10 个后台进程的并发运行。
2、 管道和后台不在一个脚本
cat fifo.sh
#! /bin/bash
# 文件操作符 FIFO 当前可读次数为 fifo_len 时返回
function wait_fifo()
{
ufifo=0
FIFO=$1 # 文件操作符
fifo_len=$2 # 文件操作符最大可读次数
FIFO_FREE_CK=$3 # 获取当前文件可读次数
while (( ${ufifo} < ${fifo_len} ));do
ufifo=$(eval ${FIFO_FREE_CK})
# 将已读的重写
for(( i = 0; i < ${ufifo}; i++ ));do
echo >&${FIFO}
done
let tWait=${fifo_len}-${ufifo}
sleep ${tWait} # sleep 1s this must need
done
}
ls /proc/self/fd # 获取已用文件操作符
ulimit -n # 可用最多文件操作符个数
mkfifo fifo_1002 # 创建管道文件
# 三个标准文件操作符,分别为 0、1、2; 对应 stdin ,stdout, stderr
exec 1002<>fifo_1002 # 绑定文件操作符和管道文件
rm -rf fifo_1002 # 删除管道文件
# 写 10 个管道
FIFO_LEN=10
for (( j = 0; j < ${FIFO_LEN}; j++ ));do
echo >&1002
done
# 返回 1002 可读次数
for (( j = 0; j < ${FIFO_LEN}; j++ ));do
echo >&1002
let jj=$j+1
if [ ${jj} -eq ${FIFO_LEN} ];then
FIFO_WAIT="${FIFO_WAIT}(read -t 0.01 -u1002 || (echo $j && false)) && (echo ${jj})"
else
FIFO_WAIT="${FIFO_WAIT}(read -t 0.01 -u1002 || (echo $j && false)) && "
fi
done
for (( i = 0; i < 8; i++ ));do
Multi_process1.sh
done
for (( i = 0; i < 8; i++ ));do
Multi_process2.sh
done
# wait 这里 wait 不在起作用
wait_fifo 1002 "${FIFO_LEN}" "${FIFO_WAIT}" # 1002可读${FIFO_LEN} 则继续执行
exec 1002>&- && exec 1002<&- # 关闭文件操作符
cat Multi_process1.sh
#! /bin/bash
# 读一个管道
read -u1002
{
# do something 1
echo >&1002 # 写管道
} &
cat Multi_process2.sh
#! /bin/bash
# 读一个管道
read -u1002
{
# do something 2
echo >&1002 # 写管道
} &
wait_fifo 函数起到阻塞等待的作用。