代码之家  ›  专栏  ›  技术社区  ›  Jan Deinhard

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

  •  47
  • Jan Deinhard  · 技术社区  · 16 年前

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

    6 回复  |  直到 16 年前
        1
  •  45
  •   hbagdi    9 年前

    这取决于您想对脚本(或任何其他要运行的程序)做什么。

    如果你只想运行脚本 system 这是最容易做的事情,但它也做了一些其他的事情,包括运行shell和让它运行命令(/bin/sh under most*nix)。

    如果您想通过shell脚本的标准输入来提供它,或者使用它的标准输出,您可以使用 popen (和) pclose )安装管道。这还使用shell(/bin/sh在most*nix下)来运行该命令。

    这两种功能都是库功能,在底层做了很多工作,但是如果它们不满足您的需求(或者您只是想试验和学习),您也可以直接使用系统调用。这也允许您避免让shell(/bin/sh)为您运行命令。

    系统调用感兴趣的是 fork , execve 和 waitpid . 你可能想用图书馆的包装纸 系统调用 (类型) man 3 exec 以获取它们的列表)。您还可以使用其他等待函数之一( man 2 wait 全部都有)。此外,您可能对系统调用感兴趣 clone 和 vfork 与叉子有关。

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

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

    子进程 父进程用于等待特定子进程完成。

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

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

        2
  •  25
  •   Matthew Flaschen    16 年前

    你可以用 system :

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

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

        3
  •  16
  •   pmg    11 年前

    如果您对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
  •  3
  •   Ganesh    9 年前

    一个简单的方法是……

    #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

        5
  •  1
  •   doron    16 年前

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

        6
  •  1
  •   GABIKA6    11 年前

    正如多伦提到的,我更喜欢用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);