如何在无额外工具安装的情况下将运行时变量传入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
关键改动说明:
- 将远程命令从单引号改为双引号,让本地的
$INTERVAL(即原$2)先被替换成实际值再传到远程 - 转义
\$(date),确保远程执行时获取的是远程服务器的系统时间 - 给
while true补充分号、给if判断的[和变量间添加空格,修复语法错误 - 给
$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
关键改动说明:
- 用
<< EOF和EOF包裹远程执行的脚本内容,本地的$INTERVAL会直接替换成实际值 - 同样转义
\$(date)保证远程时间的正确性(如果需要本地时间,改成echo $(date)即可) - 修复原脚本的语法问题,增加参数检查让脚本更可靠
这两个方案都完全依赖原生Shell功能,不需要安装任何工具,你可以根据自己的使用习惯选择。如果你的$2参数包含特殊字符(比如空格、引号),方案2的Heredoc会更稳妥,转义逻辑更简单。
内容的提问来源于stack exchange,提问作者Reshma
相关产品推荐
相关产品推荐

