2013-11-21 35 views
7

在此Go程序中得到「壞文件描述符」命令「psql」應該會引發錯誤,並且我正在嘗試讀取stderr並將其打印到Go程序中。我使用ioutil.ReadAll從stderr和stdout中讀取數據。爲什麼我使用stderr和ioutil.ReadAll

不幸的是,它根本不是從stderr中讀取的。 ioutil.ReadAll返回一個錯誤,這不是我期待的錯誤。

我得到的錯誤是

read |0: bad file descriptor 

這裏是代碼。

package main 

import (
     "fmt" 
     "os/exec" 
     "io/ioutil" 
) 

func main() { 
     cmd := exec.Command("psql") 
     stdout, err := cmd.StdoutPipe() 
     if err != nil { 
       fmt.Printf("Error: %s", err) 
     } 
     stderr, err := cmd.StderrPipe() 
     if err != nil { 
       fmt.Printf("Error: %s", err) 
     } 
     err = cmd.Start() 
     if err != nil { 
       fmt.Printf("Start error %s",err) 
     } 

     d := cmd.Wait() 
     if d != nil { 
       fmt.Println(d) 
     } 

     stdo,g := ioutil.ReadAll(stdout) 
     stde,f := ioutil.ReadAll(stderr) 

     if g != nil { 
       fmt.Println(g) 
     } 

     if f !=nil { 
       fmt.Println(f) 
     } 

     fmt.Printf("Standard err is %s \n", stde) 
     fmt.Printf("Standard out is %s \n",stdo) 
} 

回答

10

我發現,通過實驗,我得到的錯誤,因爲這樣的事實,我打電話

stdo,g := ioutil.ReadAll(stdout) 
    stde,f := ioutil.ReadAll(stderr) 

d := cmd.Wait() 

所以會發生什麼是標準輸出,標準錯誤在cmd.Wait()返回後,管道關閉。

這裏是爲cmd.StderrPipe()

// StderrPipe returns a pipe that will be connected to the command's 
// standard error when the command starts. 
// The pipe will be closed automatically after Wait sees the command exit. 

代碼註釋所以,很顯然,我們無法讀取輸出和錯誤,他們得到關閉後。

在命令啓動之前,我們無法讀取它們。所以我們必須把它們放在開始和等待之間。

下面是修復該問題的代碼。

package main 

import (
     "fmt" 
     "os/exec" 
     "io/ioutil" 
) 

func main() { 
     cmd := exec.Command("psql") 
     stdout, err := cmd.StdoutPipe() 
     if err != nil { 
       fmt.Printf("Error: %s", err) 
     } 
     stderr, err := cmd.StderrPipe() 
     if err != nil { 
       fmt.Printf("Error: %s", err) 
     } 
     err = cmd.Start() 
     if err != nil { 
       fmt.Printf("Start error %s",err) 
     } 

     stdo,g := ioutil.ReadAll(stdout) 
     stde,f := ioutil.ReadAll(stderr) 

     d := cmd.Wait() 

     if d != nil { 
       fmt.Println(d) 
     } 

     if g != nil { 
       fmt.Println(g) 
     } 

     if f !=nil { 
       fmt.Println(f) 
     } 

     fmt.Printf("Standard err is %s \n", stde) 
     fmt.Printf("Standard out is %s \n",stdo) 
} 
+0

請注意,立即處理錯誤通常是一個好主意。在你的例子中,如果'ioutil.ReadAll(stdout)'失敗,在處理錯誤之前調用'ioutil.ReadAll(stderr)'和'cmd.Wait()'。 –

+0

是的,的確如此。 – ppone

相關問題