Linux下使用popen()執行shell命令

函數原型:shell

  #include 「stdio.h」數組

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

  參數說明:oop

  command: 是一個指向以 NULL 結束的 shell 命令字符串的指針。這行命令將被傳到 bin/sh 並使用 -c 標誌,shell 將執行這個命令。指針

  mode: 只能是讀或者寫中的一種,獲得的返回值(標準 I/O 流)也具備和 type 相應的只讀或只寫類型。若是 type 是 「r」 則文件指針鏈接到 command 的標準輸出;若是 type 是 「w」 則文件指針鏈接到 command 的標準輸入。code

  返回值:排序

  若是調用成功,則返回一個讀或者打開文件的指針,若是失敗,返回NULL,具體錯誤要根據errno判斷進程

  int pclose (FILE* stream)ip

  參數說明:字符串

  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\n」);

  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\n」);

  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('\n',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)

{

FILE*pipein_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[])

{

FILE*pipe_fp,*infile;

charreadbuf[80];

if(argc!=3){

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

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

相關文章
相關標籤/搜索