2016-09-06 11 views
1

go execコマンドを実行すると、なぜかわからないのですか?
囲碁コード:コードでのショーなどgolang exec()はスタックしていますが、Run()は正常です

func main() { 
    cmd := exec.Command("/bin/bash", "test.sh") 
    _, err := cmd.Output() 
    //err := cmd.Run() 
    if err != nil { 
      fmt.Println(err) 
    } else { 
      fmt.Println("out") 
    } 
} 

に、ファイル名を指定して実行(使用する場合)、それはOKです。

test.sh:実行常に、それが終了したことがない

#!/bin/bash 
while true 
do 
    echo hello >> test.txt 
    sleep 30 
done 

#!/bin/bash 
./sleep.sh & 

それがバックグラウンドでsleep.sh

sleep.shを実行し、別のシェルスクリプトを呼び出しますバックグラウンドで

実際にはstdoutには何も出力されませんが、Output()はStuck、Run()はうまくいくことがわかります。 Go show Output()のソースコードはRun()を呼び出します。なぜ?

プログラムが立ち往生し、いくつかのGDB情報:

(gdb) info goroutines 
    1 waiting runtime.gopark 
    2 waiting runtime.gopark 
    3 waiting runtime.gopark 
    4 waiting runtime.gopark 
* 5 syscall syscall.Syscall 

(gdb) goroutine 5 bt 
#0 syscall.Syscall() at /usr/local/go/src/syscall/asm_linux_amd64.s:19 
#1 0x00000000004acf2f in syscall.read (fd=4, p= []uint8 = {...}, n=4254696, err=...) at /usr/local/go/src/syscall/zsyscall_linux_amd64.go:783 
#2 0x00000000004ac73d in syscall.Read (fd=4, p= []uint8 = {...}, n=859530501352, err=...) at /usr/local/go/src/syscall/syscall_unix.go:160 
#3 0x0000000000487703 in os.(*File).read (f=0xc82002c030, b= []uint8 = {...}, n=859530919936, err=...) at /usr/local/go/src/os/file_unix.go:211 
#4 0x0000000000484f3a in os.(*File).Read (f=0xc82002c030, b= []uint8 = {...}, n=0, err=...) at /usr/local/go/src/os/file.go:95 
#5 0x00000000004a5c6f in bytes.(*Buffer).ReadFrom (b=0xc8200140e0, r=..., n=0, err=...) at /usr/local/go/src/bytes/buffer.go:173 
#6 0x0000000000482160 in io.copyBuffer (dst=..., src=..., buf= []uint8, written=0, err=...) at /usr/local/go/src/io/io.go:375 
#7 0x0000000000481fa4 in io.Copy (dst=..., src=..., written=0, err=...) at /usr/local/go/src/io/io.go:351 
#8 0x000000000047262b in os/exec.(*Cmd).writerDescriptor.func1 (~r0=...) at /usr/local/go/src/os/exec/exec.go:232 
#9 0x00000000004726cd in os/exec.(*Cmd).Start.func1 (c=0xc820088000, fn={void (error *)} 0xc820029fb8) at /usr/local/go/src/os/exec/exec.go:340 
#10 0x0000000000456241 in runtime.goexit() at /usr/local/go/src/runtime/asm_amd64.s:1721 
#11 0x000000c820088000 in ??() 
#12 0x000000c82000c140 in ??() 
#13 0x0000000000000000 in ??() 
+0

私はmacとgoバージョンを使用しています1.6です。私はあなたのコードを実行し、すべては正常です..... –

+0

これはGolangの問題ですか?私はUbuntuを使用しています。14.04 LTS – tsjsdbd

+0

ラップトップでこのエラーを再現できないため、わかりません。 –

答えて

1

あなたが見ていることは正常な動作ですが、それは少し珍しいです。何が起こるかはあなたのプログラムのfork/bin/bashであり、これはforkを実行するtest.shをフォークします。これで、実行したコマンドのstdout、つまりtest.shがforkされた/ bin/bashが返されたことを意味するOutputを待っています。

なぜ、これはcmd.Runを呼び出すだけで違うのですか?あなたのプログラムは/ bin/bashをフォークするので、test.shをフォークして返します。あなたのプログラムはプログラムの出力を読むのを待っているわけではなく、すぐに戻る/ bin/bashの終了ステータスを探しているだけです。ここで

は、いくつかの演習です:

  1. cmd.StdoutPipe
  2. がcmd.StdoutPipe(で待機している間の行動の変化を観察使用するようにコードサンプルを変更します)(読む)(io.EOFを返します。 ioutils.ReadAllはここで便利です)、もう一つのgoroutineはcmd.Run()を待っています。あなたのメインのゴルーチンが、パイプからのもう一方の読書が終了するまで、終了させないようにしてください。
+0

あなたはGoコードで見ることができますが、実行もWait()関数を呼び出すことができます。実行はOutputのような結果を待つ必要があります.func(c * Cmd)Run()エラー{ \t if err:= c.Start ); ERR!=ゼロ{ \t \t戻りERR \t} \tリターンc.Wait() は} ' – tsjsdbd

+0

は、/ binに/ bashのではなく、子プロセスの出力の結果を待つ@tsjsdbd。 – pltvs

+0

なぜプログラムがクラッシュするのですか?私はこの質問についても非常に興味深いです... –

関連する問題