最近处理批量任务,数据量越来越大,串行执行太慢,严重影响效率。
于是写了个 Shell 脚本实现并发执行
实现步骤就三个
我的脚本长这样
#!/bin/bash
# =============================================
# Shell 并发控制示例
# 功能:并发执行多个任务,控制最大并发数
# =============================================
# 接收并发数
if [ $# -lt 1 ]; then
echo "用法: $0 <并发数>"
exit 1
fi
PROCESS=$1
# 限制最大并发数,防止系统过载
if [ ${PROCESS} -gt 5 ]; then
echo "并发数不能大于5"
exit 1
fi
# 日志目录
LOG_DIR="logs"
mkdir -p ${LOG_DIR}
# 模拟任务列表()
tasks=(
"task1"
"task2"
"task3"
"task4"
"task5"
"task6"
"task7"
"task8"
)
# ========================
# 🔁 循环提交任务
# ========================
for task in "${tasks[@]}";
do
LOG_FILE="${LOG_DIR}/${task}.log"
echo "提交任务: $task"
# ========================
# 并发执行任务(核心)
# ========================
(
# 在这里替换为你的实际命令
sleep $((RANDOM % 5)) > "${LOG_FILE}" 2>&1 # 模拟执行时间
# 记录退出状态
# 注意:这句必须紧跟在任务后面,不然 $? 就被覆盖了
echo "status: $?" >> "${LOG_FILE}"
) &
# ========================
# 控制并发数
# ========================
# 当前正在运行的任务数 >= 设定并发数时,阻塞等待
while [ $(jobs -r | wc -l) -ge ${PROCESS} ];
do
wait -n # 等待任意一个后台任务结束,释放一个名额
done
done
# ========================
# 等待所有任务完成
# ========================
wait
# ========================
# ✅ 汇总执行结果
# ========================
echo
"========================================"
echo
"所有任务已提交,开始检查结果..."
for log in ${LOG_DIR}/*.log;
do
# 提取最后的状态码
status=$(tail -n 1 "$log"| grep -oP 'status: \K\d+' 2>/dev/null)
if [ "$status" = "0" ]; then
echo "✅ $(basename "$log".log) 执行成功"
else
echo "❌ $(basename "$log".log) 执行失败!状态码: $status"
sh /path/to/alert.sh "任务失败: $(basename "$log")"
fi
done
echo
"========================================"
echo
"全部任务执行完毕!"实现并发用的 (...)&
例如:
(
你的命令 > log.txt 2>&1
echo "status: $?" >> log.txt
) &(...) 是子 shell& 放到后台,实现并发控并发靠的 jobs + wait -n
while [ $(jobs -r | wc -l) -ge ${PROCESS} ];
do
wait -n
donejobs -r 查看当前正在运行的任务数wait -n 等待任意一个任务结束,继续执行新的任务状态记录不能乱写
echo "status: $?"必须紧跟在任务命令之后
$? 就变了执行时传入并发数量
即我们定义的 PROCESS=$1
如:sh nidejiaoben.sh 5
5 表示最多同时跑 5 个任务📌 并发多少要看你的服务器压力能不能抗的住,先从几个慢慢增加,不然一下跑很多,能把服务器跑崩