la ejecución de un script php de programa en C y almacenar los resultados en una variable

StackOverflow https://stackoverflow.com/questions/1047385

  •  20-08-2019
  •  | 
  •  

Pregunta

Me gustaría ejecutar un script PHP desde un programa en C y almacenar el regreso de contenido en una variable C.

He intentado como siguiente pero no funciona:

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";
?>

Medio ambiente:

  • PHP 5.2.6
  • Apache 2.0
  • Fedora Core 10

También sugieren cualquier otra manera mejor de hacerlo.

¿Fue útil?

Solución

Respuesta corta aquí es el uso de system() o popen() en lugar de execl().Ver como Jason ya ha publicado una buena respuesta sobre el uso de popen(), Voy a saltar y se explica cómo utilizar execl() en caso de que realmente importa.Probablemente, esto es todos los técnicos innecesarios mumbo jumbo-pero maldita sea, yo tenía la mayoría de este escrito ya como un largo preludio antes de hablar popen() y yo no soy de tirar a la basura ahora!

En primer lugar...

Cuando se llama a execl() todos los argumentos de línea de comandos deben ser pasadas por separado.También, el primer argumento debe ser repetida argv[0] en cualquier programa main() tradicionalmente es el nombre del programa.Así que la llamada fija debe verse así:

execl("/usr/bin/php", "/usr/bin/php", "-q",
    "/var/www/html/phpinfo.php", (char *) NULL);

(He añadido el yeso (char *) para asegurarse de que un puntero nulo se pasa como argumento final, más que el entero 0, si NULL pasa a ser definido como 0 y no (void *) 0, que es legal.)

Sin embargo...

Esto hace que el execl() llame a la derecha, pero hay un problema más grande.El exec la familia de funciones que se utilizan casi siempre en combinación con fork() y algunos complicado pipe() los juegos malabares.Esto es debido a que el exec las funciones no se ejecutan el programa en un proceso independiente;en realidad reemplazar el actual proceso!Así que una vez que usted llame execl(), el código está hecho.Terminado. execl() nunca se devuelve.Si usted acaba de llamar como lo he hecho nunca vas a llegar a ver lo que sucede cuando su programa por arte de magia se transforman en un /usr/bin/php proceso.

OK, entonces, ¿qué es esto de fork() y pipe()?En un nivel alto, lo que tienes que hacer es dividir el proceso en dos procesos.El proceso primario seguirá siendo "su" proceso, mientras que el proceso hijo se llame de inmediato execl() y se transforme en /usr/bin/php.A continuación, si ha conectado el padre y el hijo procesos juntos correctamente van a ser capaces de comunicarse unos con otros.

Para hacer corta una larga historia, si todavía estás aquí y no he asintió con la cabeza fuera usted debe consultar a los sabios de oracle en Google de manera más detalles acerca de todo esto.Hay un montón de sitios web por ahí dando aún más (!) detalles en profundidad acerca de cómo hacer el fork/exec de la danza.

Yo no te dejan colgado, aunque.Aquí es una función que uso para mi propio programa que hace exactamente lo que yo he descrito.Es muy similar a la popen() de hecho, la única diferencia es que la persona que llama puede acceder a el niño stderr además de la secuencia de stdin y stdout.

Código de...

#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;
    }
}

Otros consejos

Probablemente, la forma más fácil sería utilizar la función popen : (extracto de la página vinculada):

  

El siguiente ejemplo demuestra el uso de popen () y pclose () para ejecutar el comando ls * para obtener una lista de archivos en el directorio actual:

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

Sin embargo, querer leer la salida de un script PHP desde un programa en C es una especie de bandera roja, y sospecho que probablemente haya una solución general más limpia para esto, pero es difícil decir más sin una descripción de nivel superior de lo que intentas hacer.

Recuerde que cuando use execl(), " saldrá en caso de éxito " ;. Por lo tanto, nunca verá & Quot; End php function & Quot; porque nunca llegará a esa línea de código.

Para superar este problema, puede usar system o fork() para crear un proceso hijo y en su proceso hijo usar execl o cualquier otra función de la familia exec.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top