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

时间:2010-09-17 14:29:13

标签: c linux shell

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

6 个答案:

答案 0 :(得分:45)

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

如果你只是想运行脚本system是最简单的事情,但它也做了一些其他的事情,包括运行shell并让它运行命令(/ bin / sh大多数* nix) )。

如果您想通过其标准输入提供shell脚本或使用其标准输出,您可以使用popen(和pclose)来设置管道。这也使用shell(大多数* nix下的/ bin / sh)来运行命令。

这些都是图书馆功能,它们有很多功能,但如果它们不能满足您的需求(或者您只是想进行实验和学习),您也可以直接使用系统调用。这也允许你避免让shell(/ bin / sh)为你运行命令。

感兴趣的系统调用是forkexecvewaitpid。您可能希望在execve周围使用其中一个库包装器(类型man 3 exec)以获取它们的列表。您可能还想使用其他一个等待函数(man 2 wait将它们全部放在一起)。此外,您可能对与fork相关的系统调用clonevfork感兴趣。

fork复制当前程序,唯一的主要区别是新进程从fork调用返回0。父进程获取返回的新进程的进程ID(或错误)。

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

父进程使用

waitpid来等待特定子进程完成。

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

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

答案 1 :(得分:25)

您可以使用system

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

这将在使用sh -c执行时阻止,然后返回状态代码。

答案 2 :(得分:16)

如果您对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;
}

答案 3 :(得分:3)

一个简单的方法是......

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

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

答案 4 :(得分:1)

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

答案 5 :(得分:1)

我更喜欢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);