C++执行命令行并获取输出

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

C++执行CommandLine

前言

 在程序开发中经常需要通过执行命令行操作来拿到一些系统信息比如获取进程信息获取系统所有用户等等在这种情况下我们不但需要执行命令行还需要拿到命令行的返回结果C++提供了一个system函数可以执行指定的cmd但是只能返回一个执行结束的状态不能获得执行后的结果很多场景下都是没办法满足我们的需求的所以需要我们自己来造轮子。

1.执行操作

 除了system函数以外我们还可以通过popen这个函数这个函数的含义是

#include <stdio.h>

FILE *popen(const char *command, const char *type);

int pclose(FILE *stream);

popen()函数的作用是:通过创建管道、fork、并调用shell。因为根据定义管道是单向的类型参数可以只指定读或写作不是两者兼而有之;结果流相应地被读取只写或只写。

 用法很简单准备好cmd对于type由于我们是读取command的输出而不是向command输入参数所以设置为"r",然后popen会返回一个文件结构体指针用于读取执行完命令的输出如果type是"w"的话则这个文件结构体指针用于向cmd输入。

 执行cmd的逻辑为

#include <stdio.h>

int execCmd(const char* cmd, std::string& result){
    FILE* pipe = popen(cmd, "r");
    if(!pipe){
        printf("popen error\n");
        return -1;
    }
    return 0;
}

 接下来就是读取cmd的输出

2.读取操作

 读取pipe的内容有多种方式可以通过getlinefgets以及fread来读取

fgets读取

int execCmdUseFgets(const char *cmd, std::string &result)
{
    FILE *pipe = popen(cmd, "r");
    if (!pipe)
    {
        printf("popen error\n");
        return -1;
    }
    size_t ret = 0;
    char buf[bufferLen + 1] = {0};
    while (fgets(buf, bufferLen, pipe) != NULL)
    {
        result.append(buf);
    }
    printf("buf=%s\n",result.c_str());
    return 0;
}

getline读取

int execCmdUseGetline(const char *cmd, std::string &result)
{
    FILE *pipe = popen(cmd, "r");
    if (!pipe)
    {
        printf("popen error\n");
        return -1;
    }
    size_t ret = 0;
    char* buf = nullptr;
    size_t len  = bufferLen;
    ssize_t ret = 0;
    while ((ret = getline(&buf, &len, pipe)) != -1)
    {
        result.append(buf);
    }
    
    printf("buf=%s\n", result.c_str());
    return 0;
}

fread读取

int execCmd(const char* cmd, std::string& result){
    FILE* pipe = popen(cmd, "r");
    if(!pipe){
        TdError("popen error");
        return -1;
    }
    size_t ret = 0;
    char buf[bufferLen+1] = {0};
    while ((ret = fread(buf, sizeof(char),bufferLen, pipe)) == bufferLen){
        result.append(buf);
    }
    if(ferror(pipe) != 0) {
        TdError("read pipe error");
        return -1;
    }
    if(feof(pipe) != 0) {
        TdError("exec cmd:%s success");
        result.append(buf, ret);
    }
    return 0;
}

 三种读取方式都可以最终拿到返回数据不同的是fgetsgetline每次都只会读取一行即使buf很大每次也只读一行这意味着命令行有多少行的输出while循环就要执行多少次而fread不需要换行buf长度为多少每次最多就能读多少字节的内容具体用哪种方式需要结合具体的场景

 如果每次执行cmd的输出数据的长度起伏不大可以直接设置缓存区长度为一个cmd输出的长度一次即可读取完毕。如果输出的数据每次都起伏很大可以设置一个合适的buf长度来多次读取。

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: c++