You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 11:35:07