基于SSH实现本地脚本携带远程主机与脚本参数直接远程执行
实现逻辑拆解
要实现「本地直接调用脚本+传入远程地址+业务参数,脚本自动在远程执行」的效果,核心是给脚本加双运行模式的判断,把本地跳转逻辑和远程业务逻辑完全隔离,根本不需要手动拼接冗长的SSH命令。
你之前脚本无输出的核心问题
- 代码执行没有做环境隔离:你写的
ssh ${user}@${host} < $0确实会把脚本内容传给远程运行,但SSH命令返回后,本地脚本进程会顺着代码顺序继续执行后面所有的业务逻辑。这部分逻辑跑在本地环境,根本读不到远程主机的硬件传感器数据,自然拿不到有效输出 - 远程执行环节没有同步参数:你把脚本内容传给远程时,没有把本地解析好的设备类型、传感器地址、告警阈值这些业务变量带过去,远程端执行时所有变量都是未定义状态,case分支匹配不到任何设备类型,根本不会触发取数和输出流程
- 参数解析逻辑没有做分支区分:把连接用的用户名、主机地址和业务参数混在同一个解析流程里,远程执行时参数顺序完全错位,解析出来的全是无效值
具体实现步骤
- 自定义一个不会和业务参数冲突的特殊标记(比如
__REMOTE_RUN__),脚本启动后第一时间判断当前命令行是否带了这个标记 - 如果判断当前是远程执行环境(带了标记),直接跳过SSH跳转流程,解析后续传入的业务参数,跑完所有业务逻辑后立刻退出,不碰本地跳转的代码
- 如果判断当前是本地初始执行环境,先提取用户传入的远程连接地址(格式为
user@host),再把所有业务参数+自定义标记作为参数,通过SSH调用本地当前脚本,让远程端启动同一个脚本实例 - 本地发起SSH连接后立刻执行
exit 0,避免本地进程继续往下跑业务代码,和远程执行结果产生冲突
参考脚本结构
#!/bin/bash # 自定义远程执行标记,避免和业务参数冲突 REMOTE_FLAG="__DO_NOT_EXEC_LOCAL__" # -------------------------- # 远程执行分支:所有业务代码全部写在这里 # -------------------------- if [ "$1" == "$REMOTE_FLAG" ]; then # 移除标记参数,剩余参数传给getopts解析业务值 shift while getopts 'd:s:w:c:' OPT; do case $OPT in d) device=$OPTARG ;; s) sensor=$OPTARG ;; w) warn_thresh=$OPTARG ;; c) crit_thresh=$OPTARG ;; esac done # 插入你原本的全部业务逻辑: # 检查传感器程序、读取温度值、阈值判断、生成Nagios格式输出 case $device in linux) echo "linux平台温度读取逻辑" ;; raspberry) echo "树莓派平台温度读取逻辑" ;; amlogic) echo "Amlogic平台温度读取逻辑" ;; esac exit 0 # 远程执行完成直接退出,不运行后续代码 fi # -------------------------- # 本地分支:仅做SSH跳转,不写业务逻辑 # -------------------------- # 第一个参数就是用户传入的远程主机地址 remote_target="$1" shift # 发起SSH连接,把标记+所有业务参数传给远程端 ssh -o LogLevel=ERROR "$remote_target" "$0" "$REMOTE_FLAG" "$@" exit 0 # 本地跳转完成直接退出,不执行业务代码
优化方向
- 如果脚本体积较大,每次通过SSH传整个脚本内容效率低,可以提前把脚本上传到远程主机的固定路径,本地跳转时直接调用远程路径下的脚本,参数传递逻辑完全不变
- 如果需要提前检查远程主机连通性,可以在本地分支发起SSH前加快速连通性探测,减少无效等待
- 不需要提前在远程主机存放脚本的场景,可以用
ssh remote_host "bash -s" -- < script.sh 标记 参数1 参数2的流式传参写法,逻辑和上面的示例完全一致,脚本内容直接通过SSH管道传给远程shell执行,不需要远程有同个文件
内容的提问来源于stack exchange,提问作者MonsieurMemons
相关产品推荐
相关产品推荐

