Expect 脚本没有退出我设置的代码

Expect script is not exiting with code I set it to

我尝试在 codereview 社区中发布这个,但是没有期望标签,而且我没有足够的业力来创建标签。

我编写了一个 expect 脚本来登录服务器或 运行 一个简单的(通常是单个)命令和 return 输出。

我有两个问题和一个愿望

此外,任何评论或(建设性的)批评将不胜感激。

 #!/usr/bin/expect -f

 if {[info exists ::env(SSH2SERVER_PASSWORD)]} {
   set password "$env(SSH2SERVER_PASSWORD)"

 } else {
   puts "SSH2SERVER_PASSWORD not set"
   exit 1
 }

 if {[llength $argv] < 2} {
   puts "usage: ssh2server user server"
   exit 1
 }

 set user    [lindex $argv 0]
 set server  [lindex $argv 1]
 set command [lrange $argv 2 end]

 set pwd_prompt "*assword:"
 set prompt "$ "

 set rc 0

 expect_before {
   #timeout { send_user 'timeout' ; exit 2 }
   timeout { send_user 'timeout' ; set rc 2}
 }

 log_user 0
 spawn ssh $user@$server
 expect "$pwd_prompt" { send -- "$password\r" }

 if { $command == "" } {
   interact

 } else {
   expect {
     "$prompt" {
       send -- "PROMPT_COMMAND=\rPS1='_MYPROMPT_'\r$command\r"
       #expect -re "$command\r\n(.*)\r\n\[^\r]*\[#$%]"
       expect -re "$command\r\n(.*)\r\n\[^\r]*_MYPROMPT_"
       set results $expect_out(1,string)
       puts $results
       send -- "^D"
       expect eof
       #catch wait ec
       #set rc [lindex $ec 3]
       #puts [lindex $ec 3]
       #exit [lindex $ec 3]
     }

     #eof { send_user $expect_out(buffer); exit 3}
     eof { send_user $expect_out(buffer); set rc 3}
   }
 }

 log_user 1

 lassign [wait] pid spawnid os_flag rc
 #puts $rc # outputs correct value
 exit $rc

我怀疑是这个问题:

       send -- "^D"

您发送的不是 Ctrl-D,而是字符 ^D.

发送 Ctrl-D

       send -- ""

要解决 "no output, timeout" 问题,您需要更改预期的正则表达式:对于这种情况,换行符太多。使用 expect -d 会向您揭示这一点。像这样:

       send -- "unset PROMPT_COMMAND; PS1='_MYPROMPT_'\r"
       expect -re "_MYPROMPT_$"

       send -- "$command\r"
       expect -re "$command(.*)\r\n_MYPROMPT_$"

捕获括号的内容现在可能为空。

为了清楚起见,我把设置提示分开了。


要捕获命令的退出状态,您可能需要这样做:

       send -- "$command; echo $?\r"
       expect -re "$command(.*)\r\n(\d+)\r\n_MYPROMPT_$"

       set results [regsub {^\r\n} $expect_out(1,string) ""]
       set status $expect_out(2,string)

不认为您可以使用expect 命令将stdout 和stderr 分开。我认为这两个流都被捕获为 "output"。 (我附近没有我的 Exploring Expect 书来确认)

如果这很重要,您可能需要调用命令将 stdout and/or stderr 重定向到文件,然后 cat 并捕获文件内容。