从 stdin 读取程序输出而不是使用 spawn

Read program output from stdin instead of using spawn

我正在尝试编写一个 shell 函数来生成 ssh 进程并使用密码进行身份验证。然后,我想使用生成的进程对 expect 做更多的事情。

这是我目前拥有的功能:

ssh_cmd() {
    ssh $USER@$HOST 2>&1 | expect -c "
        log_user 0
        set timeout 5
        expect password: {
            send \"$PASS\n\"
            sleep 2
            log_user 1
        }
    "
}

然后我想在其他地方使用给定的函数来与 ssh 进程交互,如下所示:

ssh_cmd | expect -c "
    expect '#' {
        send pwd\n
        send exit\n
    }
    expect eof
"

但是,运行 带有 -d 选项的 ssh_cmd 函数 expect 我得到以下结果:

expect version 5.45.4

expect: does "" (spawn_id exp0) match glob pattern "password:"? no
ubnt@ui1's password: expect: timed out

据我了解,ssh 的输出没有正确传输。我知道执行此操作的常用方法是使用 spawn,但这意味着该进程将在 expect 退出后被终止,并且我无法拥有一个通用函数来验证 ssh 会话并使该进程保持活动状态以供进一步使用.

你设计的东西行不通。 Expect 需要使用 spawn 命令从 expect 解释器中生成进程。将命令的标准输出传递给 expect 是不够的。

你可以试试这个:

ssh_cmd() {
    # a default bit of code if user does not provide one.
    # you probably want some checking and emit an error message.
    local user_code=${1:-set timeout 1; send "exit\r"; expect eof}
    expect -c "
        log_user 0
        set timeout 5
        spawn ssh -l $USER $HOST
        expect password: {
            send \"$PASS\n\"
            sleep 2
            log_user 1
        }
        $user_code
    "
}

然后像这样调用它:

ssh_cmd '
    expect "#" {
        send pwd\r
        send exit\r
    }
    expect eof
'

请注意,单引号在 expect 中没有特殊含义,它们只是普通字符:您可能不希望提示符是 3 字符模式 '#'