2012-04-30 17 views
33

os/exec http://golang.org/pkg/os/exec/パッケージを使用してオペレーティングシステムでコマンドを実行していますが、終了コードを取得する方法が見つからないようです。私は出力を読むことができます終了コードを取得する -

ie。

package main 

import(
    "os/exec" 
    "bytes" 
    "fmt" 
    "log" 
    ) 

func main() { 
    cmd := exec.Command("somecommand", "parameter") 
    var out bytes.Buffer 
    cmd.Stdout = &out 
    if err := cmd.Run() ; err != nil { 
     //log.Fatal(cmd.ProcessState.Success()) 
     log.Fatal(err) 
    } 
    fmt.Printf("%q\n", out.String()) 
} 

答えて

52

終了コードが0かどうかを判断するのは簡単です。最初のケースでは、cmd.Wait()はnilを返します(パイプの設定中に別のエラーがない限り)。

残念ながら、エラーケースで終了コードを取得するプラットフォームに依存しない方法はありません。これがAPIの一部ではない理由です。ただfollowtheapidocsがより:)

ここ
+1

私は文書を調べましたが、 'ProcessState'から' WaitStatus'に行く方法は決して見つけられませんでした。どうしましたか?また、メーリングリストで解決策を見つけました(これまで説明したようなものです)。https://groups.google.com/forum/?fromgroups#!searchin/golang-nuts/exit$20code/golang- nuts/dKbL1oOiCIY/Bz_haQYmMrcJ Windowsで今すぐ試してみましょう。 – OscarRyz

+0

終了コードを取得するのは簡単ではありませんが、次回に見なければならないヒントがいくつかあります。しかし、彼らはWindowsはまったく言及していないので、私はあなたの答えを楽しみにしています。 – tux21b

+0

メーリングリストにはWindows固有のことが書かれていますが、私はこのコードを実行して完全に動作しました。これはgo1上です。 – OscarRyz

8

私の拡張バージョンは、@ tux21bに基づいている見つけるために

package main 

import "os/exec" 
import "log" 
import "syscall" 

func main() { 
    cmd := exec.Command("git", "blub") 

    if err := cmd.Start(); err != nil { 
     log.Fatalf("cmd.Start: %v") 
    } 

    if err := cmd.Wait(); err != nil { 
     if exiterr, ok := err.(*exec.ExitError); ok { 
      // The program has exited with an exit code != 0 

      // This works on both Unix and Windows. Although package 
      // syscall is generally platform dependent, WaitStatus is 
      // defined for both Unix and Windows and in both cases has 
      // an ExitStatus() method with the same signature. 
      if status, ok := exiterr.Sys().(syscall.WaitStatus); ok { 
       log.Printf("Exit Status: %d", status.ExitStatus()) 
      } 
     } else { 
      log.Fatalf("cmd.Wait: %v", err) 
     } 
    } 
} 

を:次のコードは、Linuxで動作しますが、私は他のプラットフォーム上でそれをテストしていませんsが、私はそれをテストしている

utils/cmd.go

package utils 

import (
    "bytes" 
    "log" 
    "os/exec" 
    "syscall" 
) 

const defaultFailedCode = 1 

func RunCommand(name string, args ...string) (stdout string, stderr string, exitCode int) { 
    log.Println("run command:", name, args) 
    var outbuf, errbuf bytes.Buffer 
    cmd := exec.Command(name, args...) 
    cmd.Stdout = &outbuf 
    cmd.Stderr = &errbuf 

    err := cmd.Run() 
    stdout = outbuf.String() 
    stderr = errbuf.String() 

    if err != nil { 
     // try to get the exit code 
     if exitError, ok := err.(*exec.ExitError); ok { 
      ws := exitError.Sys().(syscall.WaitStatus) 
      exitCode = ws.ExitStatus() 
     } else { 
      // This will happen (in OSX) if `name` is not available in $PATH, 
      // in this situation, exit code could not be get, and stderr will be 
      // empty string very likely, so we use the default fail code, and format err 
      // to string and set to stderr 
      log.Printf("Could not get exit code for failed program: %v, %v", name, args) 
      exitCode = defaultFailedCode 
      if stderr == "" { 
       stderr = err.Error() 
      } 
     } 
    } else { 
     // success, exitCode should be 0 if go is ok 
     ws := cmd.ProcessState.Sys().(syscall.WaitStatus) 
     exitCode = ws.ExitStatus() 
    } 
    log.Printf("command result, stdout: %v, stderr: %v, exitCode: %v", stdout, stderr, exitCode) 
    return 
} 

に答えますOSX、それが他のプラットフォームでは期待どおりに動作しない場合は、私たちがそれをより良くできるように教えてください。

+0

Ubuntu 16.04 Linuxで動作し、exitCodeとともにstdoutを返します。ちょうど私が探していたものです... – MrMobileMan

+0

この機能が大好き – n0nag0n

関連する問題