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

适配新旧SSH版本的Expect SSH脚本调整方案咨询

解决Expect脚本兼容新旧SSH设备的问题

你修改后的脚本出现异常,核心原因是捕获到密钥交换错误后,直接启动新SSH进程,但Expect仍在监听原进程的输出,加上exp_continue的循环逻辑,导致新旧进程输出混杂,交互逻辑混乱。

以下是两种可靠的修改方案:

方案1:嵌套Expect块处理重连逻辑

直接在捕获到密钥交换错误时,关闭旧进程并启动新进程,用嵌套的Expect块处理新进程的交互:

# 先尝试默认参数连接新设备
spawn ssh -o StrictHostKeyChecking=no $username\@$host
expect {
    # 捕获密钥交换失败的提示,触发重连
    "no matching key exchange" {
        close
        wait
        # 用旧密钥交换算法重新连接
        spawn ssh -o KexAlgorithms=diffie-hellman-group1-sha1 -o StrictHostKeyChecking=no $username\@$host
        # 处理新进程的交互
        expect {
            timeout {
                send_user "\nTimeout Exceeded - Check Host\n"
                exit 1
            }
            eof {
                send_user "\nSSH Connection To $host Failed\n"
                exit 1
            }
            "*#" {}
            "*assword:" {
                send "$password\n"
                expect "*#"
            }
        }
    }
    # 原有的超时、EOF处理
    timeout {
        send_user "\nTimeout Exceeded - Check Host\n"
        exit 1
    }
    eof {
        send_user "\nSSH Connection To $host Failed\n"
        exit 1
    }
    # 正常交互逻辑
    "*#" {}
    "*assword:" {
        send "$password\n"
        expect "*#"
    }
}

关键细节

  • 用close+wait关闭旧进程,避免产生僵尸进程
  • 密码发送后添加expect "*#",确保脚本等待到设备提示符后再结束,防止提前退出

方案2:封装连接函数(更简洁)

把连接逻辑封装成过程,通过递归实现自动重试旧算法,避免重复代码:

# 定义SSH连接过程
proc ssh_connect {username host password use_old_kex} {
    set ssh_cmd "ssh -o StrictHostKeyChecking=no"
    # 如果需要旧算法,追加参数
    if {$use_old_kex} {
        append ssh_cmd " -o KexAlgorithms=diffie-hellman-group1-sha1"
    }
    append ssh_cmd " $username\@$host"

    spawn $ssh_cmd
    expect {
        timeout {
            send_user "\nTimeout Exceeded - Check Host\n"
            exit 1
        }
        eof {
            if {$use_old_kex} {
                # 用旧算法仍失败,直接退出
                send_user "\nSSH Connection To $host Failed Even With Old Kex\n"
                exit 1
            } else {
                # 第一次失败,尝试旧算法重连
                close
                wait
                ssh_connect $username $host $password 1
            }
        }
        "no matching key exchange" {
            # 捕获密钥交换错误,切换旧算法重连
            close
            wait
            ssh_connect $username $host $password 1
        }
        "*#" {
            return
        }
        "*assword:" {
            send "$password\n"
            expect "*#"
            return
        }
    }
}

# 调用连接函数,默认使用新设备参数
ssh_connect $username $host $password 0

优势

  • 代码复用性更高,后续修改交互逻辑只需调整一处
  • 自动处理两种连接场景,无需手动分支判断

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 15:17:32