Goでシェルコマンドを実行し、プログラムで文字列として結果の出力を取得しようとしています。 Rosetta Code バージョンを見ました:
package main
import "fmt"
import "exec"
func main() {
cmd, err := exec.Run("/bin/ls", []string{"/bin/ls"}, []string{}, "", exec.DevNull, exec.PassThrough, exec.PassThrough)
if (err != nil) {
fmt.Println(err)
return
}
cmd.Close()
しかし、これは実際の標準出力をキャプチャしたり、プログラムでアクセスできる方法でエラーを出したりすることはありません。それらは通常のstdout/stderrに引き続き出力されます。 Pipeをoutまたはerrとして使用すると他の場所で役立つことがわかりましたが、その方法の例はありません。何か案は?
この回答は、Go標準ライブラリの現在の状態を表すものではありません。最新の方法については、 @ Lourenco's answer をご覧ください!
あなたの例は、実際には標準出力からデータを読み取りません。これは私のために働く。
package main
import (
"fmt"
"exec"
"os"
"bytes"
"io"
)
func main() {
app := "/bin/ls"
cmd, err := exec.Run(app, []string{app, "-l"}, nil, "", exec.DevNull, exec.Pipe, exec.Pipe)
if (err != nil) {
fmt.Fprintln(os.Stderr, err.String())
return
}
var b bytes.Buffer
io.Copy(&b, cmd.Stdout)
fmt.Println(b.String())
cmd.Close()
}
パッケージ「exec」は 変更済み 少しでした。次の code は私のために働いた。
package main
import "os/exec"
func main() {
app := "echo"
//app := "buah"
arg0 := "-e"
arg1 := "Hello world"
arg2 := "\n\tfrom"
arg3 := "golang"
cmd := exec.Command(app, arg0, arg1, arg2, arg3)
stdout, err := cmd.Output()
if err != nil {
println(err.Error())
return
}
print(string(stdout))
}
これがお役に立てば幸いです!
提供された回答ではstdout
とstderr
を分離することはできないため、別の回答を試みます。
exec.Cmd
パッケージのos/exec
タイプのドキュメントを見ると、まず必要な情報をすべて入手できます。ここを見てください: https://golang.org/pkg/os/exec/#Cmd
特に、メンバーStdin
およびStdout
、Stderr
では、io.Reader
を使用して、新しく作成されたプロセスのstdin
とio.Writer
は、コマンドのstdout
とstderr
を使用するために使用できます。
次のプログラムのShellout
関数はコマンドを実行し、その出力とエラー出力を文字列として分離して渡します。
package main
import (
"bytes"
"fmt"
"log"
"os/exec"
)
const ShellToUse = "bash"
func Shellout(command string) (error, string, string) {
var stdout bytes.Buffer
var stderr bytes.Buffer
cmd := exec.Command(ShellToUse, "-c", command)
cmd.Stdout = &stdout
cmd.Stderr = &stderr
err := cmd.Run()
return err, stdout.String(), stderr.String()
}
func main() {
err, out, errout := Shellout("ls -ltr")
if err != nil {
log.Printf("error: %v\n", err)
}
fmt.Println("--- stdout ---")
fmt.Println(out)
fmt.Println("--- stderr ---")
fmt.Println(errout)
}
// 封装exec ,有Shell= true 这样的选项
func Cmd(cmd string, Shell bool) []byte {
if Shell {
out, err := exec.Command("bash", "-c", cmd).Output()
if err != nil {
panic("some error found")
}
return out
} else {
out, err := exec.Command(cmd).Output()
if err != nil {
panic("some error found")
}
return out
}
}
これを試すことができます。
コマンドを実行し、エラー、stdout、およびstderrをキャプチャして検査する単純な関数を次に示します。問題が発生したり、報告されたりする可能性のあるものは簡単に確認できます。
// RunCMD is a simple wrapper around terminal commands
func RunCMD(path string, args []string, debug bool) (out string, err error) {
cmd := exec.Command(path, args...)
var b []byte
b, err = cmd.CombinedOutput()
out = string(b)
if debug {
fmt.Println(strings.Join(cmd.Args[:], " "))
if err != nil {
fmt.Println("RunCMD ERROR")
fmt.Println(out)
}
}
return
}
次のように使用できます(メディアファイルの変換):
args := []string{"-y", "-i", "movie.mp4", "movie_audio.mp3", "INVALID-ARG!"}
output, err := RunCMD("ffmpeg", args, true)
if err != nil {
fmt.Println("Error:", output)
} else {
fmt.Println("Result:", output)
}
Go 1.2-1.7でこれを使用しました