当前位置: 首页 > 知识库问答 >
问题:

如何在expect shell脚本中获取派生进程的退出代码?

洪飞鸿
2023-03-14

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

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退出。

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

共有3个答案

韩欣怿
2023-03-14

经过几天的努力,我终于找到了另一种方法,我认为它可能对需要帮助的人有所帮助。我的要求是将命令和密码传递给shell函数,在远程主机中作为expect-herdoc的一部分执行该命令,并获取返回退出代码。

示例:

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

shell_function <cmd> <password>
echo $?

与其他人一样,在herdoc中扩展变量也是一个问题,这需要将值导出到环境变量中,并使用env获取herdoc中的变量。因为,password是我不想将其存储为环境变量的一部分的参数之一。因此,不再用单引号括住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: $?"

在上面的代码中,转义的expect变量是$result。将变量更改为\$result后,脚本开始正常工作。

我真诚地感谢那些为以下问题提供答案的用户,这些问题是实现我的解决方案的垫脚石。

Douglas Leeder:帮助使用expect脚本,在远程comp上运行cat并将其输出到变量

glenn jackman:如何在Expect脚本中返回生成的进程退出代码?

顾超
2023-03-14

在格伦的帮助下,我找到了解决办法。。我最后的剧本是::

期望脚本是

 [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

再次感谢格伦。。

萧鸿轩
2023-03-14

您可以使用等待命令获得生成进程的退出状态:

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手册页

等等

延迟,直到生成的进程(如果未命名,则为当前进程)终止。

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

改变

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

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

然后添加lassignif命令。

 类似资料:
  • 问题内容: 我试图执行一个脚本,该脚本执行一个EXPECT脚本和一个生成的进程,其中包含退出代码。但是我无法将生成的进程的退出代码获取到主脚本。作为成功,我总是零。 期望脚本是: 产生的脚本: 执行Expect脚本: 问题是我无法获得生成的退出返回代码以期望脚本。我希望生成脚本的退出代码3到主脚本,并且主脚本应该以退出代码3退出。 请帮助我将生成的退出代码获取到主脚本。 问题答案: 在格伦的帮助下

  • 问题内容: 我使用Expect运行测试脚本。通过退出代码测试返回成功/失败。但期望返回等效的退出代码。如何使期望返回正确的退出状态? 我的测试是使用 psql (postgresql命令处理器)运行的sql脚本。由于psql不允许将数据库密码指定为命令行参数,因此需要 脚本来 执行。 因此,我的期望脚本如下所示: 问题答案: 您已经在循环结束时等待了,您只需要使用和结果即可: 以0退出。 以1.退

  • 本文向大家介绍C# 获取进程退出代码的实现示例,包括了C# 获取进程退出代码的实现示例的使用技巧和注意事项,需要的朋友参考一下 我需要写一个程序,让这个程序知道另一个程序是否正常退出,于是就需要获取这个进程的退出代码 在程序如果需要手动退出,可以设置当前的退出代码 这时的程序运行就退出,同时退出的代码就是 -100 这和 C 语言的在 main 函数返回值一样 在 C# 如果想要实现 C 语言的

  • 问题内容: 在Jenkinsfile Groovy脚本阶段,假设我要发出一个Linux命令来输出字符串的行和列,并想要在特定行的输出中获取第n列。这样的命令的一个示例是“ ls -al”。所以我这样做正确吗? 但是,如何获取本质上为$ {COL [4]}的值,该值是“ ls -al”命令的第五列,即目录大小? 谢谢! 问题答案: 您在示例中显示的bash脚本不会返回正确的目录大小。它将以递归方式返

  • 问题内容: 使用Python的模块和方法时,如何检索退出代码? 相关代码: 我应该以其他方式这样做吗? 问题答案: 完成后将设置属性(*)。这是相关的文档部分: 所以您可以做(我没有测试过,但是应该可以): (*)发生这种情况的原因是它的实现方式:设置线程以读取子流后,它仅调用。

  • 在Jenkinsfile Groovy脚本阶段,假设我想发出一个linux命令来输出字符串的行和列,并希望在某一行的输出中获取第n列。此类命令的示例是“ls-al”。所以我做得对吗? 但是我如何获得${COL[4]}的值,这是“ls-al”命令中的第五列,即目录大小? 谢谢