Bash脚本远程执行命令进度条异常问题求助
修复带百分比进度条的多机器SSH执行脚本
核心问题分析
添加进度条后脚本故障,大概率是SSH会话占用标准输入,或者循环执行方式导致子进程变量隔离,也可能是进度条输出和远程命令输出冲突。以下是针对这类问题的通用修复方案,同时保留逐台执行+进度条的功能。
修复后的完整脚本
#!/bin/bash # 检查参数合法性 if [ $# -ne 1 ]; then echo "用法: $0 <IP列表文件路径>" exit 1 fi IP_LIST="$1" # 统计总机器数(过滤空行) TOTAL=$(grep -v '^$' "$IP_LIST" | wc -l) CURRENT=0 # 封装远程执行逻辑 function1() { local target_ip="$1" # 远程执行的命令集合,按需修改 ssh -n "$target_ip" << 'REMOTE_CMDS' # 示例命令:替换成你实际需要执行的操作 echo "当前主机: $(hostname)" uptime free -h REMOTE_CMDS # 可选:将远程输出写入日志文件,避免干扰进度条 # ssh -n "$target_ip" << 'REMOTE_CMDS' >> "log_${target_ip}.txt" # ... # REMOTE_CMDS } # 进度条渲染函数 render_progress() { local curr=$1 local total=$2 local percent=$(( curr * 100 / total )) # 用回车覆盖当前行,实现单行进度条 printf "\r[%-50s] %d%% 已完成: %d/%d" \ $(printf "#%.0s" $(seq 1 $(( percent / 2 )))) \ $percent $curr $total } # 逐台执行主逻辑 while IFS= read -r ip; do # 跳过空行和注释行(如果有) [[ -z "$ip" || "$ip" =~ ^# ]] && continue CURRENT=$(( CURRENT + 1 )) # 执行远程命令 function1 "$ip" # 更新进度条 render_progress "$CURRENT" "$TOTAL" done < "$IP_LIST" # 最后换行,避免后续输出和进度条重叠 echo -e "\n所有主机执行完成"
关键修复点说明
ssh -n参数:强制SSH不读取标准输入,避免和read命令争抢IP列表的输入流——这是最常见的故障诱因,不加-n的话,SSH会把剩余的IP行当作输入,导致循环提前终止。- 避免管道子进程陷阱:用
while read ... < "$IP_LIST"替代cat "$IP_LIST" | while read ...,后者会创建子进程,导致CURRENT变量无法在父进程中更新,进度条永远停留在0%。 - 进度条行覆盖:用
printf "\r"实现单行刷新,避免进度条刷屏;同时用%-50s固定进度条长度,保证显示整齐。 - 远程命令隔离:用
<< 'REMOTE_CMDS'(单引号包裹分界符),防止本地变量被远程Shell解析,避免意外错误。 - 空行/注释过滤:添加
[[ -z "$ip" || "$ip" =~ ^# ]] && continue,跳过IP列表中的空行和注释行,避免无效SSH连接。
验证方法
- 先注释掉进度条相关代码(
render_progress调用和函数),确认核心SSH执行逻辑正常; - 再恢复进度条代码,测试逐台执行时的百分比显示是否正常,无输出错乱或提前终止问题。
内容的提问来源于stack exchange,提问作者vijayedm
相关产品推荐
相关产品推荐

