【问题标题】:How can I execute external commands in C++/Linux?如何在 C++/Linux 中执行外部命令?
【发布时间】:2009-03-22 19:10:00
【问题描述】:

我只想知道在 C++ 中执行外部命令的最佳方法是什么,如果有输出,我该如何获取?

编辑:我想我不得不说我是这个世界上的新手,所以我想我需要一个可行的例子。例如我想执行如下命令:

ls -la

我该怎么做?

【问题讨论】:

    标签: c++ linux command-line


    【解决方案1】:

    使用popen 函数。

    示例(不完整,生产质量代码,无错误处理):

    FILE* file = popen("ls", "r");
    // use fscanf to read:
    char buffer[100];
    fscanf(file, "%100s", buffer);
    pclose(file);
    

    【讨论】:

    • @Daniel 这不是生产代码。这是一个在线论坛上的答案,它应该给人们关于 popen 函数及其参数的高级概念。任何习惯将所有 Stack Overflow 答案视为生产代码的人都会遇到比这更严重的问题。此外,任何可能溢出的缓冲区都不是值得大喊大叫的严重安全威胁。如果没有特定的威胁模型并且不知道在特定环境中什么是可信的,什么是不可信的,那么关于安全性的讨论就没有实际意义。
    • @Daniel 我听到了。当然,关于所有可能的陷阱的更完整的答案警告可能是一个更好的答案。你也许可以用三行代码写一本关于陷阱的书。然而,很明显,与这个问题密切相关的是“popen”,而不是你如何进一步处理外部进程的输出......
    • ...我觉得这个答案对能够解决其余问题的人来说已经足够有帮助了。这就是我写它的原因。是的,它并不完美。这就是为什么 Stack Overflow 拥有所有这些不错的功能,这样您就可以对需要注意的事情发表评论,或者更好的是,编辑或贡献您自己的更好的答案,而不是对其他志愿者贡献者发起人身攻击。考虑到我确实发布了一条明确暗示建议不要在生产代码中直接使用的警告,这尤其令人失望。
    • @MehrdadAfshari 您太好了,无法更新您的答案;我希望人们注意到了。
    • @Daniel 我认为当时(以及今天)很清楚,通常执行外部命令在生产中并不是一个很好的做法,原因有很多,其中一个是事实您可以简单地将该命令更改为其他命令.. 所以这几乎是常识.. 甚至不需要提及任何额外的内容(列表可能很大),因为它准确地回答了所要求的内容!我什至会将答案还原为原始答案:)
    【解决方案2】:

    一个例子:

    #include <stdio.h>
    
    int main() {
        FILE * f = popen( "ls -al", "r" );
        if ( f == 0 ) {
            fprintf( stderr, "Could not execute\n" );
            return 1;
        }
        const int BUFSIZE = 1000;
        char buf[ BUFSIZE ];
        while( fgets( buf, BUFSIZE,  f ) ) {
            fprintf( stdout, "%s", buf  );
        }
        pclose( f );
    }
    

    【讨论】:

    • 忘记在 main 末尾返回 0。并在 fgets 中使用 sizeof( buff ) 而不是 1000 :)
    • C++ 不需要在 main 结束时返回。
    • 是的,但是很高兴有回报,所以很明显程序会产生什么。
    • wget 将其状态消息写入 stderr - 使用 --quiet 选项运行它
    • @Dave Jarvis 请不要随意通过添加不必要的代码来“改进”我的答案。
    【解决方案3】:

    popen 绝对可以满足您的需求,但它有一些缺点:

    • 它会在您正在执行的命令上调用一个 shell(这意味着您需要清除任何用户提供的命令字符串)
    • 它只在一个方向上起作用,您可以向子流程提供输入,也可以读取其输出。

    如果您想调用子流程并提供输入和捕获输出,那么您必须执行以下操作:

    int Input[2], Output[2];
    
    pipe( Input );
    pipe( Output );
    
    if( fork() )
    {
        // We're in the parent here.
        // Close the reading end of the input pipe.
        close( Input[ 0 ] );
        // Close the writing end of the output pipe
        close( Output[ 1 ] );
    
        // Here we can interact with the subprocess.  Write to the subprocesses stdin via Input[ 1 ], and read from the subprocesses stdout via Output[ 0 ].
        ...
    }
    else
    {    // We're in the child here.
         close( Input[ 1 ] );
         dup2( Input[ 0 ], STDIN_FILENO );
         close( Output[ 0 ] );
         dup2( Output[ 1 ], STDOUT_FILENO );
    
         execlp( "ls", "-la", NULL );
    }
    

    当然,您可以根据需要将execlp 替换为任何其他 exec 函数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-04-16
      • 1970-01-01
      • 1970-01-01
      • 2014-07-03
      • 2013-07-01
      • 1970-01-01
      • 2013-12-03
      相关资源
      最近更新 更多