这里的简短回答是使用system()
orpopen()
而不是execl()
. 鉴于 Jason 已经发布了一个关于 using 的好答案popen()
,我将跳过它并解释如何使用execl()
,以防万一你真的关心。最有可能的是,这都是不必要的技术胡说八道——但该死的,在讨论之前,我已经把大部分内容作为长长的前奏打出来了popen()
,我现在不会把它扔掉!
首先...
调用execl()
时需要单独传递所有命令行参数。此外,第一个参数必须重复,因为argv[0]
在任何程序main()
中传统上都是程序的名称。所以固定调用应该是这样的:
execl("/usr/bin/php", "/usr/bin/php", "-q",
"/var/www/html/phpinfo.php", (char *) NULL);
(我添加了强制转换(char *)
以确保将空指针作为最终参数而不是整数 0 传递,如果NULL
恰好定义为0
而不是(void *) 0
,这是合法的。)
然而...
这让execl()
电话正确,但还有一个更大的问题。exec
函数族几乎总是fork()
与一些复杂的pipe()
杂耍结合使用。这是因为exec
函数不会在单独的进程中运行程序;他们实际上取代了当前的过程!所以一旦你打电话execl()
,你的代码就完成了。完成的。execl()
永远不会回来。如果你只是像以前那样调用它,你将永远看不到会发生什么,因为你的程序会神奇地转变为一个/usr/bin/php
进程。
好的,那么这是关于什么fork()
的pipe()
?在高层次上,您要做的就是将您的流程分成两个流程。父进程将继续是“你的”进程,而子进程将立即调用execl()
并将自己转换为/usr/bin/php
. 然后,如果您将父进程和子进程正确连接在一起,它们将能够相互通信。
长话短说,如果您还在这里并且还没有打瞌睡,您应该咨询明智的神谕 Google 以获取有关所有这一切的更多详细信息。有很多网站提供了更多(!)关于如何做fork
/exec
舞蹈的深入细节。
我不会让你挂着。这是我用于我自己的程序的一个函数,它完全符合我的概述。它与事实上非常相似popen()
,唯一的区别是调用者stderr
除了stdin
and之外还可以访问子流stdout
。
代码...
#include <errno.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
pid_t execute(const char *command, FILE **in, FILE **out, FILE **err)
{
pid_t pid;
int fd[6];
pipe(&fd[0]);
pipe(&fd[2]);
pipe(&fd[4]);
switch (pid = fork()) {
case -1:
perror("unable to fork()");
exit(1);
case 0:
close(fd[1]); // Close write end of stdin.
close(fd[2]); // Close read end of stdout.
close(fd[4]); // Close read end of stderr.
dup2(fd[0], STDIN_FILENO); // Have stdin read from the first pipe.
dup2(fd[3], STDOUT_FILENO); // Have stdout write to the second pipe.
dup2(fd[5], STDERR_FILENO); // Have stderr write to the third pipe.
execlp("/bin/sh", "/bin/sh", "-c", command, (char *) NULL);
perror("execlp() failed");
_exit(1);
default:
close(fd[0]); // Close read end of stdin.
close(fd[3]); // Close write end of stdout.
close(fd[5]); // Close write end of stderr.
if (in) *in = fdopen(fd[1], "wb"); else close(fd[1]);
if (out) *out = fdopen(fd[2], "rb"); else close(fd[2]);
if (err) *err = fdopen(fd[4], "rb"); else close(fd[4]);
return pid;
}
}