C/C++ 运行shell脚本,并获取返回结果

C/C++运行shell命令通常有两种办法,调用 system() 或者 popen() 函数

1. system函数

system() 函数原型:

/* Execute the given line as a shell command.

   This function is a cancellation point and therefore not marked with
   __THROW.  */
extern int system (const char *__command) __wur;

可以发现, system() 函数会运行shell命令,并返回标志位,告知用户命令是否运行成功,但是不会返回shell指令的运行结果。

有时,我们需要shell命令的运行结果,比如我们写系统监控日志,我们需要把结果写到文件里
popen函数可以帮助我们。

2. popen函数

popen()函数原型:

/* Create a new stream connected to a pipe running the given command.

   This function is a possible cancellation point and therefore not
   marked with __THROW.  */
extern FILE *popen (const char *__command, const char *__modes)

popen函数的功能是这样的:创建一个子shell进程,运行__command指令;同时,会建立一个匿名管道用户当前进程和子进程之间的通信,用户可以通过这个管道,获取shell命令的运行结果,或是向shell进行写输入参数,popen函数的返回值FILE*就是指向这个管道。这个管道是一个单向管道,只能写或者读,不能同时读写,因此__modes只能是“r”或者“w”。

参考这篇文章(修改了几个小bug),封装了一个运行shell命令的函数;

纯C版:

#include <string.h>
#include <stdio.h>

#define CMD_RESULT_BUF_SIZE 1024

int ExecuteCMD_C(const char* cmd, char* result_)
{
    char result[CMD_RESULT_BUF_SIZE] = {0};
    char buf_temp[CMD_RESULT_BUF_SIZE] = {0};
    FILE *ptr = NULL;
    int iRet = -1;

    //popen: 开启子进程,建立管道,并运行指令,'r':从子进程获取结果,'w':向子进程写数据
    if((ptr = popen(cmd, "r")) != NULL)  //popen
    {
        while(fgets(buf_temp, sizeof(buf_temp), ptr) != NULL)
        {
            if(strlen(result) + strlen(buf_temp) > CMD_RESULT_BUF_SIZE){
                printf("shell返回结果超出buffer size,进行截断\n");
                break;
            }
           strcat(result, buf_temp);  //字符串拼接
        }
        strcpy(result_, result);
        pclose(ptr);
        ptr = NULL;
        iRet = 0;  // 处理成功
    }
    else
    {
        printf("popen %s error\n", cmd);
        iRet = -1; // 处理失败
    }

    return iRet;
}

int main() {
    char result_[CMD_RESULT_BUF_SIZE] ;
    ExecuteCMD_C("ps -e|grep test2| grep -v 'grep' | awk '{print $1}'", result_);
    printf("%s",result_);
    ExecuteCMD_C("ls", result_);
    printf("%s",result_);
}

在这里插入图片描述.
.

C++ std::string版:

#include <string.h>
#include <stdio.h>
#include <string>
#include <iostream>

#define CMD_RESULT_BUF_SIZE 1024

int ExecuteCMD_Cpp(const std::string cmd, std::string &result_)
{
    result_ = {};
    char buf_temp[CMD_RESULT_BUF_SIZE] = {0};
    FILE *ptr = NULL;
    int iRet = -1;

    //popen: 开启子进程,建立管道,并运行指令,'r':从子进程获取结果,'w':向子进程写数据
    if((ptr = popen(cmd.c_str(), "r")) != NULL)  //popen
    {
        while(fgets(buf_temp, sizeof(buf_temp), ptr) != NULL)
        {
           result_ += buf_temp;
        }
        pclose(ptr);
        ptr = NULL;
        iRet = 0;  // 处理成功
    }
    else
    {
        printf("popen %s error\n", cmd.c_str());
        iRet = -1; // 处理失败
    }

    return iRet;
}


int main() {
    std::string str;
    ExecuteCMD_Cpp("ps -e|grep test2| grep -v 'grep' | awk '{print $1}'", str);
    std::cout << str;
    ExecuteCMD_Cpp("ls", str);
    std::cout << str;
}

在这里插入图片描述
两个代码的运行结果是一致的。

C++的更好一些,不必担心字符串长度不够的问题。

参考:
https://zhuanlan.zhihu.com/p/351712885

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值