Как я могу выполнить оболочку script из C в Linux?
Как выполнить оболочку script из C в Linux?
Ответ 1
Это зависит от того, что вы хотите сделать с помощью script (или любой другой программы, которую вы хотите запустить).
Если вы просто хотите запустить script system
, это самая простая вещь, но она также делает некоторые другие вещи, включая запуск оболочки и выполнение команды (/bin/sh в большинстве * nix).
Если вы хотите либо передать оболочку script через стандартный ввод, либо использовать стандартный вывод, вы можете использовать popen
(и pclose
) для настройки канала. Для выполнения этой команды также используется оболочка (/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);