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

如何在无额外工具安装的情况下将运行时变量传入SSH远程执行的Bash脚本并实现定时命令执行?

解决SSH远程执行时参数$2失效的问题

这个问题的核心在于单引号会阻止本地Shell解析变量——你用单引号包裹的远程命令里,$2并不会被本地脚本的第二个参数替换,而是被当作远程服务器上的变量(但远程服务器根本没有这个参数),所以自然失效了。而且你的脚本里还有几个语法小问题(比如while true后面缺分号、if判断的空格缺失),我一起给你修正,全程不需要安装任何额外工具,纯原生Shell就能搞定。

方案1:提前替换变量值(双引号包裹+转义特殊字符)

把远程命令改成双引号包裹,这样本地的$2会先被解析成实际参数值,同时转义那些需要在远程执行的特殊字符,避免本地Shell提前解析:

#!/bin/bash
echo 'Host = ' $1
USERNAME=ec2-user
KEY=/home/xxx/xxx.pem

# 先做参数合法性检查(可选,但让脚本更健壮)
INTERVAL="$2"
if [[ -z "$INTERVAL" ]]; then
    echo "请传入第二个参数(sec/min/30min/hr/12hr/day/week)"
    exit 1
fi

ssh -l ${USERNAME} -i ${KEY} "$1" "
while true; do
    echo \$(date)
    echo stats | nc localhost 11211 | grep cmd_flush
    if [ \"$INTERVAL\" == 'sec' ]; then
        sleep 1
    elif [ \"$INTERVAL\" == 'min' ]; then
        sleep 1m
    elif [ \"$INTERVAL\" == '30min' ]; then
        sleep 30m
    elif [ \"$INTERVAL\" == 'hr' ]; then
        sleep 1h
    elif [ \"$INTERVAL\" == '12hr' ]; then
        sleep 12h
    elif [ \"$INTERVAL\" == 'day' ]; then
        sleep 1d
    elif [ \"$INTERVAL\" == 'week' ]; then
        sleep 7d
    else
        echo \"None of the condition met\"
        sleep 60 # 避免无限循环狂刷日志
    fi
done
" | tee /var/log/"$1"_"$INTERVAL".log

关键改动说明:

  1. 将远程命令从单引号改为双引号,让本地的$INTERVAL(即原$2)先被替换成实际值再传到远程
  2. 转义\$(date),确保远程执行时获取的是远程服务器的系统时间
  3. 给while true补充分号、给if判断的[和变量间添加空格,修复语法错误
  4. 给$INTERVAL加双引号,避免空值或含空格的参数导致脚本报错

方案2:用Here Document(Heredoc)传递脚本

Heredoc是Shell原生的多行内容传递方式,不用纠结引号转义,只要不把Heredoc的标记用单引号括起来,本地变量就会自动展开:

#!/bin/bash
echo 'Host = ' $1
USERNAME=ec2-user
KEY=/home/xxx/xxx.pem

INTERVAL="$2"
if [[ -z "$INTERVAL" ]]; then
    echo "请传入第二个参数(sec/min/30min/hr/12hr/day/week)"
    exit 1
fi

ssh -l ${USERNAME} -i ${KEY} "$1" << EOF
while true; do
    echo \$(date)
    echo stats | nc localhost 11211 | grep cmd_flush
    if [ "$INTERVAL" == 'sec' ]; then
        sleep 1
    elif [ "$INTERVAL" == 'min' ]; then
        sleep 1m
    elif [ "$INTERVAL" == '30min' ]; then
        sleep 30m
    elif [ "$INTERVAL" == 'hr' ]; then
        sleep 1h
    elif [ "$INTERVAL" == '12hr' ]; then
        sleep 12h
    elif [ "$INTERVAL" == 'day' ]; then
        sleep 1d
    elif [ "$INTERVAL" == 'week' ]; then
        sleep 7d
    else
        echo "None of the condition met"
        sleep 60
    fi
done
EOF | tee /var/log/"$1"_"$INTERVAL".log

关键改动说明:

  1. 用<< EOF和EOF包裹远程执行的脚本内容,本地的$INTERVAL会直接替换成实际值
  2. 同样转义\$(date)保证远程时间的正确性(如果需要本地时间,改成echo $(date)即可)
  3. 修复原脚本的语法问题,增加参数检查让脚本更可靠

这两个方案都完全依赖原生Shell功能,不需要安装任何工具,你可以根据自己的使用习惯选择。如果你的$2参数包含特殊字符(比如空格、引号),方案2的Heredoc会更稳妥,转义逻辑更简单。

内容的提问来源于stack exchange,提问作者Reshma

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 17:32:35