Comment exécuter un script shell à partir de C sous Linux?

Comment puis-je exécuter un script shell à partir de C sous Linux?

45
demandé sur Jan Deinhard 2010-09-17 18:29:13

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).

43
répondu nategoose 2017-07-20 15:34:05

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.

24
répondu Matthew Flaschen 2010-09-17 14:35:32

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;
}
15
répondu pmg 2015-05-12 14:11:57

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

3
répondu Ganesh 2016-12-23 07:00:00

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.

1
répondu doron 2010-09-17 14:42:57

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);
1
répondu GABIKA6 2015-05-12 11:00:21