在 Linux 下,C++ 可以通过多种方式调用系统命令。以下是几种常用的方法:
system()
函数system()
是最简单的调用系统命令的方法,它直接将命令传递给 shell 执行。
#include <cstdlib>
int main() {
int ret = system("ls -l");
return ret;
}
注意:
system()
会启动一个新的 shell 进程,因此开销较大。popen()
函数popen()
允许你执行一个命令并与其进行通信,可以读取命令的输出或向其写入数据。
读取命令输出示例:
#include <cstdio>
#include <iostream>
#include <memory>
#include <stdexcept>
#include <string>
std::string exec(const char* cmd) {
std::array<char, 128> buffer;
std::string result;
// 使用 unique_ptr 自动管理文件描述符
std::unique_ptr<FILE, decltype(&pclose)> 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() {
try {
std::string output = exec("ls -l");
std::cout << "Output:\n" << output;
} catch (const std::exception& e) {
std::cerr << "Error: " << e.what() << std::endl;
}
return 0;
}
向命令写入数据示例:
#include <cstdio>
#include <iostream>
#include <memory>
#include <stdexcept>
#include <string>
int main() {
std::string cmd = "grep hello";
std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd.c_str(), "w"), pclose);
if (!pipe) {
throw std::runtime_error("popen() failed!");
}
const char* input = "hello world\nhello C++\ngoodbye world";
size_t written = fwrite(input, 1, strlen(input), pipe.get());
if (written != strlen(input)) {
throw std::runtime_error("Failed to write to pipe.");
}
int status = pclose(pipe.release());
if (status == -1) {
throw std::runtime_error("pclose() failed!");
}
return 0;
}
注意:
popen()
同样会启动一个新的 shell 进程。pclose()
关闭管道。fork()
和 exec()
系列函数对于更高级的控制,可以使用 fork()
创建子进程,并使用 exec()
系列函数在子进程中执行命令。这种方法不会启动新的 shell,效率更高,但编程复杂度也更大。
#include <iostream>
#include <unistd.h>
#include <sys/wait.h>
#include <cstring>
int main() {
pid_t pid = fork();
if (pid == -1) {
// 创建子进程失败
perror("fork");
return 1;
} else if (pid == 0) {
// 子进程
// 替换子进程的映像为 /bin/ls
execl("/bin/ls", "ls", "-l", (char *)NULL);
// 如果 execl 返回,说明失败
perror("execl");
return 1;
} else {
// 父进程
int status;
pid_t result = waitpid(pid, &status, 0);
if (result == -1) {
perror("waitpid");
return 1;
}
if (WIFEXITED(status)) {
std::cout << "Command exited with status: " << WEXITSTATUS(status) << std::endl;
}
}
return 0;
}
注意:
对于需要同时执行多个系统命令或与其他 C++ 代码并行运行的情况,可以结合多线程或异步编程模型。
#include <iostream>
#include <thread>
#include <vector>
#include <cstdlib>
void run_command(const std::string& cmd) {
int ret = std::system(cmd.c_str());
if (ret != 0) {
std::cerr << "Command failed: " << cmd << std::endl;
}
}
int main() {
std::vector<std::string> commands = {"ls -l", "pwd", "echo Hello, World!"};
std::vector<std::thread> threads;
for (const auto& cmd : commands) {
threads.emplace_back(run_command, cmd);
}
for (auto& th : threads) {
if (th.joinable()) {
th.join();
}
}
return 0;
}
注意:
根据具体需求选择合适的方法:
system()
。popen()
。fork()
和 exec()
系列函数。在使用这些方法时,务必注意安全性和错误处理,尤其是在处理来自不可信输入的命令时,以防止潜在的安全漏洞。