2010-09-17 6 views

Répondre

38

Cela dépend de ce que vous voulez faire avec le script (ou tout autre programme que vous voulez exécuter). Si vous voulez juste exécuter le script, c'est la chose la plus facile à faire, mais il y a aussi d'autres choses, y compris l'exécution d'un shell et l'exécution de la commande (/ bin/sh sous la plupart des * nix).

Si vous souhaitez alimenter le script shell via son entrée standard ou utiliser sa sortie standard, vous pouvez utiliser popen (et pclose) pour configurer un canal. Cela utilise également le shell (/ bin/sh sous la plupart des * nix) pour exécuter la commande.

Les deux sont des fonctions de bibliothèque qui font beaucoup sous le capot, mais si elles ne répondent pas à vos besoins (ou si vous voulez juste expérimenter et apprendre), vous pouvez également utiliser les appels système directement. Cela vous permet également d'éviter que le shell (/ bin/sh) exécute votre commande pour vous. Les appels système d'intérêt sont fork, execve et waitpid. Vous souhaiterez peut-être utiliser l'un des wrappers de bibliothèque autour de execve (tapez man 3 exec pour une liste d'entre eux). Vous pouvez également utiliser l'une des autres fonctions d'attente (man 2 wait les a tous). En outre, vous pouvez être intéressé par les appels système clone et vfork qui sont liés à la fourche.

fork duplique le programme en cours, où la seule différence principale est que le nouveau processus obtient 0 renvoyé de l'appel à fork. Le processus parent récupère l'ID de processus du nouveau processus (ou une erreur). Remplace le programme en cours par un nouveau programme (en conservant le même identifiant de processus)

execve

waitpid est utilisé par un processus parent pour attendre la fin d'un processus enfant particulier. Si les étapes fork et execve se séparent, les programmes peuvent effectuer une configuration pour le nouveau processus avant sa création (sans se tromper). Cela inclut la modification de l'entrée standard, de la sortie et de stderr pour être des fichiers différents du processus parent utilisé, changer l'utilisateur ou le groupe du processus, fermer les fichiers dont l'enfant n'aura pas besoin, changer la session ou changer les variables environnementales.

Vous pouvez également être intéressé par les appels système pipe et dup2. pipe crée un canal (avec à la fois un descripteur de fichier d'entrée et un fichier de sortie).dup2 duplique un descripteur de fichier en tant que descripteur de fichier spécifique (dup est similaire mais duplique un descripteur de fichier au plus petit descripteur de fichier disponible).

+2

Il est également intéressant de noter que fork() est assez bon marché car la mémoire est en copie-sur-écriture et n'est pas dupliquée dès que le programme se fige. – Cercerilla

+0

Je suis un grand fan de fork/exec - il vous permet d'éviter l'incertitude liée à l'environnement sur ce qui va fonctionner. Mais pouvez-vous l'utiliser directement sur des scripts shell? Comme vous le dites, en utilisant exec, vous "évitez que le shell (/ bin/sh) exécute votre commande pour vous"; n'avez-vous pas besoin de exec/bin/sh pour lancer un script shell? –

+1

@Tom Anderson: Si le script shell a des permissions d'exécution définies pour l'utilisateur effectif et a une première ligne shabang appropriée listant un fichier que l'utilisateur effectif a aussi l'autorisation d'exécuter et n'est pas lui-même un script, le noyau appelez le fichier listé sur la ligne shabang avec le fichier de script. Si le shabang du script était '#!/Bin/csh' alors'/bin/sh' ne serait pas exécuté dans le scénario fork/exec. Si c'était # #/bin/sh' alors cela serait dans le scénario fork/exec, mais avec la version 'system''/bin/sh' serait exécuté deux fois pour ce script. – nategoose

23

Vous pouvez utiliser system:

system("/usr/local/bin/foo.sh"); 

Cela bloque lors de l'exécution à l'aide sh -c, puis retourner le code d'état.

+3

+1 Ne pas oublier d'inclure '' (http: // linux.die.net/man/3/system) – pmg

+1

... en supposant qu'il a un bit exécutable et une ligne shebang. En général, 'system ("/bin/sh /usr/local/bin/foo.sh ");'. Oui, cela appelle deux fois le shell. –

1

Si vous avez besoin d'un contrôle plus précis, vous pouvez également utiliser la route forkpipeexec. Cela permettra à votre application de récupérer les données issues du script shell.

15

Si vous êtes ok avec POSIX, vous pouvez également utiliser popen()/pclose()

#include <stdio.h> 
#include <stdlib.h> 

int main(void) { 
/* ls -al | grep '^d' */ 
    FILE *pp; 
    pp = popen("ls -al", "r"); 
    if (pp != NULL) { 
    while (1) { 
     char *line; 
     char buf[1000]; 
     line = fgets(buf, sizeof buf, pp); 
     if (line == NULL) break; 
     if (line[0] == 'd') printf("%s", line); /* line includes '\n' */ 
    } 
    pclose(pp); 
    } 
    return 0; 
} 
+0

Merci pour cet exemple. –

1

Je préfère fork + execlp pour un contrôle "plus fin" comme le mentionne doron. Exemple de code ci-dessous.

Stockez la commande dans un tableau de paramètres char et espace malloc pour le résultat.

int fd[2]; 
pipe(fd); 
if ((childpid = fork()) == -1){ 
    fprintf(stderr, "FORK failed"); 
    return 1; 
} else if(childpid == 0) { 
    close(1); 
    dup2(fd[1], 1); 
    close(fd[0]); 
    execlp("/bin/sh","/bin/sh","-c",parameters,NULL); 
} 
wait(NULL); 
read(fd[0], result, RESULT_SIZE); 
printf("%s\n",result); 
+0

'close (1);' n'est pas nécessaire car dup2() ferme le fichier newfd par lui-même avant de le réaffecter. – FedericoCapaldo

2

Une façon simple .....

#include <stdio.h> 
#include <stdlib.h> 


#define SHELLSCRIPT "\ 
#/bin/bash \n\ 
echo \"hello\" \n\ 
echo \"how are you\" \n\ 
echo \"today\" \n\ 
" 
/*Also you can write using char array without using MACRO*/ 
/*You can do split it with many strings finally concatenate 
    and send to the system(concatenated_string); */ 

int main() 
{ 
    puts("Will execute sh with the following script :"); 
    puts(SHELLSCRIPT); 
    puts("Starting now:"); 
    system(SHELLSCRIPT); //it will run the script inside the c code. 
    return 0; 
} 

Dites merci à
Yoda @http://www.unix.com/programming/216190-putting-bash-script-c-program.html

Questions connexes