在 bash 脚本中保持 SSH 开放

Cod*_*upt 2 ssh bash heredoc expect spawn

在任何人说使用公钥之前,这不是一个选项,因为我正在与客户服务器打交道。

我有一个脚本来维护一个文件,其中包含我客户服务器的所有 IP/用户名/密码。通过脚本,我选择了一个服务器并使用 here 文档来登录该服务器。

#### Code up here to set the variables.
exp_internal 1
/usr/bin/expect << EOFFF

if { $USE_TUNNEL == 1 } {
        spawn ssh -L 4567:localhost:3306 $user\@$ip
} else {
        spawn ssh $user\@$ip
}
expect {
    -re ".*es.*o.*" {
        exp_send "yes\r"
        exp_continue
    }
    -re ".*sword.*" {
        exp_send "$pass\r"
    }
}
expect {
    "$ " { send "<<<Send stuff>>>" }
    "# " { send "<<<Send stuff>>>" }
}
interact
EOFFF
# End of bash script
Run Code Online (Sandbox Code Playgroud)

我的问题是,在 here 文档结束后,它会关闭 SSH 会话并将我返回到我的本地服务器。我想保持远程 ssh 会话打开。

编辑 我在输出结束exp_internal 1之前添加if { $USE_TUNNEL == 1 } {如下:

spawn ssh ****@***.***.***.***
parent: waiting for sync byte
parent: telling child to go ahead
parent: now unsynchronized from child
spawn: returns {22819}

expect: does "" (spawn_id exp4) match regular expression ".*es.*o.*"? no
".*sword.*"? no
****@***.***.***.***'s password:
expect: does "tms6@161.19.242.206's password: " (spawn_id exp4) match regular expression ".*es.*o.*"? no
".*sword.*"? yes
expect: set expect_out(0,string) "****@***.***.***.***'s password: "
expect: set expect_out(spawn_id) "exp4"
expect: set expect_out(buffer) "****@***.***.***.***'s password: "
send: sending "***********\r" to { exp4 }

expect: does "" (spawn_id exp4) match glob pattern "$ "? no
"# "? no


expect: does "\r\n" (spawn_id exp4) match glob pattern "$ "? no
"# "? no
Last login: Thu Jun  4 13:39:10 2015 from ***.***.***.***

expect: does "\r\nLast login: Thu Jun  4 13:39:10 2015 from ***.***.***.***\r\r\n" (spawn_id exp4) match glob pattern "$ "? no
"# "? no
[***@********* ~]$
expect: does "\r\nLast login: Thu Jun  4 13:39:10 2015 from ***.***.***.***\r\r\n\u******@*********:~\u001b\[****@********* ~]$ " (spawn_id exp4) match glob pattern "$ "? yes
expect: set expect_out(0,string) "$ "
expect: set expect_out(spawn_id) "exp4"
expect: set expect_out(buffer) "\r\nLast login: Thu Jun  4 13:39:10 2015 from ***.***.***.***\r\r\n\**********@*********:~\u001b\[***@**************** ~]$ "
send: sending "mylist TerminalProfile | cut -d'"' -f6\r" to { exp4 }
interact: received eof from spawn_id exp0
[*****@********** sign_on_one_file]$
Run Code Online (Sandbox Code Playgroud)

我正在与客户服务器打交道,因此我为清除所有 IP/用户名/主机名/密码而道歉。

所以我们很清楚,当它让我回到提示时的最后一行是我本地机器的提示。不是我试图登录的遥控器。

当我将 expect 脚本提取到一个单独的文件中并将其称为 bash 脚本的最后一行时,它会按预期工作。我想将所有内容都放在一个文件中,以便轻松将脚本分发给我的同事。

编辑 2<<Send stuff>>只是我公司拥有的服务器上的一个功能。它是将 mysql 表打印为 csv 的包装器。

expect {
    "$ " { send "mylist TerminalProfile | cut -d'\"' -f6\r" }
    "# " { send "" }
}
interact
Run Code Online (Sandbox Code Playgroud)

Qiu*_*fan 5

我认为我们有同样的问题,因为将“交互”和 EOFFF 混合在一起。“交互”告诉期望脚本从标准输入读取,同时 EOFFF 在您的情况下意味着标准输入已关闭,然后您得到

“从 spawn_id exp0 收到 eof”

根据这个Embedding an expect inside a bash script,目前以下解决方案对我很好:

expect <(cat <<'EOD'
spawn ... (your script here)
EOD
)
Run Code Online (Sandbox Code Playgroud)

EOD 结束了 here-document,然后整个事情被包裹在一个 <( ) 进程替换块中。结果是 expect 将看到一个临时文件名,包括您的 here-document 的内容。


另外两个解决方案:

  1. 使用临时文件保存expect脚本然后执行脚本
  2. 使用expect的“-c”选项,将你的expect命令放在“-c”之后

我也期待一些其他的方法,你能告诉我你的吗?