linux应用程序中执行shell命令常用的俩个接口:system和popen。
使用system的话只是单纯的执行,而得不到命令执行结果。倘若想要以数据的形式得到命令执行结果用于其他用途,那么popen和fgets来实现就是最简单的选择。
一、popen函数
该函数的使用,参考《Unix环境高级编程手册》。
二、fgets函数
char *fgets(char *buf, int size, FILE *stream);
该函数从指定文件流stream读取指定size长度数据,或者1行数据返回存到buf。
(1) 两个特点注意:
①读到换行符返回时,会把换行符存到buf中,不会把换行符丢掉。
所以有时候调试时,如果多次读到的内容都紧接着存到一个buf中,让后统一%s打印,会出现自动换行的情况,就是这里的原因。
②返回成功以后,会在buf末尾加上‘\0’
所以程序员就不用考虑strlen是否可用,要不要手动注意加\0的问题了。
(2) 返回条件是:
- 读到size个字节数据
读取成功,返回指向s的指针。
- 还没到size个数据但读到换行符号了。
读取成功,返回指向s的指针。
- 还没读到size个,也没遇到换行符,但遇到文件末尾(EOF)了
读取失败,返回NULL
(3)返回值:如上所述
(4)常见使用方式
由返回值可以知道,通常调用该接口的形式就是:
while(fgets(buf, size,pfile) != NULL)
{
......
}
三、示例
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define BUFFER_SIZE 4096
int main(int argc, char **argv)
{
char *cmd_string = "ls /";
FILE *cmd_fp = popen(cmd_string, "r");
if(cmd_fp == NULL)
{
printf("popen failed\n");
exit(-1);
}
char *read_buf = (char *)malloc(BUFFER_SIZE);//直接定死buffer大小,不是合理的方式,不能假设命令的执行结果不会超过你指定的buffer大小
if(read_buf == NULL)
{
printf("malloc failed\n");
exit(-1);
}
memset(read_buf, 0, BUFFER_SIZE);
/* 读取命令执行结果并打印 */
char *ptmp = read_buf;
while(fgets(ptmp, BUFFER_SIZE, cmd_fp)!=NULL)
{
if(((unsigned long)(ptmp) + strlen(ptmp)) >= ((unsigned long)(read_buf) + BUFFER_SIZE -32))//因为无法确定下一个读到的长度是多少,所以暂定32个字节的余量
break;
ptmp += strlen(ptmp);
}
printf("result:\n%s\n",read_buf);
free(read_buf);
pclose(cmd_fp);
exit(0);
}