溫馨提示×

Linux中C++如何調用系統命令

小樊
32
2025-09-01 05:36:35
欄目: 編程語言

在 Linux 中,C++ 可以通過多種方式調用系統命令。以下是幾種常用的方法:

1. 使用 system() 函數

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

#include <cstdlib>

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

注意:

  • system() 會創建一個新的 shell 來執行命令,這可能會帶來安全風險,尤其是當命令字符串來自不可信的輸入時。
  • 它無法獲取命令的輸出,只能獲取退出狀態。

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;
}

安全性注意事項

  • 避免直接拼接用戶輸入:如果命令字符串包含用戶輸入,務必進行嚴格的驗證和轉義,以防止命令注入攻擊。
  • 最小權限原則:盡量以最小權限運行程序,避免執行高權限的系統命令。
  • 錯誤處理:始終檢查函數調用的返回值,處理可能的錯誤情況。

總結

根據具體需求選擇合適的方法:

  • 簡單執行且不需要獲取輸出:使用 system()。
  • 需要獲取命令輸出:使用 popen()fork() + exec()。
  • 需要更高的控制和靈活性:使用 fork() + exec() 系列函數。
  • 文件系統操作:優先考慮使用 C++17 的 std::filesystem。

通過合理選擇和使用這些方法,可以在 C++ 程序中有效地調用系統命令,同時確保代碼的安全性和可靠性。

0
亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女