Go语言调用Shell与可执行文件的实现
os/exec包可用于调用外部命令,可以使用管道连接输入输出,并支持阻塞与非阻塞方式执行命令。
os/exec包中关键的类型为Cmd,以下介绍的所有方法皆服务于该类型:
funcCommand(namestring,arg...string)*Cmd
方法返回一个*Cmd,用于执行name指定的程序(携带arg参数)
func(c*Cmd)Run()error
执行Cmd中包含的命令,阻塞直到命令执行完成
func(c*Cmd)Start()error
执行Cmd中包含的命令,该方法立即返回,并不等待命令执行完成
func(c*Cmd)Wait()error
该方法会阻塞直到Cmd中的命令执行完成,但该命令必须是被Start方法开始执行的
func(c*Cmd)Output()([]byte,error)
执行Cmd中包含的命令,并返回标准输出的切片
func(c*Cmd)CombinedOutput()([]byte,error)
执行Cmd中包含的命令,并返回标准输出与标准错误合并后的切片
func(c*Cmd)StdinPipe()(io.WriteCloser,error)
返回一个管道,该管道会在Cmd中的命令被启动后连接到其标准输入
func(c*Cmd)StdoutPipe()(io.ReadCloser,error)
返回一个管道,该管道会在Cmd中的命令被启动后连接到其标准输出
func(c*Cmd)StderrPipe()(io.ReadCloser,error)
返回一个管道,该管道会在Cmd中的命令被启动后连接到其标准错误
普通调用示例:
调用Shell命令或可执行文件
演示在当前目录创建一个空文件
packagemain import( "fmt" "os/exec" ) funcmain(){ cmd:=exec.Command("touch","test_file") err:=cmd.Run() iferr!=nil{ fmt.Println("ExecuteCommandfailed:"+err.Error()) return } fmt.Println("ExecuteCommandfinished.") }
一般不建议使用这种默认方式调用Shell脚本:
cmd:=exec.Command("my_shell.sh")
因为这种方式实际的执行结果和命令行执行#shmy_shell.sh一样,如果你的Shell脚本不满足sh的规范,就会调用失败。
调用Shell脚本
设置bash来调用指定Shell脚本,dir_size.sh为我们测试用的Shell脚本。调用完成后打印Shell脚本的标准输出到控制台。
packagemain import( "fmt" "os/exec" ) funcmain(){ command:=`./dir_size.sh.` cmd:=exec.Command("/bin/bash","-c",command) output,err:=cmd.Output() iferr!=nil{ fmt.Printf("ExecuteShell:%sfailedwitherror:%s",command,err.Error()) return } fmt.Printf("ExecuteShell:%sfinishedwithoutput:\n%s",command,string(output)) }
dir_size.sh示例文件内容如下,用于输出当前目录的大小:
#!/bin/bash du-h--max-depth=1$1
Go程序运行结果:
[root@localhostopt]#ll total2120 -rwx------.1rootroot36Jan2216:37dir_size.sh -rwx------.1rootroot2152467Jan2216:39execCommand drwxrwxr-x.11100010004096Jul122017kibana drwx------.2rootroot4096Jan1610:45sftpuser drwx------.3rootroot4096Jan2216:41upload [root@localhostopt]#./execCommand ExecuteShell:./dir_size.sh.finishedwithoutput: 4.0K./sftpuser 181M./kibana 1.1G./upload 1.2G.
使用输入输出Pipe
演示使用管道连接到grep命令的标准输入,过滤包含test的字符串,并使用管道连接标准输出,打印运行结果:
packagemain import( "fmt" "io/ioutil" "os/exec" ) funcmain(){ cmd:=exec.Command("/bin/bash","-c","greptest") stdin,_:=cmd.StdinPipe() stdout,_:=cmd.StdoutPipe() iferr:=cmd.Start();err!=nil{ fmt.Println("ExecutefailedwhenStart:"+err.Error()) return } stdin.Write([]byte("gotextforgrep\n")) stdin.Write([]byte("gotesttextforgrep\n")) stdin.Close() out_bytes,_:=ioutil.ReadAll(stdout) stdout.Close() iferr:=cmd.Wait();err!=nil{ fmt.Println("ExecutefailedwhenWait:"+err.Error()) return } fmt.Println("Executefinished:"+string(out_bytes)) }
Go程序运行结果:
[root@localhost~]#./execCommand
Executefinished:gotesttextforgrep
阻塞/非阻塞方式调用
文章开头方法介绍处已经介绍的很清楚,且前面示例都有涉及,就不另行说明了。
参考文档:
GoLang标准库文档
到此这篇关于Go语言调用Shell与可执行文件的实现的文章就介绍到这了,更多相关Go语言调用Shell内容请搜索毛票票以前的文章或继续浏览下面的相关文章希望大家以后多多支持毛票票!