go語(yǔ)言調(diào)用外部程序,并獲取外部程序的返回值。
例子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
運(yùn)行結(jié)果
$ go build && ./main
Return OK
例子2:程序返回非零
$ cat test.sh
#!/bin/bash
echo "Hello"
exit 2
運(yùn)行結(jié)果
$ go build && ./main
Return error: exit status 2
這里我們看到com.Run()的返回成功還是失敗的區(qū)分是子程序返回值是否為零,其實(shí)在這個(gè)例子中子程序test.sh執(zhí)行是正確的,返回2是希望的行為,但是com.Run()把它定義為錯(cuò)誤,go就這么設(shè)計(jì)的,那就沒(méi)有辦法了,需要注意一下就行了。
例子3:區(qū)分正常的程序返回值,還是異常錯(cuò)誤
例如子程序test.sh不存在,或者test.sh不可執(zhí)行:
$ ./main
Return error: exec: "test.sh": executable file not found in $PATH
或者test.sh 收到異常信號(hào)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")
}
}
場(chǎng)景1: 正常退出0
$ cat test.sh
#!/bin/bash
echo "Hello"
exit 0
$ ./main
Return OK
子程序正常運(yùn)行結(jié)束,并返回0值。
場(chǎng)景2: 正常退出100
$ cat test.sh
#!/bin/bash
echo "Hello"
exit 100
$ ./main
Return exit error: exit code=100
子程序正常運(yùn)行結(jié)束,并返回100值。
場(chǎng)景3:test.sh不存在或者不可執(zhí)行
$ chmod -x test.sh
$ ./main
Return other error: exec: "test.sh": executable file not found in $PATH
子程序無(wú)法運(yùn)行,我們得到的是其他類型的錯(cuò)誤,而不是exec.ExitError類型錯(cuò)誤。
場(chǎng)景4: test.sh 運(yùn)行中被kill -9
$ cat test.sh
#!/bin/bash
echo "Hello"
sleep 100
exit 100
$ ./main
Return exit error: signal code=9
返回exec.ExitError類型錯(cuò)誤,我們拿到signal值為9
注意在另一個(gè)Terminal中kill掉test.sh
$ kill -9 PID_OF_test.sh