通过SSH批量升级多台机器的脚本报错求助
解决"Bad substitution"报错及多机SSH升级脚本修正
报错核心原因
你遇到的upgrade-all.sh: 7: Bad substitution报错,本质是数组定义不符合bash语法规范:
你用逗号+引号分隔元素的写法(USERNAMES="jed", "root", "cord")并不是bash数组的正确格式,这种写法会把整个带逗号的字符串当成数组的唯一元素,导致${!HOSTS[@]}这类数组索引操作无法被bash识别,触发替换错误。
修正步骤及完整脚本
1. 修正数组定义
bash数组的正确写法是用括号包裹元素,元素之间用空格分隔,无需额外逗号和引号(除非元素包含特殊字符):
USERNAMES=(jed root cord) HOSTS=(***.***.***.*** ***.***.***.*** ***.***.***.***) PASSWORDS=(*** *** ***)
2. 优化sudo执行逻辑
原脚本中echo -e 'PASSWORD' | sudo apt update的写法存在安全风险,且可能因sudo的终端交互限制失效,建议改用sudo -S选项(从标准输入读取密码),同时调整命令执行顺序避免管道逻辑冲突。
修正后的完整脚本
#!/bin/bash # 正确定义bash数组,元素用空格分隔 USERNAMES=(jed root cord) HOSTS=(***.***.***.*** ***.***.***.*** ***.***.***.***) PASSWORDS=(*** *** ***) # 调整sudo执行逻辑,使用-S选项读取密码 SCRIPT="pwd; echo 'PASSWORD' | sudo -S apt update && sudo -S apt upgrade -y && sudo -S apt autoremove -y" for i in "${!HOSTS[@]}" ; do echo "正在处理主机: ${HOSTS[i]}" # 替换脚本中的PASSWORD为对应主机的密码 SCR=${SCRIPT/PASSWORD/${PASSWORDS[i]}} # 执行ssh远程命令 sshpass -p "${PASSWORDS[i]}" ssh -l "${USERNAMES[i]}" "${HOSTS[i]}" "${SCR}" done
额外注意事项
- 确保用bash执行脚本:运行时使用
bash upgrade-all.sh,不要用sh upgrade-all.sh,因为sh不支持bash的数组语法。 - 避免明文存储密码:脚本明文写密码存在极大安全风险,建议改用SSH密钥认证替代密码登录,彻底规避密码泄露问题。
- 先测试单台主机:修改完成后先测试单台主机的执行逻辑,确认无问题后再批量运行。
内容的提问来源于stack exchange,提问作者Jacob Rawls
相关产品推荐
相关产品推荐

