bash脚本for循环并行执行时如何展示运行进度及完成预估
并行SSH任务进度追踪与耗时预估实现方案
方案1:纯Bash原生实现(无额外依赖)
核心思路是通过临时文件标记任务完成状态,后台独立进程定期统计完成数量,计算进度、已耗时长和预估剩余时间。
完整代码示例:
#!/bin/bash # 配置参数 LIMIT=20 # 替换为你的节点总数 # 创建临时目录存储完成标记 TMP_DIR=$(mktemp -d) # 记录脚本启动时间 START_TIME=$(date +%s) # 定义你的业务函数 my_function() { local n=$1 # 此处替换为你原来的SSH执行逻辑,建议重定向输出避免冲毁进度条 ssh user@node$n "your_command" > "${TMP_DIR}/${n}.log" 2>&1 # 任务完成后创建标记文件 touch "${TMP_DIR}/${n}.done" } # 导出函数供子进程调用 export -f my_function export TMP_DIR # 批量启动并行任务 for (( n=0; n<${LIMIT}; n++ )); do my_function $n & done # 后台启动进度监控进程 ( while true; do # 统计已完成任务数 DONE=$(ls "${TMP_DIR}"/*.done 2>/dev/null | wc -l) # 计算进度百分比 PERCENT=$(( DONE * 100 / LIMIT )) # 计算已耗时长 ELAPSED=$(( $(date +%s) - START_TIME )) # 计算预估剩余时间 if [ ${DONE} -gt 0 ]; then ETA=$(( ELAPSED * (LIMIT - DONE) / DONE )) ETA_FMT=$(printf "%02d:%02d:%02d" $((ETA/3600)) $((ETA%3600/60)) $((ETA%60))) else ETA_FMT="计算中" fi ELAPSED_FMT=$(printf "%02d:%02d:%02d" $((ELAPSED/3600)) $((ELAPSED%3600/60)) $((ELAPSED%60))) # 生成进度条 BAR=$(printf "%0.s=" $(seq 1 $((PERCENT/2)))) # 刷新进度显示(覆盖上一行) printf "\r[%-50s] %d%% 已完成:%d/%d 已耗时:%s 预估剩余:%s" "${BAR}" "${PERCENT}" "${DONE}" "${LIMIT}" "${ELAPSED_FMT}" "${ETA_FMT}" # 全部完成后退出监控 [ ${DONE} -eq ${LIMIT} ] && break sleep 1 # 刷新间隔,可调整 done echo -e "\n所有任务执行完毕" ) & MONITOR_PID=$! # 等待所有任务执行完成 wait # 结束监控进程 kill ${MONITOR_PID} 2>/dev/null # 清理临时目录 rm -rf "${TMP_DIR}"
方案2:使用GNU Parallel(更简洁)
如果允许安装额外工具,GNU Parallel原生支持并行任务进度统计、耗时预估功能,无需手动维护计数逻辑。
使用示例:
#!/bin/bash LIMIT=20 # 定义你的业务函数 my_function() { local n=$1 ssh user@node$n "your_command" > "${n}.log" 2>&1 } export -f my_function # 并行执行并显示进度条和预估时间 seq 0 $((LIMIT-1)) | parallel -j ${LIMIT} --bar --eta my_function {}
参数说明:
-j ${LIMIT}:指定并行任务数,此处设置为和节点数一致即全并行执行--bar:显示图形化进度条--eta:显示预估剩余完成时间
通用注意事项
- 若任务有标准输出/错误输出,建议重定向到独立日志文件,避免进度条显示被异常输出冲毁
- 预估剩余时间基于已完成任务的平均耗时计算,若单任务耗时差异较大,前期预估会存在误差,待部分任务完成后会逐步准确
- 纯Bash方案可在开头添加陷阱逻辑,保证异常退出时自动清理临时资源:
trap "rm -rf $TMP_DIR; kill $MONITOR_PID 2>/dev/null" EXIT INT TERM
内容的提问来源于stack exchange,提问作者heresthebuzz
相关产品推荐
相关产品推荐

