【问题标题】:Why child process returns exit status = 32512 in unix?为什么子进程在 unix 中返回退出状态 = 32512?
【发布时间】:2011-08-04 01:04:05
【问题描述】:

在我的程序中,我正在执行给定的命令并获取结果(日志和退出状态)。此外,我的程序必须支持特定于 shell 的命令(即包含特定于 shell 的字符 ~(tild)、|(pipe)、* 的命令)。但是,当我尝试通过我的程序在我的主目录中运行 sh -c ls | wc 时,它失败了,它的退出状态为 32512,也在 stderr 流中打印了 "sh: ls | wc: command not found"

但有趣的是,如果我在 shell 中运行命令sh -c ls | wc,它可以正常工作。

有什么问题?或者更可取的是如何通过我的程序运行特定于 shell 的命令(即我应该运行哪个命令和哪个参数)?

下面的代码部分在 fork() 之后的子部分中。它执行命令。

tokenized_commandstd::vector<std::string>,在我的情况下,"sh", "-c", "ls", "|", "wc" 被存储,我也尝试在那里存储"sh", "-c", "\"ls | wc\"",但结果是一样的。 commandchar *,其中存储了完整的命令行。

        boost::shared_array<const char *> bargv(new const char *[tokenized_command.size() + 1]);
        const char **argv = bargv.get();
        for(int i = 0; i < tokenized_command.size(); ++i)
        {
            argv[i] = tokenized_command[i].c_str();
            printf("argv[%d]: %s\n", i, argv[i]); //trace
        }
        argv[tokenized_command.size()] = NULL;

        if(execvp(argv[0], (char * const *)argv) == -1)
        {
            fprintf(stderr, "Failed to execute command %s: %s", command, strerror(errno));
            _exit(EXIT_FAILURE);
        }

附言

我知道使用system(command) 代替execvp 可以解决我的问题。但是system() 等到命令完成,这对我的程序来说还不够好。而且我确信在system()的实现中使用了exec-family函数之一,所以问题也可以通过exec解决,但我不知道如何。

【问题讨论】:

  • 请给出一些代码来显示你是如何运行 shell 命令的,并收集结果和退出状态。
  • 我没有看到与cc++ 标签相关的任何内容,因此我删除了它们。
  • 我添加了一些与cc++ 相关的内容。

标签: c++ c shell unix posix


【解决方案1】:

execvp 获取可执行文件的路径,以及用于启动该可执行文件的参数。它不需要 bourne shell 命令。

ls | wc 是一个 bourne shell 命令(以及其他命令),由于使用管道,它不能分解为可执行文件的路径和一些参数。这意味着它不能使用execvp 执行。

要使用 execvp 执行 bourne shell 命令,必须执行 sh 并传递 -c 和命令作为参数。

所以你想使用execvp 执行ls | wc

char *const argv[] = {
    "sh",
    "-c", "ls | wc",  // Command to execute.
    NULL
};

execvp(argv[0], argv)

你显然尝试过

char *const argv[] = {
    "sh",
    "-c", "ls",  // Command to execute.
    "|",         // Stored in called sh's $0.
    "wc",        // Stored in called sh's $1.
    NULL
};

这与 bourne shell 命令sh -c ls '|' wc 相同。

两者都与 shell 命令sh -c ls | wc 非常不同。那是

char *const argv[] = {
    "sh",
    "-c", "sh -c ls | wc",  // Command to execute.
    NULL
};

您似乎认为|wc 被传递给sh,但事实并非如此。 | 是一个特殊字符,它产生一个管道,而不是一个参数。


至于退出代码,

Bits 15-8 = Exit code.
Bit     7 = 1 if a core dump was produced.
Bits  6-0 = Signal number that killed the process.

32512 = 0x7F00

所以它没有因信号而死,也没有产生核心转储,它以代码 127 (0x7F) 退出。

127 的含义尚不清楚,这就是为什么它应该伴随着错误消息。您尝试执行程序ls | wc,但没有这样的程序。

【讨论】:

  • 不,我收到错误消息。对不起,我没有把它放在这里。 sh: ls | wc: command not found这是消息/
  • @Mihran Hovsepyan,您正在尝试执行名为“ls | wc”的文件,而不是执行 bourne shell 命令“ls | wc”。如果要执行 bourne shell 命令,则需要启动 bourne shell 并将命令传递给它。 sh -c 'ls | wc'.
  • 我不想吃午餐壳。我不想从我的程序中运行特定于 shell 的命令。
  • @Mihran Hovsepyan。目前尚不清楚你的意思是什么。如果您的意思是要避免运行 shell,那么您根本无法执行 ls | wc。如果你的意思是你想让 shell 可配置,我真的不明白这一点,但没有什么能阻止你。
  • @Mihran Hovsepyan。如果你想避免运行 shell,你需要启动两个进程(一个是ls,另一个是wc),在进程中在它们之间创建一个管道。您还必须管理两个进程而不是一个进程的终止。自己从lswc 实现您想要的功能甚至可能更容易。
【解决方案2】:

你应该执行sh -c 'ls | wc'

选项-c 需要字符串形式的命令。在 shell 中它当然可以工作,因为生成 ls 和将输出重定向到 wc 和在单独的 shell 中启动 ls | wc 之间没有区别。

【讨论】:

  • 实际上,它可能生成了一个单独的 shell 来运行 ls 并且还生成了一个 wc 来接收它的输出。
  • 是的,我知道,我只是没有下划线。
猜你喜欢
  • 1970-01-01
  • 2021-05-01
  • 2015-03-11
  • 2012-01-17
  • 2020-10-24
  • 2012-04-21
  • 2017-03-19
  • 2010-10-28
  • 2014-11-01
相关资源
最近更新 更多