2013-11-21 19 views
7

"psql"コマンドでエラーが発生し、stderrを読み込み、Goプログラムで印刷しようとしています。私はstderrとstdoutからデータを読み込むためにioutil.ReadAllを使います。stderrとioutil.ReadAllを使用してこのGoプログラムで "bad file descriptor"を取得するのはなぜですか

残念ながら、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

は私が実験を通して、私が原因私は

d := cmd.Wait() 

はそう何が起こることは、標準出力、標準エラー出力である

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

後に呼び出していたという事実に、エラーを取得していますということがわかりましたパイプはcmd.Wait()返却後に閉鎖されます。

は、ここで彼らが閉じて取得した後、我々はstdoutとstderrを読み取ることができないので、明らかに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

関連する問題