1. 程式人生 > >從Linux程式中執行shell(程式、指令碼)並獲得輸出結果(轉)

從Linux程式中執行shell(程式、指令碼)並獲得輸出結果(轉)

1. 前言
2. 使用臨時檔案
3. 使用匿名管道
4. 使用popen
5. 小結

1. 前言

Unix界有一句名言:“一行shell指令碼勝過萬行C程式”,雖然這句話有些誇張,但不可否認的是,藉助指令碼確實能夠極大的簡化一些程式設計工作。比如實現一個ping程式來測試網路的連通性,實現ping函式需要寫上200~300行程式碼,為什麼不能直接呼叫系統的ping命令呢?通常在程式中通過 system函式來呼叫shell命令。但是,system函式僅返回命令是否執行成功,而我們可能需要獲得shell命令在控制檯上輸出的結果。例如,執行外部命令ping後,如果執行失敗,我們希望得到ping的返回資訊。

2. 使用臨時檔案

首先想到的方法就是將命令輸出重定向到一個臨時檔案,在我們的應用程式中讀取這個臨時檔案,獲得外部命令執行結果,程式碼如下所示:

複製程式碼

      
       #define
        CMD_STR_LEN 1024
        
       int
        mysystem(
       char
       *
        cmdstring, 
       char
       *
        tmpfile) { 
char cmd_string[CMD_STR_LEN]; tmpnam(tmpfile); sprintf(cmd_string, " %s > %s " , cmdstring, tmpfile); return system(cmd_string); } 複製程式碼 這種使用使用了臨時檔案作為應用程式和外部命令之間的聯絡橋樑,在應用程式中需要讀取檔案,然後再刪除該臨時檔案,比較繁瑣,優點是實現簡單,容易理解。有沒有不借助臨時檔案的方法呢?

3. 使用匿名管道

在<<UNIX環境高階程式設計>>一書中給出了一種通過匿名管道方式將程式結果輸出到分頁程式的例子,因此想到,我們也可以通過管道來將外部命令的結果同應用程式連線起來。方法就是fork一個子程序,並建立一個匿名管道,在子程序中執行shell命令,並將其標準輸出dup 到匿名管道的輸入端,父程序從管道中讀取,即可獲得shell命令的輸出,程式碼如下:

  int mysystem(char* cmdstring, char* buf, int len)
  {
  int  fd[2];
  pid_t pid;
  int  n, count; 
  memset(buf, 0, len);
  if (pipe(fd) < 0)
  return -1;
  if ((pid = fork()) < 0)
  return -1;
  else if (pid > 0)