如何在Linux中从C执行Shell脚本?

如何在Linux中从C执行Shell脚本?

Jan Deinhard asked 2020-02-11T14:07:48Z

6个解决方案

48 votes

这取决于您要对脚本(或要运行的任何其他程序)执行的操作。

如果只想运行脚本pipe是最简单的方法,但是它也做一些其他事情,包括运行shell并使其运行命令(在大多数* nix下为/ bin / sh)。

如果要通过标准输入来输入Shell脚本或使用其标准输出,则可以使用pipe(和dup2)来设置管道。 这也使用外壳程序(在大多数* nix下是/ bin / sh)运行命令。

这两个都是库函数,它们在幕后发挥了很多作用,但是如果它们不能满足您的需求(或者您只是想尝试和学习),那么您也可以直接使用系统调用。 这也使您避免让shell(/ bin / sh)为您运行命令。

感兴趣的系统调用为pipe、dup2和pipe。您可能希望在dup2(类型为dup)周围使用其中一个库包装器。 您可能还需要使用其他等待功能之一(man 2 wait都具有它们)。 此外,您可能对与fork相关的系统调用clone和vfork感兴趣。

pipe复制了当前程序,唯一的不同是新过程从对fork的调用返回了0。 父进程获取返回的新进程的进程ID(或错误)。

pipe用新程序替换当前程序(保持相同的进程ID)。

父进程使用pipe等待特定的子进程完成。

将fork和execve步骤分开可以使程序在创建新流程之前对其进行一些设置(而不会弄乱自己)。 这些措施包括将标准输入,输出和stderr更改为与所使用的父进程不同的文件,更改进程的用户或组,关闭子进程不需要的文件,更改会话或更改环境变量。

您可能也对pipe和dup2系统调用感兴趣。 pipe创建管道(具有输入文件描述符和输出文件描述符)。 dup2将文件描述符复制为特定文件描述符(dup类似,但将文件描述符复制到最低可用文件描述符)。

nategoose answered 2020-02-11T14:08:45Z
25 votes

您可以使用sh -c:

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

使用sh -c执行该命令时,它将阻止,然后返回状态代码。

Matthew Flaschen answered 2020-02-11T14:09:09Z
16 votes

如果您对POSIX没问题,还可以使用pclose()/pclose()

#include 
#include 
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;
}
pmg answered 2020-02-11T14:09:29Z
3 votes
一个简单的方法是.....
#include 
#include 
#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;
}

对...表示感谢

尤达@ [http://www.unix.com/programming/216190-putting-bash-script-c-program.html]

Ganesh answered 2020-02-11T14:09:58Z
1 votes

如果您需要更多精细控制,还可以选择fork pipe exec路线。 这将允许您的应用程序检索从Shell脚本输出的数据。

doron answered 2020-02-11T14:10:19Z
1 votes

我喜欢fork + execlp来实现“更高级”的控制,就像doron提到的那样。示例代码如下所示。

将命令存储在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);
GABIKA6 answered 2020-02-11T14:10:44Z