如何获得在expect内运行的脚本的退出代码



一段时间以来,我正在努力获得我从预期内运行的脚本的退出代码。这是一个BASH脚本,有问题的部分如下所示:

expect -c "
log_file $LOG
spawn su - $ora_user
expect ""
send "source $oraenv_binaryr"
expect "ORACLE_SID = [$ora_user] ?"
send "$SIDr"
expect "The Oracle base has been set to /oracle/$SID"
send "$execPATHroot/$subscript $args_subscriptr"
expect ""
send "echo $?r"
expect -re "(\d+)" {
set result $expect_out(1,string)
}
send_user "subscript exit code: $result"
log_file
send "exitr"
expect ""
exit [lindex $result 3]"
sub_rc=$?

需要说明的是,这是获得代码的许多尝试之一,但是没有成功。我想我的问题在于错误转义字符或错误使用括号.....

调试时,我得到以下内容:

[336] oraenv_binary=/usr/local/bin/oraenv
[338] expect -c '
log_file /var/opt/osit/oracle/log/ora_sbp_patching_root.bash.log
spawn su - oracle
expect
send "source /usr/local/bin/oraenvr"
expect "ORACLE_SID = [oracle] ?"
send "H95r"
expect "The Oracle base has been set to /oracle/H95"
send "/opt/osit/oracle/bin/ora_sbp_patching_orausr.bash -s H95 -a CHECK -p /imports/e2r2s48ifde0002/CDSAP/DB/oracle/ORA19/SBP/SBP_1915_220419_202205 -h /imports/e2r2s48ifde0002/CDSAP/DB/oracle/ORA19/SBP/SBP_1915_220419_202205/README19P_2205-70004508.HTM -u oracler"
expect
send "echo $?r"
expect -re "(d+)" {
set result $expect_out(1,string)
}
send_user "subscript exit code: $result"
log_file
send "exitr"
expect
exit [lindex $result 3]'

…下标在这里运行,退出码为0

-sh-4.2$ subscript exit code: decho $?
0
-sh-4.2$ exit
logout
expected integer but got ""
while executing
"exit [lindex $result 3]"
[357] sub_rc=0

在我看来,正则表达式部分"(d+)"不太好,但也许,它完全是一个烂摊子……: -)请帮助。

我已经阅读并尝试了这些建议:有没有一种方法来期望输出而不从Tcl期望的缓冲区中删除它?

https://wiki.tcl-lang.org/page/How +期望+ +可以捕获+ +退出+代码+ + +远程+命令

https://www.unix.com/shell-programming-and-scripting/144812-expect-script-obtain-exit-code-remote-command.html

你有这个

expect -re "(d+)" {
set result $expect_out(1,string)
}
send_user "subscript exit code: $result"
我们可以看到输出是
-sh-4.2$ subscript exit code: decho $?
0

因为正则表达式"(d+)"双引号中,将发生反斜杠替换,并且模式变为可能不匹配的(d+)(在那一点上您是否得到10秒延迟?)—我怀疑这就是为什么$result为空的原因。

反斜杠在正则表达式中很普遍。使用大括号将它们括起来是正确的方法:

expect -re {d+} {set result $expect_out(0,string)}

使用expect -d运行期望代码(或在代码中设置exp_internal 1)会发出非常详细的期望调试输出,这对于查看模式是否匹配非常有用。


在此处使用带引号的shell比使用带引号的字符串封装代码更可取。

考虑
expect -c "
send_user "my home is $env(HOME)\n"
"

expect << 'END_CODE'
send_user "my home is $env(HOME)n"
END_CODE

使用这种技术,您可以通过环境传递shell变量:

export ora_user=oracle
expect << 'END_EXPECT'
#...
spawn su - $env(ora_user)
END_EXPECT

非常感谢你的回答Glenn,提到了一些有趣的观点。关于大括号和双引号-我已经这样改变了,但是没有效果。我在我的代码中用反斜杠转义了那些双引号-我认为效果是一样的,但是,它对我来说肯定看起来更好,显然它更安全。我玩了期望的调试模式-谢谢,我可以看到更多的信息。我注意到expect包含的东西比我"预期"的要多得多。: -)

= =比;这只是一个片段:

.rn-sh-4.2$ " (spawn_id exp7) match regular expression "d+"? (No Gate, RE only) gate=yes re=yes
expect: set expect_out(0,string) "4"
expect: set expect_out(spawn_id) "exp7"
expect: set expect_out(buffer) "rn-sh-4"
can't read "expect_out(1,string)": no such element in array
while executing
"set result $expect_out(1,string)"
invoked from within
"expect -re {d+} {set result $expect_out(1,string)}"

正如你所看到的,当我发送要执行的下标时,我期待"也就是说,什么都没有,只有新的提示行。然而,在这一点上,expect充满了东西,而不是完全空白——我认为,我需要准确地定义提示符:

-sh-4.2$

,然后我需要期待它,连同回显的退出代码$?并以某种方式分离退出码整数来得到我想要的......我会继续努力的。

最终有效的代码如下(大部分归功于Glenn的众多建议):

expect -c "
log_file $LOG
spawn su - $ora_user
expect -re {$ $}
send "PS1='>'r"
expect -re {>$}
send "source $oraenv_binaryr"
expect {ORACLE_SID = [$ora_user] ? }
send "$SIDr"
expect "The Oracle base has been set to /oracle/$SID"
send "$execPATHroot/$subscript $args_subscriptr"
expect { (subscript) ; exp_continue }
expect -re {>$}
send "echo $?r"
expect -re {(d+)rn>$} {set result $expect_out(1,string)}
send_user "subscript exit code:$resultn"
log_file
send "exitr"
expect "logout"
exit [lindex $result 0]"
sub_rc=$?
echo sub_rc:$sub_rc

spawn su - $ora_user之后的第一件事是通过send "PS1='>'r"设置提示符,以便使带有提示符的新行不那么干扰。

然后在send "$execPATHroot/$subscript $args_subscriptr"之后,我使用了这样一个事实,即我已经编写了下标,使每一行输出都由(subscript)关键字填充。因此,当下标产生输出时,期望继续按exp_continue进行。

$subscript结束时,出现>提示符,期望发送echo $?获取$subscript的退出码。这在屏幕上显示为:

>echo $?
0
>

,所以代码应该期待整数,返回和新的行提示-即{(d+)rn>$}。此时期望匹配输出,expect_out(1,string)被正确填充:

send: sending "echo $?r" to { exp7 }
Gate keeper glob pattern for '(d+)rn>$' is '*
>'. Activating booster.
expect: does "" (spawn_id exp7) match regular expression "(d+)rn>$"? Gate "*rn>"? gate=no
echo $?
0
>
expect: does "echo $?rn0rn>" (spawn_id exp7) match regular expression "(d+)rn>$"? Gate "*rn>"? gate=yes re=yes
expect: set expect_out(0,string) "0rn>"
expect: set expect_out(1,string) "0"
expect: set expect_out(spawn_id) "exp7"
expect: set expect_out(buffer) "echo $?rn0rn>"

另一件要提到的事情是nsend_user "subscript exit code:$resultn"中,所以有新的行下…

最后修改的代码是:

exit [lindex $result 0]"

我已经将索引更改为0,因为变量结果只有一个项目,索引0代表列表中的第一个项目。

最新更新