c++写入shell命令
C++编程执行shell命令
本文写作用于linuxC++编程
system调用执行shell命令
使用system(“ls -l ”)执行shell命令,但其返回值为整型。返回0则为不成功执行。
#include <iostream>
int main(){
std::string cmd = "ls -l";
int ret = system(cmd.to_str());
return 0;
}
popen调用执行shell命令
使用popen调用执行命令,FILE *popen(const char *command, const char *type);
,popne返回值为标准IO流,不包括标准异常的返回;且popen的输出流默认是块缓冲的;popen的实现原理为调用popen时会创建一个管道,用于父子进程之间通信;然后fork子进程,子进程调用exec执行指定命令(一般默认会用/bin/sh -c),父进程通过返回的文件指针与子进程交互;唤醒shell程序执行shell命令。支持的类型参数为读或者写模式。结果流相应为只读或者只写。command参数是一个包含shell命令的非空字符串指针,cmd通过‘/bin/sh -c’ 解释shell命令。另外需要配套使用pclose()函数等待进程终结,并返回退出状态。由于其是直接使用/bin/sh执行shell命令,所以会具有命令注入的风险。
#include <iostream>
using namespace std;
int main(){
std::string cmd = "ls -l";
FILE* stream = popen(cmd.c_str(), "r");
char buffer[128];
while (fgets(buffer, sizeof(buffer), stream)) {
cout << buffer;
}
pclose(stream);
return 0;
}
此种方式的缺点是,安全性差,可能会被串改
pipe、fork、exec组合
pipe创建管道、fork创建子进程,然后使用子进程使用execl函数执行命令
#include <iostream>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
using namespace std;
int main(){
std::string cmd = "ls -l";
pid_t pid;
int pipefd[2];
if (pipe(pipefd)) {
perror("pipe failed");
exit(EXIT_FAILURE);
}
pid = fork(); //fork子进程,共享管道fd
if (pid == 0) { // 子进程
cout << "子进程id是" << getpid() << endl;
cout << "父进程id是" << getppid() << endl;
// 关闭读端
close(pipefd[0]);
dup2(pipefd[1], STDOUT_FILENO); // 标准输出重定向到fd
dup2(pipefd[1], STDERR_FILENO);
execl("/bin/ls", "ls", "-l", (char*)nullptr);
} else if (pid > 0) {
cout << "子进程id是" << getpid() << endl;
cout << "父进程id是" << getppid() << endl;
close(pipefd[1]); // 关闭写端
char buffer[128];
// FILE* stream = fdopen(pipefd[0],"r");
// while (fgets(buffer, sizeof(buffer), stream)) {
// cout << buffer;
// }
while (read(pipefd[0], buffer, sizeof(buffer))) {
cout << buffer;
}
close(pipefd[0]); // 关闭读端
wait(nullptr);
} else {
perror("fork failed");
exit(EXIT_FAILURE);
}
return 0;
}
封装为c++流
使用stdio_filebuf封装FILE文件流为C++文件缓冲,从而可以被istream进行初始化。
__gnu_cxx::stdio_filebuf(FILE* file, std::ios::openmode mode);
openmode支持的文件模式为:std::ios::in(读取模式),std::ios::out(写入模式),std::ios::out|std::ios::in(写入加读取模式),之后使用istream对象关联到filebuf
#include <iostream>
#include <ext/stdio_filebuf.h>
using namespace std;
int main(){
std::string cmd = "ls -l";
FILE* stream = popen(cmd.c_str(), "r");
string temp;
__gnu_cxx::stdio_filebuf<char> filebuf(stream, std::ios::in);
while (getline(istream(&filebuf), temp)) {
cout << temp << endl;
}
pclose(stream);
return 0;
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 2分钟学会 DeepSeek API,竟然比官方更好用!
· .NET 使用 DeepSeek R1 开发智能 AI 客户端
· 10亿数据,如何做迁移?
· 推荐几款开源且免费的 .NET MAUI 组件库
· c# 半导体/led行业 晶圆片WaferMap实现 map图实现入门篇