linux

Linux中C++如何调用系统命令

小樊
41
2025-09-01 05:36:35
栏目: 编程语言

在 Linux 中,C++ 可以通过多种方式调用系统命令。以下是几种常用的方法:

1. 使用 system() 函数

system() 是最简单的方法之一,它直接在子 shell 中执行指定的命令。

#include <cstdlib>

int main() {
    int ret = system("ls -l");
    return ret;
}

注意:

2. 使用 popen()pclose()

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 管理 FILE* 的生命周期
    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);
    } catch (const std::runtime_error& e) {
        std::cerr << "Error: " << e.what() << std::endl;
        return EXIT_FAILURE;
    }
    return EXIT_SUCCESS;
}

向命令写入输入示例:

#include <cstdio>
#include <iostream>
#include <memory>
#include <stdexcept>
#include <string>

int exec(const char* cmd, const char* input) {
    int pipefd[2];
    if (pipe(pipefd) == -1) {
        throw std::runtime_error("pipe() failed!");
    }

    pid_t pid = fork();
    if (pid == -1) {
        throw std::runtime_error("fork() failed!");
    } else if (pid == 0) { // 子进程
        close(pipefd[0]); // 不需要读取端

        // 将标准输入重定向到管道写端
        dup2(pipefd[1], STDIN_FILENO);
        close(pipefd[1]);

        // 执行命令
        execl("/bin/sh", "sh", "-c", cmd, (char*)NULL);
        // 如果 execl 返回,表示失败
        perror("execl");
        exit(EXIT_FAILURE);
    } else { // 父进程
        close(pipefd[1]); // 不需要写入端

        char buffer[128];
        ssize_t count;
        while ((count = read(pipefd[0], buffer, sizeof(buffer)-1)) > 0) {
            buffer[count] = '\0';
            std::cout << buffer;
        }

        if (count == -1) {
            throw std::runtime_error("read() failed!");
        }

        int status;
        waitpid(pid, &status, 0); // 等待子进程结束
        if (WIFEXITED(status)) {
            return WEXITSTATUS(status);
        }
    }
    return EXIT_SUCCESS;
}

int main() {
    try {
        std::string output = exec("grep Hello", "Hello\nWorld\nHello C++");
        std::cout <<(output);
    } catch (const std::runtime_error& e) {
        std::cerr << "Error: " << e.what() << std::endl;
        return EXIT_FAILURE;
    }
    return EXIT_SUCCESS;
}

3. 使用 fork()exec() 系列函数

通过 fork() 创建子进程,并使用 exec() 系列函数在子进程中执行命令。这种方法提供了更高的灵活性,但实现起来更复杂。

#include <iostream>
#include <unistd.h>
#include <sys/wait.h>

int main() {
    pid_t pid = fork();
    if (pid == -1) {
        // 创建子进程失败
        perror("fork");
        return EXIT_FAILURE;
    } else if (pid == 0) { // 子进程
        // 执行命令,例如 ls -l
        execl("/bin/ls", "ls", "-l", (char*)NULL);
        // 如果 execl 返回,表示失败
        perror("execl");
        return EXIT_FAILURE;
    } else { // 父进程
        int status;
        // 等待子进程结束
        waitpid(pid, &status, 0);
        if (WIFEXITED(status)) {
            std::cout << "子进程退出,状态码:" << WEXITSTATUS(status) << std::endl;
        }
    }
    return EXIT_SUCCESS;
}

4. 使用 C++17 的 std::filesystem(适用于文件系统操作)

虽然 std::filesystem 不是直接用于执行系统命令,但它提供了丰富的文件和目录操作功能,可以减少对系统命令的依赖。

#include <iostream>
#include <filesystem>

namespace fs = std::filesystem;

int main() {
    for (const auto& entry : fs::directory_iterator("/path/to/directory")) {
        std::cout << entry.path() << std::endl;
    }
    return EXIT_SUCCESS;
}

安全性注意事项

总结

根据具体需求选择合适的方法:

通过合理选择和使用这些方法,可以在 C++ 程序中有效地调用系统命令,同时确保代码的安全性和可靠性。

0
看了该问题的人还看了