【问题标题】:How to get the exit code of spawned process in expect shell script?如何在期望 shell 脚本中获取生成进程的退出代码?
【发布时间】:2014-05-12 16:18:32
【问题描述】:

我正在尝试执行一个脚本,该脚本执行一个 EXPECT 脚本和一个包含退出代码的衍生进程。但是我无法将生成的进程的退出代码获取到主脚本。我总是得到零作为成功。

期望脚本是:

 [Linux Dev:anr ]$ cat testexit.sh
 #!/bin/bash
 export tmp_script_file="/home/anr/tmp_script_temp.sh"
 cp /home/anr/tmp_script $tmp_script_file
 chmod a+x $tmp_script_file
 cat $tmp_script_file
 expect << 'EOF'
 set timeout -1
 spawn  $env(tmp_script_file)
 expect {
 "INVALID "  { exit 4 }
 timeout     { exit 4 }
 }
 EOF
 echo "spawned process status" $?
 rm -f $tmp_script_file
 echo "done"

衍生脚本:

 [Linux Dev:anr ]$ cat tmp_script
 exit 3

Expect 脚本的执行:

 [Linux Dev:anr ]$ ./testexit.sh
 exit 3
 spawn /home/anr/tmp_script_temp.sh
 spawned process status 0
 done

问题是我无法让生成的退出返回码期待脚本。我希望生成脚本的退出代码 3 到主脚本,主脚本应该以退出代码 3 退出。

请帮助我将生成的退出代码获取到主脚本。

【问题讨论】:

  • 尝试将期望部分放在单独的文件中,即可执行期望脚本,然后尝试获取退出状态。
  • @Jord,我只需要在 shell 脚本中编写期望方法。它不应该是单独的可执行文件。
  • 我从link 得到了一些答案,但无法将该解决方案整合到我的代码中。我是期望方法的新蜜蜂。

标签: linux bash shell unix expect


【解决方案1】:

您可以使用wait 命令获得衍生进程的退出状态:

expect <<'END'
log_user 0
spawn sh -c {echo hello; exit 42}
expect eof
puts $expect_out(buffer)

lassign [wait] pid spawnid os_error_flag value

if {$os_error_flag == 0} {
    puts "exit status: $value"
} else {
    puts "errno: $value"
}
END
hello

exit status: 42

来自expect man page

等待 [args]

延迟到一个衍生进程(或当前进程,如果没有命名)终止。

wait 通常返回四个整数的列表。第一个整数是等待的进程的 pid。第二个整数是对应的 spawn id。如果发生操作系统错误,则第三个整数为 -1,否则为 0。如果第三个整数为 0,则第四个整数是衍生进程返回的状态。如果第三个整数是-1,第四个整数就是操作系统设置的errno值。还设置了全局变量errorCode。


改变

expect {
"INVALID "  { exit 4 }
timeout     { exit 4 }
}

expect {
    "INVALID "  { exit 4 }
    timeout     { exit 4 }
    eof
}

然后添加lassignif 命令。

【讨论】:

  • 你的期望一定很老了。改用这个:foreach {pid spawnid os_error_flag value} [wait] break
  • 您能解释一下为什么使用“[ ]”来包含等待命令吗?
  • 这是 Tcl 命令替换语法。您必须执行命令,然后将结果捕获到变量中。参考tcl.tk/man/tcl8.6/TclCmd/Tcl.htm规则号7
【解决方案2】:

在 glenn 的帮助下,我得到了解决方案.. 我的最终脚本是::

期望脚本是

 [Linux Dev:anr ]$ cat testexit.sh
 #!/bin/bash
 export tmp_script_file="/home/anr/tmp_script_temp.sh"
 cp /home/anr/tmp_script $tmp_script_file
 chmod a+x $tmp_script_file
 cat $tmp_script_file
 expect << 'EOF'
 set timeout -1
 spawn  $env(tmp_script_file)
 expect {
 "INVALID "  { exit 4 }
 timeout     { exit 4 }
 eof
 }

 foreach {pid spawnid os_error_flag value} [wait] break

 if {$os_error_flag == 0} {
     puts "exit status: $value"
     exit $value
 } else {
     puts "errno: $value"
     exit $value
 }
 EOF
 echo "spawned process status" $?
 rm -f $tmp_script_file
 echo "done"

衍生脚本:

 [Linux Dev:anr ]$ cat tmp_script
 exit 3

Expect 脚本的执行:

 [Linux Dev:anr ]$ ./testexit.sh
 exit 3
 spawn /home/anr/tmp_script_temp.sh
 exit status: 3
 spawned process status 3
 done

再次感谢格伦..

【讨论】:

  • 感谢分享您的解决方案。 foreach {pid spawnid os_error_flag value} [wait] break 比 @glennjackman 的 lassign [wait] pid spawnid os_error_flag value 有什么好处?
  • lassign 到达 Tcl 8.5。 foreach 是旧 Tcls 的方法
【解决方案3】:

在为期望的heredoc中扩展变量苦苦挣扎了几天之后,最后我遇到了另一种我认为可能对有需要的人有所帮助的方法。我的要求是将命令和密码传递给 shell 函数,在远程主机中执行命令作为期望 heredoc 的一部分并获取返回退出代码。

例子:

function shell_function {
   # Get the command and password as arguments
   # Run command using expect
   # Return the exit code
}

shell_function <cmd> <password>
echo $?

像其他人一样,在 heredoc 中扩展变量是一个问题,需要将值导出到环境变量中并使用 env 来获取 heredoc 中的变量。因为,密码是我不想将其存储为环境变量的一部分的参数之一。因此,不是用单引号括住heredoc 开头,而是对heredoc 的变量进行了转义。这允许直接使用传递的参数。

以下是最终脚本:

#! /bin/bash
# This function runs a command like 'ssh' and provides the password
function run_with_password {
    cmd="$2"
    paswd="$1"
    expect << END
        set timeout 60
        spawn $cmd
        expect {
            "yes/no" { send "yes\r" }
            "*assword*" { send -- $paswd\r }
        }
        expect EOF
        catch wait result
        exit [lindex \$result 3]
END
}

my_password="AnswerIS42Really?"
cmd_to_run="ssh userid@hostname"
cmd_to_run="$cmd_to_run ls .sawfish"
run_with_password $my_password "$cmd_to_run"
echo "Command run code: $?"

在上面的代码中,转义的期望变量是$result。将变量更改为\$result 后,脚本开始像魅力一样工作。

衷心感谢为以下问题提供答案的用户,这是我找到解决方案的垫脚石。

Douglas Leeder: help with expect script, run cat on remote comp and get output of it to the variable

glenn jackman: How to return spawned process exit code in Expect script?

【讨论】:

    猜你喜欢
    • 2012-03-04
    • 2011-08-13
    • 1970-01-01
    • 2013-08-28
    • 2022-01-13
    • 2010-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多