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

如何在Linux中从C执行shell脚本?,c,linux,shell,C,Linux,Shell,如何在Linux中从C执行shell脚本?您可以使用系统: system("/usr/local/bin/foo.sh"); 这将在使用sh-c执行时阻塞,然后返回状态代码。如果需要更精细的坡度控制,也可以使用分叉管道执行路线。这将允许您的应用程序检索从shell脚本输出的数据。如果您对POSIX没有问题,也可以使用/ #包括 #包括 内部主(空){ /*ls-al|grep'^d'*/ 文件*pp; pp=popen(“ls-al”、“r”); 如果(pp!=NULL){ 而(1){ 字符*

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

您可以使用
系统

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

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

如果需要更精细的坡度控制,也可以使用
分叉
管道
执行
路线。这将允许您的应用程序检索从shell脚本输出的数据。

如果您对POSIX没有问题,也可以使用/

#包括
#包括
内部主(空){
/*ls-al|grep'^d'*/
文件*pp;
pp=popen(“ls-al”、“r”);
如果(pp!=NULL){
而(1){
字符*行;
char-buf[1000];
直线=fgets(buf,尺寸buf,pp);
如果(line==NULL)中断;
如果(第[0]行==“d”)printf(“%s”,第)行);/*行包括“\n”*/
}
pclose(pp);
}
返回0;
}

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

如果您只想运行脚本是最简单的事情,但它也会做一些其他事情,包括运行shell和让它运行命令(/bin/sh在most*nix下)

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

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

感兴趣的系统调用有
fork
execve
waitpid
。您可能需要在
execve
周围使用一个库包装器(键入
man3exec
获取它们的列表)。您可能还想使用其他等待功能之一(
man 2 wait
拥有所有这些功能)。此外,您可能对与fork相关的系统调用
clone
vfork
感兴趣

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

execve
将当前程序替换为新程序(保持相同的进程id)

父进程使用waitpid来等待特定子进程完成

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


您可能还对
管道
dup2
系统调用感兴趣<代码>管道
创建管道(同时具有输入和输出文件描述符)
dup2
将文件描述符复制为特定的文件描述符(
dup
类似,但将文件描述符复制为最低可用文件描述符)。

我更喜欢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);
一个简单的方法是

#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;
}
#包括
#包括
#定义SHELLSCRIPT“\
#/bin/bash\n\
回音“你好”\n\
echo \“你好吗\”\n\
回音“今天”\n\
"
/*也可以使用字符数组而不使用宏进行写入*/
/*您可以使用许多字符串将其拆分,最后连接起来
并发送到系统(连接的_字符串)*/
int main()
{
puts(“将使用以下脚本执行sh:”);
puts(shell脚本);
看跌期权(“现在开始:”);
系统(SHELLSCRIPT);//它将在c代码中运行脚本。
返回0;
}
感谢

尤达。。。假设它有可执行位和shebang行。通常,
系统(“/bin/sh/usr/local/bin/foo.sh”)。是的,这实际上调用了两次shell。嗨,马特。这是有用的。但是,我看到它被阻塞了。如何使其异步?还值得注意的是,fork()非常便宜,因为内存是写时复制的,并且不会在程序fork时立即复制。我非常喜欢fork/exec-它可以避免基于环境的不确定运行内容。但是您可以直接在shell脚本上使用它吗?正如您所说,通过使用exec,您“避免让shell(/bin/sh)为您运行命令”;因此,您不需要exec/bin/sh来运行shell脚本吗?@Tom Anderson:如果shell脚本为有效用户设置了执行权限,并且有一个适当的shabang第一行列出了有效用户也有权执行的文件,并且该文件本身不是某种脚本,那么内核将调用上列出的文件使用脚本文件创建沙邦行。如果脚本的沙邦是
#/bin/csh
则在fork/exec场景中不会运行
/bin/sh
。如果是
#/bin/sh
则它将在fork/exec场景中运行,但对于
系统
版本
/bin/sh
将为此脚本运行两次。
关闭(1)不需要,因为dup2()会在重新分配之前自行关闭新FD。
#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;
}