문제

C 프로그램에서 PHP 스크립트를 실행하고 리턴 컨텐츠를 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";
?>

환경:

  • PHP 5.2.6
  • 아파치 2.0
  • 페도라 코어 10

또한 더 나은 방법을 제안하십시오.

도움이 되었습니까?

해결책

여기서 짧은 대답은 사용하는 것입니다 system() 또는 popen() 보다는 execl(). Jason이 이미 사용에 대한 좋은 답변을 게시 한 것처럼 popen(), 나는 그것을 건너 뛰고 사용 방법을 설명 할 것입니다 execl() 당신이 실제로 관심을 갖는 경우를 대비하여. 아마도 이것은 모든 불필요한 기술적 인 Mumbo Jumbo 일 가능성이 높습니다. 그러나 DAMMIT, 나는 이것의 대부분이 이미 논의하기 전에 긴 전주곡으로 이미 타이핑을했습니다. 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. 그런 다음 부모와 자식 과정을 올바르게 연결하면 서로 의사 소통 할 수 있습니다.

긴 이야기를 짧게 만들기 위해, 아직 여기에 있고 고개를 끄덕이지 않았다면 현명한 Oracle Google과 상담 하여이 모든 것에 대한 자세한 내용을 설명해야합니다. 거기에 더 많은 웹 사이트가 있습니다. 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 기능: (링크 된 페이지에서 발췌) :

다음 예제는 현재 디렉토리에서 파일 목록을 얻기 위해 ls *를 실행하기 위해 Popen () 및 pclose ()를 사용하는 것을 보여줍니다.

#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() */
    ...
}

그러나 C 프로그램 내에서 PHP 스크립트의 출력을 읽고 싶어하는 것은 일종의 붉은 깃발이며, 아마도 이것에 대한 더 깨끗한 솔루션이있을 것 같지만, 당신이 무엇에 대한 더 높은 수준의 설명없이 더 많은 것을 말하기는 어렵습니다. ' 다시 시도합니다.

당신이 사용할 때를 기억하십시오 execl() "성공을 종료"할 것입니다. 따라서 "END PHP 함수"는 해당 코드 라인에 도달하지 않기 때문에 결코 보지 못할 것입니다.

이 문제를 극복하기 위해 사용할 수 있습니다 system 또는 사용 fork() 아동 과정을 만들고 자녀 과정에서 execl 또는 다른 기능 exec 가족.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top