【发布时间】:2018-01-10 08:11:39
【问题描述】:
我正在尝试通过以下方式从 bash 调用期望脚本:
#!/bin/bash
mkfifo foobar
expectScript > foobar &
# other stuff that does stuff with foobar
expectScript 需要做的是 ssh 到远程主机。从那里它需要 ssh 到另一个远程主机。然后需要将用户切换到root(不允许root登录)。然后它需要发出一个最终需要写入 foobar 的命令(例如 tail -f /var/log/messages)。没有其他东西可以写入 foobar,例如密码提示或命令提示。只有命令的输出可以写入 foobar。我的脚本的登录部分工作正常。我正在努力解决的是如何将输出写入 foobar,并以 SIGINT 将终止命令的方式。
这是我所拥有的:
#!/usr/bin/expect --
set HOST1_USER myuser
set HOST2_USER myotheruser
set HOST1_PASSWORD mypassword
set HOST2_PASSWORD myotherpassword
set ROOT_PASSWORD anotherpassword
set HOST1 192.168.0.5
# HOST2 is only reachable from HOST1
set HOST2 192.168.1.12
global until_interrupt
set until_interrupt 0
set HOST1_PROMPT "CL-\\d.*#"
set HOST2_PROMPT "\\\$ $"
set ROOT_PROMPT "# $"
log_user 0
spawn ssh $HOST1_USER@$HOST1
# ssh keys are exchanged with HOST1, so there is no need for password here
expect -re "$HOST1_PROMPT" {
send "ssh HOST2_USER@$HOST2\n"
expect {
-re ".*ssword.*" { send "$HOST2_PASSWORD\n" }
-re ".*Are you sure you want to continue connecting.*" {send "yes\n"; exp_continue}
}
}
expect -re "$HOST2_PROMPT" { send "su\n" }
expect -re ".*ssword.*" { send "ROOT_PASSWORD\n" }
log_user 1
# nothing up to this point should have been sent to stdout
# now I want the output of the tail command to be sent to stdout
expect -re "$ROOT_PROMPT" { send "tail -f /var/log/messages\n" }
# I want to wait here until SIGINT is sent. There may be a better way than the traps below.
# Set a trap to watch for SIGINT
trap {
set until_interrupt sigint_detected
} SIGINT
while { $until_interrupt == 0 } {
#wait until sigint
}
send "\003"
# I think that is SIGINT, and that I'm sending it because I caught the first one in the trap.
trap {
exit
} SIGINT
set timeout 30
expect -re "$ROOT_PROMPT" { send "exit\n" }
expect -re "$HOST2_PROMPT" { send "exit\n" }
expect -re "$HOST1_PROMPT" { send "exit\n" }
# Fully exited
【问题讨论】:
-
大部分
expect脚本可以通过使用公钥身份验证和ssh内置的隧道支持来消除。 -
感谢 chepner,但没有什么可以消除的,因为在 HOST2 上我需要以 root 身份运行命令(sudo 不起作用),而 HOST2 不允许 root 通过 ssh 登录。所以需要先用非root用户登录,然后su到root。我已经在公钥认证工作的主机上实现了这个解决方案,而且要容易得多。但是对于这个特定的服务器,我看不出它是如何工作的。
-
如果你有root密码,你可以配置
sudo工作。没有什么可以阻止您在本地ssh配置文件中设置正确的用户 ID 和主机名。 -
谢谢chepner。我正在登录一个无法对 sudo 进行此类修改的系统,即使我有 root 密码。
-
还有一个警告让我无法完全避免期望,否则我肯定会走你建议的路线。即使在我以 root 身份登录后,我还需要运行另一个无法组合为 command1 的命令;命令2。 (command1 是 vrctl,因此为 command2 设置上下文。)
标签: linux bash stdout expect fifo