当前位置: 首页 > 科技观察

Go语言执行命令的几种方式

时间:2023-03-12 01:38:51 科技观察

Go语言是用来执行一个系统命令的,相对于python来说有点复杂。执行命令是很常见的需求,比如调用系统命令,启动exe等,这里分几种情况,后面会总结。只执行命令,不输出结果执行命令,得到输出结果阻塞和异步执行下面以pingwww.baidu.com为例依次执行各种命令,主要使用标准库中的os/exec.在执行命令时,我们主要使用os/exec包拥有者的Cmd结构方法。Cmd结构定义如下Cmd结构定义[1]。主要参数是Pathstring//Args,存放命令的参数,包括命令名作为第一个参数;如果是空切片或nil,则相当于一个没有参数的命令。////在典型用法中,Path和Args都应由Command函数设置。args[]string//env指定进程的环境,如果为nil,则在当前进程的环境中执行。Stdinio.Reader//Stdout和Stderr指定进程的标准输出和标准错误输出。////如果有一个为nil,Run方法会将相应的文件描述符关联到null设备(os.DevNull)////如果两个字段相同,最多一个线程可以同时写入.Stdoutio.WriterStderrio.Writer但是我们一般不会直接构造Cmd结构体,而是通过exec.Command()函数返回一个Cmd结构体指针,比如exec.Command("ping","www.baidu.com")ping是一个命令,“www.baidu.com”是参数,然后在得到*Cmd后使用构造方法Run、Start等方法真正执行命令。只执行命令,不输出结果。这里的输出只是说明命令被执行了,但我们并不关心它的具体输出。在这种情况下,它是相当实用的。我们只想执行命令。在python中,我们可以使用os.system()函数来执行,当然这是阻塞执行。>>>importos>>>r=os.system("pingwww.baidu.com")是Pingwww.a.shifen.com[39.156.66.18]with32bytesofdata:Replyfrom39.156.66.18:bytes=32time=6msTTL=54来自39.156.66.18的回复:字节=32时间=28msTTL=54来自39.156.66.18的回复:字节=32时间=6msTTL=54来自39.156.66.18的回复:字节=32Ping统计时间=7msTTL=5439.156.66.18:Packets:Sent=4,Received=4,Lost=0(0%lost),估计往返时间以毫秒为单位:最小=6ms,最长=28ms,平均=11ms>>>r0这里的r是只是为了获取命令的执行结果,0表示没有错误,但是执行命令的输出是Pingwww.a.shifen.com.....我们不管。您可以使用Run()或Start()方法来执行命令。run是阻塞执行,start()是非阻塞执行。该程序在退出之前只暂停了一会儿,什么也不输出。如果换成command.Start(),程序运行后会立即停止。如果想像python一样获取os.system的执行结果,其实这里的结果应该是ExitError,程序的退出码,应该怎么做呢?exec包中有一个特殊的结构体ExitError,使用它的一些方法可以得到ExitCode,但是如果要得到ExitCode是为了得到命令的结束,也就是要阻塞的操作,使用Run()方法阻塞并等待执行结果。使用Start()方法后,还可以使用Wait()方法等待执行完成。通过command.ProcessState.Sys().(syscall.WaitStatus).ExitCode获取命令执行的退出码。执行命令,得到输出结果。这里的输出结果是命令行的标准输出或错误输出,即stdout或stderr,存放在bytes.Buffer中。这里得到的中文输出有乱码:这个我查过,一般是设置控制台输出chcp或者使用:golang.org/x/text/encoding/simplifiedchinese这个包用来转换。我不想用它。我稍后会找到这个。说说方法吧。命令行的输入有时会进入命令行等待用户交互,比如输入nslookup。像上面的ping命令一样执行不在环境变量中的命令,因为在windows或者linux中,这个命令是在环境变量中的,但是像windows中的copy命令,是不在环境变量中的,一般情况下可以在cmd中使用go语言中的copy命令,但是在go语言中直接如上使用是不行的。例如,使用上面的代码,替换复制命令。得到的输出是:runerror:exec:"copy":executablefilenotfoundin%PATH%shouldusecmd","/C"复制命令: