为什么子进程在unix中返回退出状态= 32512?

问题描述 投票:0回答:2

在我的程序中,我正在执行给定的命令并获取结果(日志和退出状态)。另外,我的程序必须支持 shell 特定命令(即包含 shell 特定字符 ~(tild)、|(pipe)、* 的命令)。但是,当我尝试通过我的程序在我的主目录中运行

sh -c ls | wc
时,它失败了,其退出状态为 32512,也在 stderr 流中打印了
"sh: ls | wc: command not found"

但有趣的是,如果我在 shell 中运行命令

sh -c ls | wc
,它就能正确工作。

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

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

tokenized_command
std::vector<std::string>
,在我的情况下,
"sh", "-c", "ls", "|", "wc"
存储在其中,我也尝试存储在那里
"sh", "-c", "\"ls | wc\""
,但结果是相同的。
command
char *
存储完整命令行的位置。

        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
解决,但我不知道如何解决。

c++ c shell unix posix
2个回答
32
投票

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

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

要使用

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

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
,但没有这样的程序。


1
投票

您应该执行

sh -c 'ls | wc'

选项

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

© www.soinside.com 2019 - 2024. All rights reserved.