【问题标题】:Get the return code of a C program in my shell program在我的 shell 程序中获取 C 程序的返回码
【发布时间】:2015-12-26 19:23:42
【问题描述】:

假设我有一个名为 Foo.c 的 C 程序,它正在打印一些东西并返回一个名为 rc 的值,我在我的 shell 程序中执行如下:

foobar=$(Foo | tail -1)

现在,变量 foobar 具有程序 Foo 的最后打印值。但是在不打扰这一点的情况下,我想在我的shell程序中获取程序的返回码rc

【问题讨论】:

  • 使用$?变量。
  • 我不确定 $?在这种情况下有效,因为他使用的是管道。所以最后执行的命令是tail -1。
  • 我做了一个简单的测试,它不起作用。最后返回的值为尾部返回码
  • 它不工作。美元?即使我将 rc 值硬编码为 rc=100; return rc;,变量也会显示值 0
  • 查看man bash管道的返回状态是最后一条命令的退出状态

标签: c bash shell


【解决方案1】:

$? 给出最后执行命令的返回值。

【讨论】:

  • @sat 的回答解释了为什么$? 不适用于这个问题。
【解决方案2】:

您可以使用“set -o pipefail”选项。

[root@myserver Test]# set -o pipefail
[root@myserver Test]# ./a.out | tail -l
[root@myserver Test]# echo $?
100

这里我的程序 a.out 返回 100。

或者另一种选择是使用 pipestatus 环境变量。你可以在这里读到它。 http://www.linuxnix.com/2011/03/pipestatus-internal-variable.html

【讨论】:

  • 有趣的选项。就像一个注释。这仅在管道中的所有其他程序返回 0 时才有效。来自 doc 链接:只要测试程序后面的程序都没有报告非零退出代码,管道将报告其退出代码为测试程序。
【解决方案3】:

如果您使用bash shell,您可以使用PIPESTATUS 数组变量来获取pipe 进程的状态。

$ tail sat | wc -l
tail: cannot open ‘sat’ for reading: No such file or directory
0
$ echo "${PIPESTATUS[0]} ${PIPESTATUS[1]}"
1 0
$

来自man bash

管道状态

一个数组变量,包含最近执行的前台管道(可能只包含一个命令)中进程的退出状态值列表。

【讨论】:

    【解决方案4】:

    这会将Foo 的输出的最后一行分配给foobar,并将Foo 的退出代码分配给code

    { read -r foobar; read code; } < <( (Foo; echo $? ) | tail -2)
    

    &lt;(...) 构造称为进程替换。在上面的代码中,read 命令从进程替换中接收它们的标准输入。由于tail -2,进程替换总共产生两行。第一行是Foo 产生的最后一行,它被分配给foobar。第二个分配给code

    第一个和第二个&lt; 之间的空格是必不可少的。

    示例

    创建函数Foo后,可以测试上面的内容:

    $ Foo() { echo "Testing"; false; }
    $ { read -r foobar; read code; } < <( (echo "Testing"; false; echo $? ) | tail -2)
    $ echo "foobar=$foobar code=$code"
    foobar=Testing code=1
    

    还有:

    $ Foo() { echo "2nd Test"; true; }
    $ { read -r foobar; read code; } < <( (Foo; echo $? ) | tail -2)
    $ echo "foobar=$foobar code=$code"
    foobar=2nd Test code=0
    

    【讨论】:

    • 嘿 John.. 感谢您的回答,但 Foo 是一个 C 函数。
    • 但是如果Foo 没有输出任何东西,或者它的最后一行输出没有以换行符结尾,这将失败。
    • @kirtan Foo 是否是 C 函数没有区别。该脚本的工作方式相同。
    【解决方案5】:

    恐怕你必须使用临时文件来存储Foo程序的输出,获取返回码然后执行tail -1。就像下面这样:

    Foo > /tmp/temp_file
    ret=$?
    foobar=$(tail -1 /tmp/temp_file)
    

    【讨论】:

    • 这是在 portable shell 中执行此操作的唯一方法。
    • ... 但是,您的演示应该使用mktemp 并在之后删除暂存文件。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-25
    • 1970-01-01
    • 2019-12-04
    • 2020-04-21
    相关资源
    最近更新 更多