#define MAXLINE 1024
int main()
char result_buf[MAXLINE], command[MAXLINE];
int rc = 0; // 用于接收命令返回值
FILE *fp;
/*将要执行的命令写入buf*/
snprintf(command, sizeof(command), "ls ./ | wc -l");
/*执行预先设定的命令,并读出该命令的标准输出*/
fp = popen(command, "r");
if(NULL == fp)
perror("popen执行失败!");
exit(1);
while(fgets(result_buf, sizeof(result_buf), fp) != NULL)
/*为了下面输出好看些,把命令返回的换行符去掉*/
if('\n' == result_buf[strlen(result_buf)-1])
result_buf[strlen(result_buf)-1] = '\0';
printf("命令【%s】 输出【%s】\r\n", command, result_buf);
/*等待命令执行完毕并关闭管道及文件指针*/
rc = pclose(fp);
if(-1 == rc)
perror("关闭文件指针失败");
exit(1);
printf("命令【%s】子进程结束状态【%d】命令返回值【%d】\r\n", command, rc, WEXITSTATUS(rc));
return 0;
编译并执行:
$ gcc popen.c
$ ./a.out
上面popen只捕获了command的标准输出,如果command执行失败,子进程会把错误信息打印到标准错误输出,父进程就无法获取。比如,command命令为“ls nofile.txt” ,事实上我们根本没有nofile.txt这个文件,这时shell会输出“ls: nofile.txt: No such file or directory”。这个输出是在标准错误输出上的。通过上面的程序并无法获取。
注:如果你把上面程序中的command设成“ls nofile.txt”,编译执行程序你会看到如下结果:
$ gcc popen.c
$ ./a.out
ls: nofile.txt: No such file or directory
命令【ls nofile.txt】子进程结束状态【256】命令返回值【1】
需要注意的是第一行输出并不是父进程的输出,而是子进程的标准错误输出。
有时子进程的错误信息是很有用的,那么父进程怎么才能获取子进程的错误信息呢?
这里我们可以重定向子进程的错误输出,让错误输出重定向到标准输出(2>&1),这样父进程就可以捕获子进程的错误信息了。例如command为“ls nofile.txt 2>&1”,输出如下:
命令【ls nofile.txt 2>&1】 输出【ls: nofile.txt: No such file or directory】
命令【ls nofile.txt 2>&1】子进程结束状态【256】命令返回值【1】
附:子进程的终止状态判断涉及到的宏,设进程终止状态为status.
WIFEXITED(status)如果子进程正常结束则为非0值。
WEXITSTATUS(status)取得子进程exit()返回的结束代码,一般会先用WIFEXITED 来判断是否正常结束才能使用此宏。
WIFSIGNALED(status)如果子进程是因为信号而结束则此宏值为真。
WTERMSIG(status)取得子进程因信号而中止的信号代码,一般会先用WIFSIGNALED 来判断后才使用此宏。
WIFSTOPPED(status)如果子进程处于暂停执行情况则此宏值为真。一般只有使用WUNTRACED 时才会有此情况。
WSTOPSIG(status)取得引发子进程暂停的信号代码,一般会先用WIFSTOPPED 来判断后才使用此宏。