Comment exécuter un script shell à partir de C sous Linux?
Comment puis-je exécuter un script shell à partir de C sous Linux?
6 réponses
, Il dépend de ce que vous voulez faire avec le script (ou tout autre programme que vous souhaitez exécuter).
Si vous voulez simplement exécuter le script system
est la chose la plus facile à faire, mais il fait aussi d'autres choses, y compris l'exécution d'un shell et l'exécution de la commande (/bin/sh sous most *nix).
Si vous voulez alimenter le script shell via son entrée standard ou consommer sa sortie standard, vous pouvez utiliser popen
(et pclose
) pour configurer un tuyau. Cela utilise également le shell (/bin / sh sous most * 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.
, Le système des appels d'intérêts sont fork
, execve
, et waitpid
. Vous pouvez utiliser l'un des wrappers de bibliothèque autour de execve
(Tapez man 3 exec
pour une liste d'entre eux). Vous peut également vouloir utiliser l'une des autres fonctions d'attente (man 2 wait
les a toutes). De plus, vous pouvez être intéressé par les appels système clone
et vfork
qui sont liés à fork.
fork
duplique le programme actuel, où la seule différence principale est que le nouveau processus obtient 0 retourné de l'appel à fork. Le processus parent obtient l'id de processus du nouveau processus (ou une erreur) retourné.
execve
remplace le programme actuel avec un nouveau programme (en gardant le même processus ID).
waitpid
est utilisé par un processus parent pour attendre la fin d'un processus enfant particulier.
La séparation des étapes fork et execve permet aux programmes de configurer le nouveau processus avant sa création (sans se gâcher). Ceux-ci incluent la modification de l'entrée standard, de la sortie et de stderr pour qu'ils soient différents des fichiers du processus parent utilisé, la modification de l'utilisateur ou du groupe du processus, la fermeture des fichiers dont l'enfant n'aura pas besoin, la modification de la session ou la modification du variables environnementales.
Vous pouvez également être intéressé par les appels système pipe
et dup2
. pipe
crée un tuyau (avec un descripteur de fichier d'entrée et 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 descripteur de fichier le plus bas disponible).
Vous pouvez utiliser system
:
system("/usr/local/bin/foo.sh");
Cela bloquera pendant l'exécution en utilisant sh -c
, puis retournera le code d'état.
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;
}
Un moyen simple est.....
#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
Si vous avez besoin de plus haute qualité de contrôle, vous pouvez aussi aller au fork
pipe
exec
l'itinéraire. Cela permettra à votre application de récupérer les données sorties à partir du script shell.
Je préfère fork + execlp pour le contrôle "plus fin" comme doron l'a mentionné. Exemple de code ci-dessous.
Stockez votre commande dans un tableau de paramètres char et un 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);