在 Linux 环境写 C++ 程序时,经常会遇到“代码里顺手执行一条命令”的需求,比如列目录、调用系统工具,或者把命令结果继续交给程序处理。这个问题看似简单,真正落地时却要先分清需求:你到底只是想把命令跑起来,还是还要接住输出、继续分析结果;本文就围绕这两个方向,分别梳理 system() 和 popen() 的用法、差异,以及什么场景下更适合选哪一种。
用 system() 直接执行命令
如果需求很简单,只是让程序执行一条 Linux 命令,那么最直接的办法就是调用 system()。这个函数接收一个字符串参数,参数内容就是要执行的命令。
原理上,它更像是“把命令丢给系统去执行”。写法非常短,适合快速调用现成命令。
#include <cstdlib>int main() {system("ls -l");return 0;}这段程序运行后会执行 ls -l,终端里会输出当前目录的列表。
system() 的优点很明确:上手成本低,代码也最少。对于“只想执行命令,不关心程序内如何处理输出”的场景,这种方式足够直接。
system() 需要注意什么
它的限制也同样明显。最需要注意的一点是,system() 是阻塞的:命令没有执行完,当前 C++ 程序就不会继续往下运行。
这意味着它更适合一次性、短平快的调用。如果你的程序后面还要依赖命令结果做判断,或者希望把输出拿回 C++ 代码里继续处理,system() 就显得不够用了。
用 popen() 通过管道读取输出
如果你不仅要执行命令,还想获取命令输出,那么更常见的方案是 popen()。它会在程序和外部命令之间建立一个管道,让你可以在 C++ 里读取命令返回的内容。

下面这个例子做了一层简单封装:执行命令后,逐行读取输出,并拼接成一个字符串返回。
#include <iostream>#include <cstdio>#include <memory>#include <stdexcept>std::string exec(const char* cmd) {std::array<char, 128> buffer;std::string result;std::shared_ptr<FILE> pipe(popen(cmd, "r"), pclose);if (!pipe) throw std::runtime_error("popen() failed!");while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {result += buffer.data();}return result;}int main() {std::string output = exec("ls -l");std::cout << output;return 0;}这段代码里,popen(cmd, "r") 表示以读取模式执行命令;随后通过 fgets() 持续读取命令输出,最后把结果保存到 std::string 中,再输出到控制台。
相比 system(),这种方式的核心价值不在“把命令跑起来”,而在“把命令输出接回来”。只要你后续要做文本处理、状态判断、结果记录,popen() 的实用性都会更高。
popen() 更灵活在哪里
popen() 更适合需要交互控制的场景。文章原文提到,它不仅可以接收命令输出,也可以向命令发送输入;从使用思路上看,它比 system() 更像一条可操作的通信通道,而不只是单纯触发一次外部命令。
因此,当你希望处理标准输出、错误流,或者把外部命令当作程序流程中的一个环节时,通常会优先考虑这种方案。
怎么选:看你是否需要处理结果
两种方式并不是谁完全替代谁,而是适合的任务不同。

如果你的目标只是执行一条命令,执行完就结束,不需要在 C++ 代码里进一步接管结果,那么 system() 足够简单,也最省事。
如果你需要拿到命令输出,准备把返回内容继续解析、打印、判断,或者纳入程序逻辑里,那么 popen() 会更合适。它虽然写法比 system() 多一些,但换来的,是更高的可控性和更清晰的程序内处理能力。
可以概括为一句话:system() 适合“只执行”,popen() 适合“执行后还要处理结果”。在实际开发里,如果需求已经涉及输出读取或交互,优先从 popen() 开始考虑会更稳妥。









