题
我谨执行PHP script从C程序和储存返回的内容在至C的变量。
我试图像下面,但它不工作:
C:
printf("calling php function\n");
execl("/usr/bin/php -q", "/var/www/html/phpinfo.php", NULL);
printf("End php function\n");
PHP:
<?php
echo "hello";
?>
环境:
- PHP5.2.6
- Apache2.0
- Fedora核心10
还建议任何其他更好的方式来做到这一点。
解决方案
简短地回答这里是使用 system()
或 popen()
而不是 execl()
.看到杰森已经发布的一个很好的答案约使用 popen()
, 我会跳过,并解释如何使用 execl()
只是在你实际上的照顾。最有可能的,这都是不必要的技术胡言乱语-但是,妈,我大多数这种类型的出已经作为一个长期的前奏在讨论 popen()
我不把它扔掉吧!
首先...
打电话时 execl()
所有的命令行参数需要被过分开。此外,第一个参数必须重复 argv[0]
在任何计划的 main()
是在传统名称的程序。所以,固定电话应该是这样的:
execl("/usr/bin/php", "/usr/bin/php", "-q",
"/var/www/html/phpinfo.php", (char *) NULL);
(I增加铸到 (char *)
确保一个空的指针是通过作为最后的参数,而不是整数0,如果 NULL
发生在被定义为 0
而不 (void *) 0
, ,这是合法的。)
但是...
这得到的 execl()
呼叫的权利,但有一个更大的问题。的 exec
家庭的职能几乎总是结合使用 fork()
和一些复杂的 pipe()
玩杂耍的.这是因为 exec
功能不会运行的程序在一个独立的进程;他们实际上取代目前的进程的!所以一旦你打电话 execl()
, ,你的代码。完成。 execl()
永远不会返回。如果你只是叫它喜欢你做了你永远也不会来看看会发生什么作为你的节目将会奇迹般地变成一个 /usr/bin/php
过程。
好了,这是什么 fork()
和 pipe()
?在较高的水平,你有什么要做的是分割你的过程分成两个进程。父进程将继续是"你的"过程,而孩子的进程将立即呼叫 execl()
并把自己变成 /usr/bin/php
.然后如果你有线的父母和子进程在一起正确的,他们将能够相互沟通。
长话短说,如果你还在这里并没有点头你应该咨询明智的oracle谷歌的方式有关的更多详细信息,所有这一切。有很多的网站在那里给予甚至更多(!) 在深入详细信息关于如何做到的 fork
/exec
舞蹈。
我不会离开你挂虽然。这里有一个功能我用我自己的程序,不正是我已经概述。这是非常相似 popen()
事实上,唯一的区别是,该呼叫者可以访问的孩子的 stderr
流除了 stdin
和 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;
}
}
其他提示
可能是最简单的方法就是使用 popen功能:(摘自联页):
下面的示例说明了使用的popen()和pclose()执行命令ls*为了获得的文件的列表在当前的目录:
#include <stdio.h>
...
FILE *fp;
int status;
char path[PATH_MAX];
fp = popen("ls *", "r");
if (fp == NULL)
/* Handle error */;
while (fgets(path, PATH_MAX, fp) != NULL)
printf("%s", path);
status = pclose(fp);
if (status == -1) {
/* Error reported by pclose() */
...
} else {
/* Use macros described under wait() to inspect `status' in order
to determine success/failure of command executed by popen() */
...
}
然而,想读输出PHP script从C节目是一种红色的标志,和我怀疑有可能是一些更清洁的整体解决方案,但很难说得更加没有一个高级别说明你想要什么做的。
记得当你使用 execl()
它将"出口成功"。所以,你永远不会看见"结束php功能",因为它将永远不会得到这一行代码。
为了克服这个问题,你可以使用 system
或者使用 fork()
创建一个儿童的进程和你的孩子过程中的使用 execl
或任何其他的功能 exec
家庭。