阅读量:2
在 Linux 中,C++ 可以通过多种方式调用系统命令。以下是几种常用的方法:
1. 使用 system() 函数
system() 是最简单的方法之一,它直接在子 shell 中执行指定的命令。
#include
int main() {
int ret = system("ls -l");
return ret;
}
注意:
system()会创建一个新的 shell 来执行命令,这可能会带来安全风险,尤其是当命令字符串来自不可信的输入时。- 它无法获取命令的输出,只能获取退出状态。
2. 使用 popen() 和 pclose()
popen() 打开一个指向命令的管道,并允许读取命令的输出或向其写入输入。
读取命令输出示例:
#include
#include
#include
#include
#include
std::string exec(const char* cmd) {
std::array<char, 128> buffer;
std::string result;
// 使用 unique_ptr 管理 FILE* 的生命周期
std::unique_ptrdecltype (&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
#include
#include
#include
#include
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
#include
#include
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
#include
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++ 程序中有效地调用系统命令,同时确保代码的安全性和可靠性。
以上就是关于“Linux中C++如何调用系统命令”的相关介绍,筋斗云是国内较早的云主机应用的服务商,拥有10余年行业经验,提供丰富的云服务器、租用服务器等相关产品服务。云服务器资源弹性伸缩,主机vCPU、内存性能强悍、超高I/O速度、故障秒级恢复;电子化备案,提交快速,专业团队7×24小时服务支持!
简单好用、高性价比云服务器租用链接:https://www.jindouyun.cn/product/cvm