zoukankan      html  css  js  c++  java
  • Linux下使用popen()执行shell命令【转】

    本文转载自:https://my.oschina.net/u/727148/blog/262987

    函数原型:

      #include “stdio.h”

      FILE popen( const char command, const char* mode )

      参数说明:

      command: 是一个指向以 NULL 结束的 shell 命令字符串的指针。这行命令将被传到 bin/sh 并使用 -c 标志,shell 将执行这个命令。

      mode: 只能是读或者写中的一种,得到的返回值(标准 I/O 流)也具有和 type 相应的只读或只写类型。如果 type 是 “r” 则文件指针连接到 command 的标准输出;如果 type 是 “w” 则文件指针连接到 command 的标准输入。

      返回值:

      如果调用成功,则返回一个读或者打开文件的指针,如果失败,返回NULL,具体错误要根据errno判断

      int pclose (FILE* stream)

      参数说明:

      stream:popen返回的文件指针

      返回值:

      如果调用失败,返回 -1

      作用:

      popen() 函数用于创建一个管道:其内部实现为调用 fork 产生一个子进程,执行一个 shell 以运行命令来开启一个进程这个进程必须由 pclose() 函数关闭。

      例子:

      管道读:先创建一个文件test,然后再test文件内写入“Read pipe successfully !”

      #include “stdio.h”

      #include “stdlib.h”

      int main()

      {

      FILE *fp;

      char buf[200] = {0};

      if((fp = popen(“cat test”, “r”)) == NULL) {

      perror(“Fail to popen ”);

      exit(1);

      }

      while(fgets(buf, 200, fp) != NULL) {

      printf(“%s”, buf);

      }

      pclose(fp);

      return 0;

      }

      打印输出: Read pipe successfully !

      管道读:

      #include “stdio.h”

      #include “stdlib.h”

      int main()

      {

      FILE *fp;

      char buf[200] = {0};

      if((fp = popen(“cat > test1″, “w”)) == NULL) {

      perror(“Fail to popen ”);

      exit(1);

      }

      fwrite(“Read pipe successfully !”, 1, sizeof(“Read pipe successfully !”), fp);

      pclose(fp);

      return 0;

      }

      执行完毕后,当前目录下多了一个test1文件,打开,里面内容为Read pipe successfully !

    popen()和pclose()

    如果你认为上面创建和使用管道的方法过于繁琐的话,你也可以使用下面的简单的方法:

    库函数:popen()和pclose();

    原型:FILEpopen(charcommand,char*type);

    返回值:如果成功,返回一个新的文件流。

    如果无法创建进程或者管道,返回NULL。

    此标准的库函数通过在系统内部调用pipe()来创建一个半双工的管道,然后它创建一个子进程,启动shell,最后在shell上执行command参数中的命令。管道中数据流的方向是由第二个参数type控制的。此参数可以是r或者w,分别代表读或写。但不能同时为读和写。在Linux系统下,管道将会以参数type中第一个字符代表的方式打开。所以,如果你在参数type中写入rw,管道将会以读的方式打开。
    
    虽然此库函数的用法很简单,但也有一些不利的地方。例如它失去了使用系统调用pipe()时可以有的对系统的控制。尽管这样,因为可以直接地使用shell命令,所以shell中的一些通配符和其他的一些扩展符号都可以在command参数中使用。
    

    使用popen()创建的管道必须使用pclose()关闭。其实,popen/pclose和标准文件输入/输出流中的fopen()/fclose()十分相似。

    库函数:pclose();

    原型:intpclose(FILE*stream);

    返回值:返回系统调用wait4()的状态。

    如果stream无效,或者系统调用wait4()失败,则返回-1。

    注意此库函数等待管道进程运行结束,然后关闭文件流。库函数pclose()在使用popen()创建的进程上执行wait4()函数。当它返回时,它将破坏管道和文件系统。
    
    在下面的例子中,用sort命令打开了一个管道,然后对一个字符数组排序:
    

    include<stdio.h>

    defineMAXSTRS5

    intmain(void)

    {

    intcntr;

    FILE*pipe_fp;

    char*strings[MAXSTRS]={"echo","bravo","alpha",

    "charlie","delta"};

    /Createonewaypipelinewithcalltopopen()/

    if((pipe_fp=popen("sort","w"))==NULL)

    {

    perror("popen");

    exit(1);

    }

    /Processingloop/

    for(cntr=0;cntr<MAXSTRS;cntr++){

    fputs(strings[cntr],pipe_fp);

    fputc(' ',pipe_fp);

    }

    /Closethepipe/

    pclose(pipe_fp);

    return(0);

    }

    因为popen()使用shell执行命令,所以所有的shell扩展符和通配符都可以使用。此外,它还可以和popen()一起使用重定向和输出管道函数。再看下面的例子:

    popen("ls~scottb","r");

    popen("sort>/tmp/foo","w");

    popen("sort|uniq|more","w");

    下面的程序是另一个使用popen()的例子,它打开两个管道(一个用于ls命令,另一个用于

    sort命令):

    include<stdio.h>

    intmain(void)

    {

    FILEpipein_fp,pipeout_fp;

    charreadbuf[80];

    /Createonewaypipelinewithcalltopopen()/

    if((pipein_fp=popen("ls","r"))==NULL)

    {

    perror("popen");

    exit(1);

    }

    /Createonewaypipelinewithcalltopopen()/

    if((pipeout_fp=popen("sort","w"))==NULL)

    {

    perror("popen");

    exit(1);

    }

    /Processingloop/

    while(fgets(readbuf,80,pipein_fp))

    fputs(readbuf,pipeout_fp);

    /Closethepipes/

    pclose(pipein_fp);

    pclose(pipeout_fp);

    return(0);

    }

    最后,我们再看一个使用popen()的例子。此程序用于创建一个命令和文件之间的管道:

    include<stdio.h>

    intmain(intargc,char*argv[])

    {

    FILEpipe_fp,infile;

    charreadbuf[80];

    if(argc!=3){

    fprintf(stderr,"USAGE:popen3[command][filename] ");

    exit(1);

    }

    /Open up input file/

    if((infile=fopen(argv[2],"rt"))==NULL)

    {

    perror("fopen");

    exit(1);

    }

    /Create one way pipe line with call topopen()/

    if((pipe_fp=popen(argv[1],"w"))==NULL)

    {

    perror("popen");

    exit(1);

    }

    /Processingloop/

    do{

    fgets(readbuf,80,infile);

    if(feof(infile))break;

    fputs(readbuf,pipe_fp);

    }while(!feof(infile));

    fclose(infile);

    pclose(pipe_fp);

    return(0);

    }

    下面是使用此程序的例子:

    popen3sortpopen3.c

    popen3catpopen3.c

    popen3morepopen3.c

    popen3catpopen3.c|grepmain

  • 相关阅读:
    【反射】Java反射机制
    Composer教程之常用命令
    Composer教程之基础用法
    Composer教程之初识Composer
    Composer 的结构详解
    现代 PHP 新特性系列(七) —— 内置的 HTTP 服务器
    现代 PHP 新特性系列(一) —— 命名空间
    现代 PHP 新特性系列(二) —— 善用接口
    现代 PHP 新特性系列(三) —— Trait 概览
    现代 PHP 新特性系列(四) —— 生成器的创建和使用
  • 原文地址:https://www.cnblogs.com/zzb-Dream-90Time/p/7326870.html
Copyright © 2011-2022 走看看