【问题标题】:How to get the exit code of program invoked by system call?如何获取系统调用调用的程序的退出代码?
【发布时间】:2013-11-25 12:44:18
【问题描述】:

例如,程序a.out:

int main()
{
    return 0x10;
}

程序b.out:

int main()
{
    if(system("./a.out") == 0x10)
       return 0;
    else
       return -1;
}

根据cppreference,system() 的返回值依赖于实现。因此,程序b.out的尝试显然是错误的。

在上述情况下,我怎样才能得到0x10 而不是未确定的值? 如果系统调用不是正确的工具,那么正确的方法是什么?

【问题讨论】:

  • 它是实现定义的,这意味着您需要在 unix 或 unix like environment 上查找文档,例如,man system 会告诉您所需的详细信息。
  • system 对此有点重。你真的想为此启动一个shell吗?如果调用代码都以 root 身份运行,或者在一个奇怪的环境中运行,那么这是一个安全禁忌。
  • @NicholasWilson 这是一个很好的观点。你能描述一下建议的方法吗?
  • @southp 只需 fork 和 exec。如果您真的需要使用 shell 语法(例如 system("./a.out | anotherapp 2>/dev/null"))并且无需费心在代码中设置所需的管道或重定向,则应该只使用 system。

标签: c++


【解决方案1】:

引用man system:

The value returned is -1 on  error  (e.g.   fork(2)  failed),  and  the
return  status  of the command otherwise.  This latter return status is
in the format specified in wait(2).  Thus, the exit code of the command
will  be  WEXITSTATUS(status).   In case /bin/sh could not be executed,
the exit status will be that of a command that does exit(127).

您需要使用WEXITSTATUS 来确定命令的退出代码。您的 b.c 需要类似于:

#include <stdio.h>
#include <sys/wait.h>
int main()
{
    int ret = system("./a.out");
    if (WEXITSTATUS(ret) == 0x10)
      return 0;
    else
      return 1;
}

【讨论】:

  • 也许更便携,if (WIFEXITED(ret) &amp;&amp; WEXITSTATUS(ret) == ...)?
  • 如果您使用 Visual C++,您将如何做到这一点?我们不能使用&lt;sys/wait.h&gt;
【解决方案2】:

系统调用很好,但是你必须注意你的命令才能执行。 我运行类似'myscript.sh p1 p2 p3 | tee /mylog' 并且总是恢复正常。 问题是管道。系统总是返回最后一个始终有效的命令的退出代码,而不是 myscript 的结果。 因此,如果您不期望第一个命令的退出代码,请仅在命令中使用管道执行。

【讨论】:

    【解决方案3】:

    如果你在 unix 系统上,你应该使用 fork execve 并等待。

    这里是您案例的示例代码:

    Program b.out:
    
    int main()
    {
        return 0x10;
    }
    
    pRogram a.out:
    
    int main()
    {
     int pbPid = 0;
     int returnValue;
     if ((pbPid = fork()) == 0) // Fork create a child process
     {
      // Only executed in child process
      char* arg[]; //argument to program b
      execv("pathto program b", arg);
      exit(34);
     }
     else
     {
      // Only executed in parent(original) process
      waitpid(pbPid, &returnValue, 0);
     }
     returnValue = WEXITSTATUS(returnValue);
     // returnValue will be 34 if exeve failed
     return 0;
    }
    

    【讨论】:

    • 如何处理 execv 的错误返回?考虑到所有奇怪的 WEXITSTATUS 东西,exit(-1) 真的足够好吗? (对不起。来自 Windows 世界,这一切都更加明显)
    • 我更新了代码,希望现在更明显:)
    猜你喜欢
    • 1970-01-01
    • 2013-02-06
    • 2020-05-19
    • 2018-05-17
    • 2019-07-21
    • 2021-12-04
    • 2022-11-10
    • 1970-01-01
    • 2013-12-18
    相关资源
    最近更新 更多