2013-11-21 8 views
7

Der Befehl "psql" sollte einen Fehler werfen, und ich versuche stderr zu lesen und es im Go-Programm zu drucken. Ich benutze ioutil.ReadAll, um die Daten von stderr und stdout zu lesen.Warum bekomme ich "bid file descriptor" in diesem Go-Programm mit stderr und ioutil.ReadAll

Leider liest es überhaupt nicht von stderr. ioutil.ReadAll gibt einen Fehler zurück, der nicht der Fehler ist, den ich erwarte.

Der Fehler, den ich bekommen ist

read |0: bad file descriptor 

Hier ist der Code.

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) 
} 

Antwort

10

fand ich, dass durch Experimente, dass ich die Störung erhalte, aufgrund der Tatsache, dass ich

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

nach

d := cmd.Wait() 

so nenne, was passiert, ist die stdout, stderr Rohr wird geschlossen, nachdem die cmd.Wait() zurückkehrt.

Hier sind die Code-Kommentare für das 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. 

So offensichtlich können wir nicht stdout und stderr lesen, nachdem sie geschlossen erhalten.

Wir können sie nicht lesen, bevor der Befehl startet. Also müssen wir sie zwischen Start und Wartezeit setzen.

Hier ist Code, der das behebt.

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

Beachten Sie, dass es im Allgemeinen eine gute Idee ist, sofort mit Fehlern umzugehen. Wenn in Ihrem Beispiel "ioutil.ReadAll (stdout)" fehlschlägt, werden "ioutil.ReadAll (stderr)" und "cmd.Wait()" aufgerufen, bevor der Fehler behandelt wird. –

+0

Ja, das stimmt. – ppone

Verwandte Themen