SSH Bash脚本if语句问题:Yum/Apt服务器更新脚本修正
修正你的SSH批量更新服务器脚本
我帮你梳理下脚本里的几个关键问题,然后给出修正后的版本,顺便解释每个改动的原因:
原脚本的核心问题
- 远程命令没正确传递:你写的
ssh -l ${USERNAME} ${HOSTNAME}之后的代码全是在本地执行的,根本没传到远程服务器上,这是最致命的问题。 - if条件语法错误:
[[ $find_os='yum' ]]里的比较运算符两边没有空格,Bash会把整个$find_os='yum'当成一个非空字符串,导致条件永远为真,根本起不到判断作用。 - 命令执行逻辑问题:变量里的
&&在直接用双引号包裹执行时,远程环境可能不会正确解析,导致命令执行失败。 - 错误提示位置不对:找不到包管理器的提示是在本地输出的,你根本不知道是哪台服务器出了问题。
修正后的脚本
#!/bin/bash USERNAME="root" HOSTS="host1 host2 host3" for HOSTNAME in ${HOSTS}; do echo "开始更新服务器 ${HOSTNAME}..." ssh -l ${USERNAME} ${HOSTNAME} ' # 远程执行:检测包管理器 find_os=$(command -v yum || command -v apt-get) # 如果都没找到,输出错误并退出 if [[ -z $find_os ]]; then echo "错误:该服务器既没有yum也没有apt-get包管理器" exit 1 fi # 根据检测结果执行对应更新命令 if [[ $find_os == "/usr/bin/yum" ]]; then yum check-update && yum -y update else apt update && apt -y upgrade fi ' done
改动说明
- 远程命令包裹:把所有要在远程执行的逻辑用单引号包裹,这样SSH会把整个字符串作为命令发送到目标服务器执行,确保所有判断和命令都在远程运行。
- 修复条件判断:用
[[ $find_os == "/usr/bin/yum" ]]做判断,command -v返回的是命令的完整路径,这样判断更准确,避免出现同名命令的干扰;同时给比较运算符两边加上了空格,符合Bash语法规范。 - 错误处理优化:在远程逻辑里判断
find_os是否为空,如果为空就输出错误并退出,让你清楚知道哪台服务器有问题。 - 增加进度提示:在本地添加了
echo "开始更新服务器 ${HOSTNAME}...",方便你跟踪批量更新的进度。
可选:保留变量的写法
如果你想把更新命令存在变量里复用,可以用双引号包裹远程命令(注意转义远程变量的$),再用eval执行变量里的命令链:
#!/bin/bash USERNAME="root" HOSTS="host1 host2 host3" apt_run="apt update && apt -y upgrade" yum_run="yum check-update && yum -y update" for HOSTNAME in ${HOSTS}; do echo "开始更新服务器 ${HOSTNAME}..." ssh -l ${USERNAME} ${HOSTNAME} " find_os=\$(command -v yum || command -v apt-get) if [[ -z \$find_os ]]; then echo \"错误:该服务器既没有yum也没有apt-get包管理器\" exit 1 fi if [[ \$find_os == \"/usr/bin/yum\" ]]; then eval \"${yum_run}\" else eval \"${apt_run}\" fi " done
这里用双引号让本地的yum_run和apt_run变量被正确替换,同时把远程的$find_os转义成\$,避免本地Shell提前解析这个变量。
内容的提问来源于stack exchange,提问作者robothead
相关产品推荐
相关产品推荐

