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

     2023-02-23     195

关键词:

【中文标题】如何在 Linux 中从 C 执行 shell 脚本?【英文标题】:How to execute a shell script from C in Linux? 【发布时间】:2011-04-13 18:24:39 【问题描述】:

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

【问题讨论】:

【参考方案1】:

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

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

如果您想通过标准输入提供 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 更改为与使用的父进程不同的文件、更改进程的用户或组、关闭子进程不需要的文件、更改会话或更改环境变量。

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

【讨论】:

另外值得注意的是,fork() 非常便宜,因为内存是写时复制的,并且不会在程序分叉时立即复制。 我是 fork/exec 的忠实粉丝——它可以让你避免基于环境的不确定性来决定运行什么。但是你可以直接在 shell 脚本上使用它吗?正如您所说,通过使用 exec,您“避免让 shell (/bin/sh) 为您运行命令”;因此,您不需要 exec /bin/sh 来运行 shell 脚本吗? @Tom Anderson:如果 shell 脚本为有效用户设置了执行权限,并且有一个适当的 shabang 第一行列出了一个文件,有效用户也有权执行并且本身也不是脚本某种类型的内核将使用脚本文件调用 shabang 行中列出的文件。如果脚本的shabang 是#!/bin/csh,那么/bin/sh 将不会在fork/exec 场景中运行。如果是 #!/bin/sh,那么它会在 fork/exec 场景中,但对于 system 版本,/bin/sh 将为此脚本运行两次。【参考方案2】:

你可以使用system:

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

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

【讨论】:

... 假设它具有可执行位和 shebang 行。一般来说,system("/bin/sh /usr/local/bin/foo.sh");。是的,这实际上调用了两次 shell。 嗨,马特。这很有用。但是,我看到它正在阻塞。如何使其异步?【参考方案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;

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

【讨论】:

【参考方案5】:

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

【讨论】:

【参考方案6】:

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

【讨论】:

close(1); 不需要,因为 dup2() 在重新分配之前会自行关闭 newfd。

如何在 Linux 中从 Mono/C# 访问游戏杆/游戏手柄?

】如何在Linux中从Mono/C#访问游戏杆/游戏手柄?【英文标题】:Howtoaccessajoystick/gamepadfromMono/C#inLinux?【发布时间】:2013-03-2020:38:39【问题描述】:我正在运行Debian的RaspberryPi上使用C#开发一个机器人项目。我得到了一个与操作系统... 查看详情

如何在Linux中从C打印毫秒和纳秒精度的时间差?

】如何在Linux中从C打印毫秒和纳秒精度的时间差?【英文标题】:HowtoprinttimedifferenceinaccuracyofmillisecondsandnanosecondsfromCinLinux?【发布时间】:2013-04-2222:19:32【问题描述】:我有这个程序可以打印2个不同实例之间的时间差,但它的... 查看详情

如何在 C/C++ 中从 system() 捕获结果 [重复]

】如何在C/C++中从system()捕获结果[重复]【英文标题】:howtocaptureresultfromsystem()inC/C++[duplicate]【发布时间】:2010-02-1404:18:42【问题描述】:可能重复:HowcanIrunanexternalprogramfromCandparseitsoutput?嗨,有人可以告诉我们在执行system()函数... 查看详情

在 C# 中从 .docx 文件的页眉和页脚获取图像

...描述】:我有一个.docx文件,它在页脚和页眉中有图像。如何获取图片,知道哪些在页脚,哪些在页眉?我尝试使用:Microsoft.Office.Interop.Word.Rangerange=section.Footers[Microsof 查看详情

使用 Pywinrm 在远程 Windows 机器中从 linux 执行 vbs 脚本(执行双跳)

】使用Pywinrm在远程Windows机器中从linux执行vbs脚本(执行双跳)【英文标题】:Executevbsscript(thatdoesdoublehop)inremotewindowsmachinefromlinuxusingPywinrm【发布时间】:2015-05-1919:25:04【问题描述】:我需要从Linux机器在Windows机器上运行vbs脚本... 查看详情

如何在windows实现远程调用linux下的shell指令

求一个实现方法,请高人指教。想通过windows的cmd或者Vb语言,来实现远程调用Linux下一个Shell指令。等待到这个shell指令结束后,将执行结果返回到Windows。参考技术A可以用ssh协议远程连接linux服务器就可以使用linux服务器上的shell... 查看详情

如何在 Windows 中从我的 VS2008/C++ 应用程序中执行一个程序来替换调用者并在 xp/vista/7 上运行?

】如何在Windows中从我的VS2008/C++应用程序中执行一个程序来替换调用者并在xp/vista/7上运行?【英文标题】:HowcanIexecuteaprogramfrommyVS2008/C++applicationinwindowsthatreplacesthecallerandrunsonxp/vista/7?【发布时间】:2012-04-2718:04:52【问题描述】:... 查看详情

如何在 Python 中从 SXS 加载 C DLL?

】如何在Python中从SXS加载CDLL?【英文标题】:HowdoIloadaCDLLfromtheSXSinPython?【发布时间】:2014-12-0921:31:31【问题描述】:这通常通过在与可执行文件一起驻留的清单文件中指定DLL依赖项来完成。但是,我不知道如何在Python中实现这... 查看详情

如何查看linux上的历史执行命令

1>History命令语法:[test@linux]#history[n][test@linux]#history[-c][test@linux]#history[-raw]histfiles参数:n:数字,要列出最近的n笔命令列表-c:将目前的shell中的所有history内容全部消除-参考技术Ahistory命令。 参考技术B1>History命令语法:[test@l... 查看详情

如何使用 C 函数执行 Shell 内置命令?

】如何使用C函数执行Shell内置命令?【英文标题】:HowdoIexecuteaShellbuilt-incommandwithaCfunction?【发布时间】:2013-10-1302:23:47【问题描述】:我想通过像execv()这样的C语言函数来执行Linux命令“pwd”。问题是没有名为“pwd”的可执行文... 查看详情

linux中实现延迟45分钟后执行命令,写了一段c程序,实现延迟,接下来,该如何执行命令呢,也就是shell

...urname\n");system("pause");return0;问题:接下里该如何去执行shell命令,是在c代码中实现,还是c语言里调用shell文件。如何实现,谢谢。新情况:嵌入式linux没有at命令还是c代码实现吧参考技术A1、system(执行shell命令)相... 查看详情

是否可以在标准 C 中从堆栈中执行代码?

】是否可以在标准C中从堆栈中执行代码?【英文标题】:IsitpossibletoexecutecodefromthestackinstandardC?【发布时间】:2011-04-1421:43:32【问题描述】:以下代码无法按预期工作,但希望能说明我的尝试:longfoo(inta,intb)returna+b;voidcall_foo_from_... 查看详情

如何在目标 c 中从 int 转换为字符串:示例代码

】如何在目标c中从int转换为字符串:示例代码【英文标题】:Howtoconvertfrominttostringinobjectivec:examplecode【发布时间】:2010-11-0910:36:04【问题描述】:我正在尝试从int转换为字符串,但我遇到了麻烦。我通过调试器跟踪执行,字符... 查看详情

linux系列教程(二十)——linux的shell概述以及如何执行脚本

  从这篇博客开始,我们将进入Linux的shell脚本的学习,这对于Linux学习爱好者而言是特别重要的一节,也是特别有意思的一节,shell脚本就像我们知道的Java,php类似的编程语言一样,通过shell脚本,我们能完成很多有意思的应... 查看详情

如何在 C# 中从路径运行 .exe

】如何在C#中从路径运行.exe【英文标题】:Howtoruna.exeinC#fromapath【发布时间】:2014-04-0203:54:58【问题描述】:我在从路径执行.exe时遇到问题。我已经搜索了谷歌并检查了有关此主题的推荐内容,但是它们不起作用...我正在尝试从... 查看详情

如何在shell脚本中,判断一个基本命令执行是不是成功

1.连接到相应的Linux主机,进入Linux命令行状态,等待shell命令的输入。2.在Linux命令行下,输入shell命令:Telnet192.168.120.209。3.最后,按下回车键执行shell指令,此时会看到telnet并没有连接成功。注意事项附件:LINUX系统外壳原理作为... 查看详情

如何在 Windows 中从 C++ 程序执行另一个 exe

】如何在Windows中从C++程序执行另一个exe【英文标题】:HowtoexecuteanotherexefromaC++programinWindows【发布时间】:2013-07-1715:17:23【问题描述】:我希望我的C++程序在Windows中执行另一个.exe。我该怎么做?我正在使用VisualC++2010。这是我的... 查看详情

如何在 Android 中从 Java 代码执行 Python 脚本

】如何在Android中从Java代码执行Python脚本【英文标题】:HowtoexecutePythonscriptfromJavacodeinAndroid【发布时间】:2015-05-0904:22:31【问题描述】:我正在尝试让一个标准的Android应用程序执行一个可以将值返回给Java的python脚本,但我面临... 查看详情