我有下面的辅助函数,用于在 posix 系统上执行命令并获取返回值。我曾经使用,但如果应用程序在/有机会完成其工作之前运行并退出,popen
则无法获取应用程序的返回码。popen
popen
pclose
下面的辅助函数创建一个进程分支,用于execvp
运行所需的外部进程,然后父进程waitpid
用于获取返回码。我看到它拒绝运行的奇怪情况。
wait
当使用=调用时true
,waitpid
无论如何都应该返回应用程序的退出代码。但是,我看到stdout
指定返回码不为零的输出,但返回码为零。在常规 shell 中测试外部进程,然后echo
ing$?
返回非零,因此外部进程没有返回正确的代码不是问题。如果有任何帮助,正在运行的外部进程是mount(8)
(是的,我知道我可以使用mount(2)
,但除此之外)。
我提前为代码转储道歉。其中大部分是调试/记录:
inline int ForkAndRun(const std::string &command, const std::vector<std::string> &args, bool wait = false, std::string *output = NULL)
{
std::string debug;
std::vector<char*> argv;
for(size_t i = 0; i < args.size(); ++i)
{
argv.push_back(const_cast<char*>(args[i].c_str()));
debug += "\"";
debug += args[i];
debug += "\" ";
}
argv.push_back((char*)NULL);
neosmart::logger.Debug("Executing %s", debug.c_str());
int pipefd[2];
if (pipe(pipefd) != 0)
{
neosmart::logger.Error("Failed to create pipe descriptor when trying to launch %s", debug.c_str());
return EXIT_FAILURE;
}
pid_t pid = fork();
if (pid == 0)
{
close(pipefd[STDIN_FILENO]); //child isn't going to be reading
dup2(pipefd[STDOUT_FILENO], STDOUT_FILENO);
close(pipefd[STDOUT_FILENO]); //now that it's been dup2'd
dup2(pipefd[STDOUT_FILENO], STDERR_FILENO);
if (execvp(command.c_str(), &argv[0]) != 0)
{
exit(EXIT_FAILURE);
}
return 0;
}
else if (pid < 0)
{
neosmart::logger.Error("Failed to fork when trying to launch %s", debug.c_str());
return EXIT_FAILURE;
}
else
{
close(pipefd[STDOUT_FILENO]);
int exitCode = 0;
if (wait)
{
waitpid(pid, &exitCode, wait ? __WALL : (WNOHANG | WUNTRACED));
std::string result;
char buffer[128];
ssize_t bytesRead;
while ((bytesRead = read(pipefd[STDIN_FILENO], buffer, sizeof(buffer)-1)) != 0)
{
buffer[bytesRead] = '\0';
result += buffer;
}
if (wait)
{
if ((WIFEXITED(exitCode)) == 0)
{
neosmart::logger.Error("Failed to run command %s", debug.c_str());
neosmart::logger.Info("Output:\n%s", result.c_str());
}
else
{
neosmart::logger.Debug("Output:\n%s", result.c_str());
exitCode = WEXITSTATUS(exitCode);
if (exitCode != 0)
{
neosmart::logger.Info("Return code %d", (exitCode));
}
}
}
if (output)
{
result.swap(*output);
}
}
close(pipefd[STDIN_FILENO]);
return exitCode;
}
}
请注意,该命令使用正确的参数运行正常,该函数继续运行,没有任何问题,并WIFEXITED
返回TRUE
. 但是,WEXITSTATUS
当它应该返回其他东西时,返回 0。