2011-04-10 15 views
7

Quiero ejecutar un comando de shell en mi programa c. Pero el problema es que no quiero que mi programa espere hasta que se ejecute el comando. No es necesario leer el resultado del comando de shell (no devuelve datos de todos modos) Entonces, básicamente, ¿es posible?Ejecutando un comando de shell en un programa c

+1

Por cierto, no importa si desea ejecutar un comando de shell u otro ejecutable. Ya sea que use 'system()' o el enfoque 'fork()/exec()', todo lo que se requiere es un ejecutable. ¿Quizás quieras editar el título de tu pregunta en consecuencia? – Jens

Respuesta

5

fork() y system() es lo que necesita

+0

Junto con exec() o sus variantes, probablemente. – PhD

+1

'system' haría que el proceso hijo esperara el comando shell -' exec' reemplazaría el proceso secundario con el shell. – rlc

+0

@Ronald: no. Reemplaza el proceso secundario con otro proceso. No está claro desde el OP si quiere ejecutar otro programa o una línea de comando de shell, pero si es el último, entonces solo system() hará el truco. ejecutivo no involucra el shell. –

5

Claro, sólo fork y exec: utilizar fork para crear un nuevo proceso y, en el proceso hijo, utilice exec para iniciar el shell con el comando. execv toma los argumentos que normalmente le daría al shell.

Su código podría tener este aspecto:

pid_t child_pid = fork(); 
if (child_pid == 0) 
{ // in child 
    /* set up arguments */ 
    // launch here 
    execv("/bin/sh", args); 
    // if you ever get here, there's been an error - handle it 
} 
else if (child_pid < 0) 
{ // handle error 
} 

el proceso hijo enviará una señal SIGCHLD cuando muere. Este código citado del estándar POSIX (SUSv4) se encargará de que:

static void 
handle_sigchld(int signum, siginfo_t *sinfo, void *unused) 
{ 
    int status; 

    /* 
    * Obtain status information for the child which 
    * caused the SIGCHLD signal and write its exit code 
    * to stdout. 
    */ 
    if (sinfo->si_code != CLD_EXITED) 
    { 
     static char msg[] = "wrong si_code\n"; 
     write(2, msg, sizeof msg - 1); 
    } 
    else if (waitpid(sinfo->si_pid, &status, 0) == -1) 
    { 
     static char msg[] = "waitpid() failed\n"; 
     write(2, msg, sizeof msg - 1); 
    } 
    else if (!WIFEXITED(status)) 
    { 
     static char msg[] = "WIFEXITED was false\n"; 
     write(2, msg, sizeof msg - 1); 
    } 
    else 
    { 
     int code = WEXITSTATUS(status); 
     char buf[2]; 
     buf[0] = '0' + code; 
     buf[1] = '\n'; 
     write(1, buf, 2); 
    } 
} 
+0

exec no implica el shell. supongamos que el OP quiere ejecutar 'ls | grep -v hola'. Esto funcionará con el sistema, pero no funcionará con el ejecutivo. –

+0

el OP puede pasarlos al shell - el sistema hace lo mismo (pero hace otro 'fork' y' exec' detrás de las escenas). – rlc

1

código try así:

#include <stdlib.h> 
#include <unistd.h> 
int main(int argc, char ** argv) 
{ 
    if (!fork()) 
    { 
     execv("ls", {"myDir"}); /* Your command with arguments instead of ls. */ 
    } 
} 
+2

Esto me parece demasiado rápido y sucio ya que esto crearía un proceso zombie desde el momento en que el comando sale hasta las salidas principales. Un programa Unix con buen comportamiento querría evitar eso. Ver otras respuestas que usan 'waitpid'. – Jens

+0

Lo siento. No soy tan bueno con las * nix APIs :). – JackMc

1

¿Qué pasa simplemente amplificar el comando con system ("command &")?

Cuestiones relacionadas