2016-09-29 10 views
-1

を経由してシェルスクリプトを実行した後、私は以下のようになります(copy.sh命名)簡単なシェルスクリプトを持って戻ってエラーを取得: -はGolang

#! /bin/sh 

cp $1 $2 

私はchmod 777 copy.shをしました。

Iは、上記シェルコードを実行golangコードを持っている: -

package main 

import (
    "fmt" 
    "os/exec" 
) 

func main() { 
    _, err := exec.Command("/Users/debraj/copy.sh", "/Users/debraj/temp.txt", "/Users/debraj/gotest/").Output() 
    if err != nil { 
     fmt.Println("Failed to execute command " + err.Error()) 
     return 
    } 
    fmt.Printf("\nCopy Successful - %v") 
} 

上記のコードは以下の出力であること示している: -

jabongs-MacBook-Pro-4:src debraj$ go run copyerr.go 
Failed to execute command exit status 1 
jabongs-MacBook-Pro-4:src debraj$ 

しかし、私は、シェルスクリプトから受信エラー次のようになります: -

jabongs-MacBook-Pro-4:~ debraj$ ./copy.sh /Users/debraj/temp.txt /Users/debraj/gotest/ 
cp: /Users/debraj/gotest/temp.txt: Permission denied  

誰かが私にどのように同じエラーメッセージ帽子はシェルスクリプトによって返されますか?

Iドンの場合、tはchmod 777 copy.shを行うと、ファイルは以下のように権限を持っている: -

jabongs-MacBook-Pro-4:~ debraj$ ls -la copy.sh 
-rw-r--r-- 1 debraj staff 21 Sep 29 13:28 copy.sh 

シェルスクリプトによって与えられるように次にgolangコードが出力を提供します。なぜこれがこのように振る舞っているのかを教えてもらえますか?

私は

  • Golang 1.7
  • のMac OS X 10.11.4
+5

出力の代わりにCombinedOutputを使用しますか?あなたはstderrを無視しました。 – lofcek

答えて

2

Alrightyの午前!だから、その中核にある問題は、あなたがエラーを取得することができる2つの異なる場所を持っているということです。

  1. それはdoesnのためexec.Command()出力は、()(すべてであなたのシェルスクリプトを実行できない場合。
  2. シェルスクリプト自体は実行されますが、エラーコードが返されます(スクリプトで最後に実行された行はエラーなので)。最初のケースで

(すぐに失敗した)何かをしようとすると、移動自体が明確に定義されたシステムエラーを得たので、あなたはERRで、合理的な何かを得る必要があります。後者の場合、Goはスクリプトを実行することができましたが、出力(無視しています)と戻りコード(この場合、スクリプトによって最後に実行されたコードの終了コード)がありました。文字通り出力が何か(メガバイトとメガバイトのナンセンステキストを含む)だった可能性があるので、Goは怠惰な方法で状態コードを返します。基本的にみんながスタンダードを乱用していることを考えると、これは、IMHOが正しいことです。

さらに、スクリプト(少し修正した場合)はエラーメッセージを表示せずに実際にエラーコードを返すことができます。あなたのスクリプトから実際のエラー情報を確認したい場合は、言っ

、次のいずれかの操作を行います。

// Display everything we got if error. 
output, err := exec.Command(...).CombinedOutput() 
if err != nil { 
    fmt.Println("Error when running command. Output:") 
    fmt.Println(string(output)) 
    fmt.Printf("Got command status: %s\n", err.Error()) 
    return 
} 

か:

// Display just the stderr if an error occurs 
cmd := exec.Command(...) 
stderr := &bytes.Buffer{} // make sure to import bytes 
cmd.Stderr = stderr 
err := cmd.Run() 
if err != nil { 
    fmt.Println("Error when running command. Error log:") 
    fmt.Println(stderr.String()) 
    fmt.Printf("Got command status: %s\n", err.Error()) 
    return 
} 

を...またはあなたが好きになり、StderrPipe()を使用し、最後の行または同様のものを読むことができます。実際、cmd.Stderrはio.Writerになる可能性があるので、この特定の猫をスキンケアする方法はたくさんあります。根本的な原因を探しているストリームを解析するものを含め、ほとんどあらゆるハンドラを簡単に書くことができます。

使用するOutput()とCombinedOutput()は、スクリプトが完全に実行されたときにのみ表示されるということです。これは、何が起こっているのかを監視しているユーザーは、処理が行われている間は何も起こらず、大きな負荷がかかることを意味するため、長時間実行されるスクリプトでは重大なUIの問題になる可能性があります。 StdoutPipe()とStderrPipe()を使用する方が望ましいでしょう。出力を解析/解釈(または表示)することができます。もちろん、スクリプトが数秒以上実行されないことや、人間が監視しないことを保証できれば、誰が気にしますか?

スクリプトの実行時に出力を表示する方法を調べる場合は、StdoutPipe()の例を参考にしてください。

+0

このような良い説明をありがとう。 – tuk