Mih*_*yan 13 c c++ unix shell posix
在我的程序中,我正在执行给定的命令并获得结果(日志和退出状态).此外,我的程序必须支持特定于shell的命令(即包含shell特定字符〜(tild),|(管道),*)的命令.但是当我尝试sh -c ls | wc
通过我的程序在我的主目录中运行它失败并且它的退出状态是32512时,也"sh: ls | wc: command not found"
打印了stderr流.
但有趣的是,sh -c ls | wc
如果我在shell中运行它,该命令的工作正常.
问题是什么?或者更优选的是如何通过我的程序运行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);
}
Run Code Online (Sandbox Code Playgroud)
PS
我知道使用system(command)
相反execvp
可以解决我的问题.但system()
等到命令完成,这对我的程序来说还不够好.并且我确信在system()
使用exec-family函数之一时,也可以解决问题exec
,但我不知道如何解决.
ike*_*ami 26
execvp
获取可执行文件的路径,以及用于启动该可执行文件的参数.它不需要bourne shell命令.
ls | wc
是一个bourne shell命令(以及其他命令),由于使用了管道,它不能分解为可执行文件的路径和一些参数.这意味着它无法使用execvp
.
要使用bourne shell命令execvp
,必须执行sh
并传递-c
参数命令.
所以你想要执行ls | wc
使用execvp
.
char *const argv[] = {
"sh",
"-c", "ls | wc", // Command to execute.
NULL
};
execvp(argv[0], argv)
Run Code Online (Sandbox Code Playgroud)
你显然试过了
char *const argv[] = {
"sh",
"-c", "ls", // Command to execute.
"|", // Stored in called sh's $0.
"wc", // Stored in called sh's $1.
NULL
};
Run Code Online (Sandbox Code Playgroud)
这与bourne shell命令相同sh -c ls '|' wc
.
两者都与shell命令非常不同sh -c ls | wc
.那就是
char *const argv[] = {
"sh",
"-c", "sh -c ls | wc", // Command to execute.
NULL
};
Run Code Online (Sandbox Code Playgroud)
你似乎在思考|
并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.
Run Code Online (Sandbox Code Playgroud)
32512 = 0x7F00
所以它没有死于信号,没有产生核心转储,它退出代码127(0x7F).
什么127意味着不清楚,这就是为什么它应该伴随着错误信息.你试图执行程序ls | wc
,但没有这样的程序.