【问题标题】:Executing bash command and getting the output in C执行 bash 命令并在 C 中获取输出
【发布时间】:2013-01-01 20:36:34
【问题描述】:

您好,我在网上看到了一些解决方案,基本上都是创建文件,但是我想将它们存储在一个 char 数组中。速度对我来说真的很重要,我不想花时间在硬盘上工作。所以popen() 对我来说不是一个真正的解决方案。

【问题讨论】:

  • popen 不打开文件。它运行一个程序并将输出直接连接到 C 输入流。我知道流的类型称为FILE*,但它并不是真正的文件。
  • 您对popen 有什么反对意见?这将是执行此操作的正常方式。
  • 如果速度是您最关心的问题,您为什么要首先尝试执行 bash 命令?
  • 另外,请考虑阅读man 3 popen,它包含您需要知道的所有内容,包括为什么popen 是这里的最佳选择。

标签: c linux bash command


【解决方案1】:

您介意拥有多个 C 程序吗?如果您不介意,您可以使用命令行参数。在第一个 C 程序中,您可以执行以下操作

system("YourCommand | SecondProgram");

SecondProgram 将是您将要编写的第二个 C 程序的“可执行文件”。在第二个 C 程序中,您可以接收命令YourCommand 的输出作为SecondProgram 中的命令行参数。为此,您可以开始第二个 C 程序的 main(),如下所示

main(int argc,char *argv[])

数组argv 将具有YourCommand 的输出,argc 将包含数组argv 中的元素数。

【讨论】:

  • @AndreasGrapentin 说明原因
  • 我真的不认为这对我来说是一个快速的方法。此外我不明白第二个程序如何将输出发送回第一个程序......
  • 也许最重要的原因是您不能确定 SecondProgram 真的是您想要的程序。编辑:有关更多信息,请参阅cplusplus.com/forum/articles/11153
  • @SarpKaya 在第二个程序中实现输出处理。在你的情况下这是一个问题吗?您尝试通过哪个命令执行?系统调用不能成为解决方案吗?
【解决方案2】:

如果您阅读 popen 的联机帮助页,您会注意到以下内容:

popen() 函数通过创建管道、分叉、 并调用外壳。 [...] popen() 的返回值是 在所有方面都正常的标准 I/O 流,除了它必须是 用 pclose() 而不是 fclose(3) 关闭。 [...] 从 "popened" 流读取命令的标准输出,并且 命令的标准输入与进程的标准输入相同 调用 popen()。

(强调我的)

如您所见,对popen 的调用导致命令的stdout 通过I/O 流 传送到您的程序中,这与磁盘I 无关/O,而是由操作系统管理的进程间通信。

(作为旁注:在合理范围内,依靠操作系统的基本功能来解决常见问题通常是一个好主意。由于popenPOSIX.1-2001 的一部分,因此您可以依赖它适用于所有符合标准的操作系统,甚至 Windows)

编辑:如果您想了解更多信息,请阅读:http://linux.die.net/man/3/popen

【讨论】:

    【解决方案3】:

    如果速度对您很重要,您可以编写自己的 popen 版本。

    这可能是有道理的,因为 popen() - 创建一个管道 - 叉子 - 执行外壳(非常昂贵!) - 外壳创建管道、分叉、执行您的程序

    您的定制版本可以将程序简化为: - 创建一个管道 - 叉子 - 执行你的程序

    您甚至可以扩展 popen 来分别控制命令 STDOUT、STDERR 和 STDIN。 我写了这样一个套路,见https://github.com/rockdaboot/mget/blob/master/libmget/pipe.c 它是 GPL 的。

    您使用 FILE 指针调用 mget_popen3() 或使用文件描述符调用 mget_fd_popen3()。 至少,它应该让你知道如何去做。

    【讨论】:

      【解决方案4】:

      这是一个工作代码sn-p:

      char bash_cmd[256] = "ls -l";
      char buffer[1000];
      FILE *pipe;
      int len; 
      
      pipe = popen(bash_cmd, "r");
      
      if (NULL == pipe) {
          perror("pipe");
          exit(1);
      } 
      
      fgets(buffer, sizeof(buffer), pipe);
      
      len = strlen(buffer);
      buffer[len-1] = '\0'; 
      
      pclose(pipe);
      

      【讨论】:

      • 这不是一个有效的sn-p,您必须在fgets之后修改buffer变量而不是bash_cmd
      【解决方案5】:

      永远不要忘记 Knuth 所说的“过早的优化是万恶之源”。在重要之前不要担心性能,然后在做任何事情之前测量。除极少数情况外,您的时间价值远高于程序运行的成本。

      Jon Bentley 的“编写高效程序”(遗憾的是已绝版,在他的"Programming Pearls" 一章中有总结)详细讨论了如何使程序运行得更快(如果值得的话);并且仅作为最后一项措施,为了挤出最后可能的 2% 的性能(在将运行时间减少一半之后),它建议使用您建议的更改。引用的书中包含一些非常有趣的关于“性能优化”的战争故事,这些故事完全是一种浪费(优化从未使用过的代码,优化运行的代码,而操作系统正在转动它的拇指,...)。

      【讨论】:

        猜你喜欢
        • 2011-12-28
        • 2018-01-16
        • 2014-06-29
        • 2016-10-10
        • 2010-10-03
        相关资源
        最近更新 更多