为什么subprocess在UNIX下返回退出状态= 32512?

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

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

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

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

tokenized_commandstd::vector<std::string>其中在我的情况下, "sh", "-c", "ls", "|", "wc"被存储,也试图在那里存储"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); } 

PS

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

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

ls | wc ls | wc是一个bourne shell命令(等等),并且由于使用了一个管道,它不能被分解成可执行文件和一些参数的路径。 这意味着它不能使用execvp执行。

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

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

 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 sh -c ls '|' wc

和shell命令sh -c ls | wc完全不同 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)退出。

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

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

选项-c需要一个字符串形式的命令。 在shell中当然是有用的,因为在产生ls和重定向输出到wc和启动ls | wc之间没有区别ls | wc ls | wc在单独的shell中。