go語言調用外部程序遭垛,并獲取外部程序的返回值晌纫。
例子1: 程序返回0
$ cat main.go
package main
import (
"fmt"
"os/exec"
)
func main() {
cmd := exec.Command("test.sh")
err := cmd.Run()
if err != nil {
fmt.Printf("Return error: %s\n", err)
} else {
fmt.Printf("Return OK\n")
}
}
$ cat test.sh
#!/bin/bash
echo "Hello"
exit 0
運行結果
$ go build && ./main
Return OK
例子2:程序返回非零
$ cat test.sh
#!/bin/bash
echo "Hello"
exit 2
運行結果
$ go build && ./main
Return error: exit status 2
這里我們看到com.Run()的返回成功還是失敗的區(qū)分是子程序返回值是否為零,其實在這個例子中子程序test.sh執(zhí)行是正確的罢艾,返回2是希望的行為抚恒,但是com.Run()把它定義為錯誤,go就這么設計的蛤奢,那就沒有辦法了,需要注意一下就行了陶贼。
例子3:區(qū)分正常的程序返回值啤贩,還是異常錯誤
例如子程序test.sh不存在,或者test.sh不可執(zhí)行:
$ ./main
Return error: exec: "test.sh": executable file not found in $PATH
或者test.sh 收到異常信號crash了拜秧。
$ ./main
Return error: signal: killed
改造后的main.go
package main
import (
"fmt"
"syscall"
"os/exec"
)
func main() {
cmd := exec.Command("test.sh")
err := cmd.Run();
if err != nil {
if exitErr, ok := err.(*exec.ExitError); ok {
status := exitErr.Sys().(syscall.WaitStatus)
switch {
case status.Exited():
fmt.Printf("Return exit error: exit code=%d\n", status.ExitStatus())
case status.Signaled():
fmt.Printf("Return exit error: signal code=%d\n", status.Signal())
}
} else {
fmt.Printf("Return other error: %s\n", err)
}
} else {
fmt.Printf("Return OK\n")
}
}
場景1: 正常退出0
$ cat test.sh
#!/bin/bash
echo "Hello"
exit 0
$ ./main
Return OK
子程序正常運行結束痹屹,并返回0值。
場景2: 正常退出100
$ cat test.sh
#!/bin/bash
echo "Hello"
exit 100
$ ./main
Return exit error: exit code=100
子程序正常運行結束枉氮,并返回100值志衍。
場景3:test.sh不存在或者不可執(zhí)行
$ chmod -x test.sh
$ ./main
Return other error: exec: "test.sh": executable file not found in $PATH
子程序無法運行暖庄,我們得到的是其他類型的錯誤,而不是exec.ExitError類型錯誤足画。
場景4: test.sh 運行中被kill -9
$ cat test.sh
#!/bin/bash
echo "Hello"
sleep 100
exit 100
$ ./main
Return exit error: signal code=9
返回exec.ExitError類型錯誤雄驹,我們拿到signal值為9
注意在另一個Terminal中kill掉test.sh
$ kill -9 PID_OF_test.sh