Подтвердить что ты не робот

Как выполнить оболочку script из C в Linux?

Как я могу выполнить оболочку script из C в Linux?

4b9b3361

Ответ 1

Это зависит от того, что вы хотите сделать с помощью script (или любой другой программы, которую вы хотите запустить).

Если вы просто хотите запустить script system, это самая простая вещь, но она также делает некоторые другие вещи, включая запуск оболочки и выполнение команды (/bin/sh в большинстве * nix).

Если вы хотите либо передать оболочку script через стандартный ввод, либо использовать стандартный вывод, вы можете использовать popenpclose) для настройки канала. Для выполнения этой команды также используется оболочка (/bin/sh при большинстве * nix).

Обе из них - это функции библиотеки, которые многое делают под капотом, но если они не соответствуют вашим потребностям (или вы просто хотите поэкспериментировать и учиться), вы также можете напрямую использовать системные вызовы. Это также позволяет избежать использования командной оболочки (/bin/sh) для вас.

Интересующие системы представляют собой fork, execve и waitpid. Вы можете использовать одну из оберток библиотеки вокруг execve (введите man 3 exec для их списка). Вы также можете использовать одну из других функций ожидания (man 2 wait имеет их все). Кроме того, вас могут заинтересовать системные вызовы clone и vfork, связанные с fork.

fork дублирует текущую программу, где единственным главным отличием является то, что новый процесс получает 0, возвращенный из вызова в fork. Родительский процесс возвращает новый идентификатор процесса (или ошибку).

execve заменяет текущую программу новой программой (сохраняя один и тот же идентификатор процесса).

waitpid используется родительским процессом для ожидания завершения определенного дочернего процесса.

С помощью разметки fork и execve отдельные программы позволяют выполнять некоторую настройку для нового процесса до его создания (без испорчения). Они включают в себя изменение стандартного ввода, вывода и stderr для разных файлов, чем используемый родительский процесс, изменение пользователя или группы процесса, закрытие файлов, которые не нужны ребенку, изменение сеанса или изменение переменных окружения.

Вы также можете быть заинтересованы в системных вызовах pipe и dup2. pipe создает канал (как с входным, так и с дескриптором выходного файла). dup2 дублирует файловый дескриптор как специфический дескриптор файла (dup аналогичен, но дублирует файловый дескриптор для самого доступного дескриптора файла).

Ответ 2

Вы можете использовать system:

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

Это будет блокироваться во время выполнения с помощью sh -c, а затем вернуть код состояния.

Ответ 3

Если вы в порядке с POSIX, вы также можете использовать 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;
}

Ответ 4

Простым способом является.....

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

Скажите спасибо Yoda @http://www.unix.com/programming/216190-putting-bash-script-c-program.html

Ответ 5

Если вам нужен более тонкий контроль, вы также можете пройти маршрут fork pipe exec. Это позволит вашему приложению получать данные, выводимые из оболочки script.

Ответ 6

Я предпочитаю fork + execlp для "более тонкого" управления, как упоминалось дором. Пример кода, показанного ниже.

Сохраните команду в параметрах массива char и пространстве malloc для результата.

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