Bash脚本中SSH远程执行命令存变量后执行失败的排查与修复
问题描述
直接执行以下命令可成功运行:
ssh hostname "rm -rf ~/directory"
拆分变量编写脚本时也能正常工作:
#!bash SSH_HOST=hostname DIR_REMOTE='~/directory' ssh $SSH_HOST "rm -rf $DIR_REMOTE"
但将完整命令封装到字符串变量再执行时失败:
#!bash SSH_HOST=hostname DIR_REMOTE='~/directory' CMD="ssh $SSH_HOST \"rm -rf $DIR_REMOTE\"" echo "$CMD" $CMD
报错信息:
zsh:1: no such file or directory: rm -rf ~/directory
错误原因
将完整命令存入字符串变量后直接执行,会打乱shell的分词与引号解析逻辑。此时shell会把"rm -rf ~/directory"当作一个完整的参数传给ssh,ssh会误认为你要执行的命令就是rm -rf ~/directory(把空格和路径全部当作命令名的一部分),而非调用rm命令并传入-rf和~/directory参数,自然找不到这个不存在的“命令”。
修复方案
方案1:用函数封装(推荐)
把命令逻辑封装成函数,既清晰又能彻底避免分词问题:
#!bash SSH_HOST=hostname DIR_REMOTE='~/directory' run_remote_rm() { ssh "$SSH_HOST" "rm -rf $DIR_REMOTE" } run_remote_rm
方案2:用数组存储命令参数
如果必须用变量存储,使用数组保存命令与每个参数,shell会正确处理分词:
#!bash SSH_HOST=hostname DIR_REMOTE='~/directory' CMD=(ssh "$SSH_HOST" "rm -rf $DIR_REMOTE") # 执行数组中的命令 "${CMD[@]}"
方案3:直接执行命令(最直接)
若没有特殊需求,无需将完整命令存为字符串变量,直接使用你之前能正常运行的写法即可。
内容的提问来源于stack exchange,提问作者John Siu
相关产品推荐
相关产品推荐

