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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5638321/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 18:33:55  来源:igfitidea点击:

Why child process returns exit status = 32512 in unix?

c++cshellunixposix

提问by Mihran Hovsepyan

In my program I'm executing given command and getting result (log, and exit status). Also my program have to support shell specific commands (i.e. commands which contains shell specific characters ~(tild),|(pipe),*). But when I try to run sh -c ls | wcin my home directory via my program it failed and its exit status was 32512, also in stderr stream "sh: ls | wc: command not found"was printed.

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

But the interesting thing is that the command sh -c ls | wcworks correct if I run it in shell.

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

What is the problem? Or more preferable how can I run shell specific commands via my program (i.ec which command with which parameters should I run)?

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

The code part bellow is in child part after fork(). It executs the command.

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

tokenized_commandis std::vector<std::string>where in my case "sh", "-c", "ls", "|", "wc"are stored, also I have tried to store there "sh", "-c", "\"ls | wc\""but result is same. commandis char *where full command line is stored.

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);
        }

P.S.

聚苯乙烯

I know that using system(command)instead execvpcan solve my problem. But system()waits until command is finished, and this is not good enough for my program. And also I'm sure that in implementation of system()one of exec-family functions is used, so the problem can be solved via execas well, but I don't know how.

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

回答by ikegami

execvptakes a path to an executable, and arguments with which to launch that executable. It doesn't take bourne shell commands.

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

ls | wcis a bourne shell command (among others), and it can't be broken down into the path to an executable and some arguments due to the use of a pipe. This means it can't be executed using execvp.

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

To execute a bourne shell command using execvp, one has to execute shand pass -cand the command for arguments.

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

So you want to execute ls | wcusing execvp.

所以你想ls | wc使用execvp.

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

execvp(argv[0], argv)

You apparently tried

你显然试过

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

That would be the same as bourne shell command sh -c ls '|' wc.

这与 bourne shell command 相同sh -c ls '|' wc

And both are very different than shell command sh -c ls | wc. That would be

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

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

You seem to think |and wcare passed to the sh, but that's not the case at all. |is a special character which results in a pipe, not an argument.

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



As for the exit code,

至于退出代码,

##代码##

32512 = 0x7F00

32512 = 0x7F00

So it didn't die from a signal, a core dump wasn't produced, and it exited with code 127 (0x7F).

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

What 127 means is unclear, which is why it should accompanied by an error message. You tried to execute program ls | wc, but there is no such program.

127 是什么意思不清楚,这就是为什么它应该伴随着错误信息。您试图执行 program ls | wc,但没有这样的程序。

回答by pajton

You should execute sh -c 'ls | wc'.

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

Option -cexpects a command in form of string. In shell of course it is working, because there is no difference between spawning lsand redirecting output to wcand launching ls | wcin separate shell.

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