Wie führe ich ein Shell-Skript von C in Linux aus?

Lesezeit: 5 Minuten

Wie kann ich ein Shell-Skript von C in Linux ausführen?

Benutzeravatar von nategoose
Nategans

Es hängt davon ab, was Sie mit dem Skript (oder einem anderen Programm, das Sie ausführen möchten) machen möchten.

Wenn Sie nur das Skript ausführen möchten system ist am einfachsten, aber es macht auch einige andere Dinge, einschließlich das Ausführen einer Shell und das Ausführen des Befehls (/bin/sh unter den meisten * nix).

Wenn Sie das Shell-Skript entweder über seine Standardeingabe füttern oder seine Standardausgabe verwenden möchten, können Sie verwenden popen (und pclose), um eine Pipe einzurichten. Dies verwendet auch die Shell (/bin/sh unter den meisten *nix), um den Befehl auszuführen.

Beides sind Bibliotheksfunktionen, die unter der Haube viel leisten, aber wenn sie Ihren Anforderungen nicht entsprechen (oder Sie nur experimentieren und lernen möchten), können Sie auch Systemaufrufe direkt verwenden. Dadurch können Sie auch vermeiden, dass die Shell (/bin/sh) Ihren Befehl für Sie ausführt.

Die Systemaufrufe von Interesse sind fork, execveund waitpid. Möglicherweise möchten Sie einen der Bibliotheks-Wrapper verwenden execve (Typ man 3 exec für eine Liste von ihnen). Möglicherweise möchten Sie auch eine der anderen Wartefunktionen verwenden (man 2 wait hat sie alle). Zusätzlich könnten Sie an den Systemaufrufen interessiert sein clone und vfork die mit Gabel verwandt sind.

fork dupliziert das aktuelle Programm, wobei der einzige Hauptunterschied darin besteht, dass der neue Prozess 0 vom Aufruf von Fork zurückerhält. Der übergeordnete Prozess erhält die Prozess-ID des neuen Prozesses (oder einen Fehler) zurückgegeben.

execve ersetzt das aktuelle Programm durch ein neues Programm (unter Beibehaltung der gleichen Prozess-ID).

waitpid wird von einem übergeordneten Prozess verwendet, um auf die Beendigung eines bestimmten untergeordneten Prozesses zu warten.

Da die Fork- und Execve-Schritte getrennt sind, können Programme einige Einstellungen für den neuen Prozess vornehmen, bevor er erstellt wird (ohne sich selbst zu vermasseln). Dazu gehören das Ändern von Standardeingabe, -ausgabe und stderr in andere Dateien als der verwendete übergeordnete Prozess, das Ändern des Benutzers oder der Gruppe des Prozesses, das Schließen von Dateien, die das Kind nicht benötigt, das Ändern der Sitzung oder das Ändern der Umgebungsvariablen.

Das könnte Sie auch interessieren pipe und dup2 Systemaufrufe. pipe erstellt eine Pipe (mit sowohl einem Eingabe- als auch einem Ausgabedateideskriptor). dup2 dupliziert einen Dateideskriptor als einen spezifischen Dateideskriptor (dup ist ähnlich, dupliziert aber einen Dateideskriptor auf den niedrigsten verfügbaren Dateideskriptor).

  • Es ist auch erwähnenswert, dass fork() ziemlich billig ist, da der Speicher Copy-on-Write ist und nicht dupliziert wird, sobald das Programm sich verzweigt.

    – Cercerilla

    17. September 2010 um 15:33 Uhr

  • Ich bin ein großer Fan von Fork/Exec – damit können Sie umgebungsbasierte Unsicherheiten darüber vermeiden, was ausgeführt werden wird. Aber können Sie es direkt in Shell-Skripten verwenden? Wie Sie sagen, vermeiden Sie durch die Verwendung von exec, dass die Shell (/bin/sh) Ihren Befehl für Sie ausführt. müssen Sie daher nicht /bin/sh ausführen, um ein Shell-Skript auszuführen?

    – Tom Anderson

    17. September 2010 um 16:33 Uhr

  • @Tom Anderson: Wenn für das Shell-Skript Ausführungsberechtigungen für den effektiven Benutzer festgelegt sind und eine entsprechende Shabang-erste Zeile eine Datei auflistet, für die der effektive Benutzer auch die Berechtigung zum Ausführen hat und die auch selbst kein Skript ist, wird der Kernel aufrufen die Datei, die in der Shabang-Zeile mit der Skriptdatei aufgeführt ist. Wenn das Shabang des Drehbuchs wäre #!/bin/csh dann /bin/sh würde im Fork/Exec-Szenario nicht ausgeführt werden. Wenn es wäre #!/bin/sh dann wäre es im Fork/Exec-Szenario, aber mit der system Ausführung /bin/sh würde für dieses Skript zweimal ausgeführt werden.

    – Nategans

    17. September 2010 um 16:43 Uhr

Benutzeravatar von Matthew Flaschen
Matthäus Flaschen

Sie können verwenden system:

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

Dies wird während der Ausführung blockiert sh -cund geben Sie dann den Statuscode zurück.

  • … vorausgesetzt, es hat ein ausführbares Bit und eine Shebang-Zeile. Im Algemeinen, system("/bin/sh /usr/local/bin/foo.sh");. Ja, das ruft die Shell tatsächlich zweimal auf.

    – Roman Cheplyaka

    17. September 2010 um 15:07 Uhr


  • Hallo Matt. Das ist nützlich. Aber ich sehe, dass es blockiert. Wie mache ich es asynchron?

    – mdasari

    18. August 2018 um 22:27 Uhr

  • Selbst wenn das Skript ausführbar ist, sagt system(“script.sh”) “script.sh not found”, sogar mit absolutem Pfad. Es funktioniert nur mit system(“sh script.sh”)

    – R71

    24. Juni um 15:37 Uhr

Benutzeravatar von pmg
pmg

Wenn Sie mit POSIX einverstanden sind, können Sie auch verwenden 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;
}

Ein einfacher Weg ist…..

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

Danke sagen
Yoda @http://www.unix.com/programming/216190-putting-bash-script-c-program.html

Benutzeravatar von Doron
doron

Wenn Sie eine feinstufigere Steuerung benötigen, können Sie auch das verwenden fork pipe exec Route. Dadurch kann Ihre Anwendung die vom Shell-Skript ausgegebenen Daten abrufen.

Benutzeravatar von molnarg
molnarg

Ich bevorzuge fork + execlp für eine “feinere” Steuerung, wie Doron erwähnt hat. Beispielcode unten gezeigt.

Speichern Sie Ihren Befehl in einem char-Array-Parameter und Malloc-Speicherplatz für das Ergebnis.

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

1416030cookie-checkWie führe ich ein Shell-Skript von C in Linux aus?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy