Spawning Processe 生成进程
有时需要生成非go程序的其他进程。例如,网站上语法高亮是通过从Go程序中生成pygmentize进程来实现的。让我们来看看在Go中生成进程的几个例子。
从一个简单的命令开始,这个命令不需要参数或输入数据,只需要打印信息到标准输出。exec.Command辅助函数创建一个命令对象来表示这个外部进程。Output是另一个辅助函数,它处理命令的常见情况,如运行命令、等待命令完成并收集命令的输出等。检查是否发生错误,如果没有错误,dateOut是保存了日期信息的字节流数据。
接下来,我们将研究一个稍微复杂的情况,即将数据传输到外部进程的stdin标准输入管道上,并从其stdout标准输出管道上收集结果。在这里,显式获取命令的输入/输出管道,启动进程,向标准输入管道写入一些数据后关闭标准输入,然后从标准输出管道中读取结果字节流,最后等待进程退出。
我们在上面的例子中省略了错误检查,但是你可以像使用通常的条件测试那样检查是否发生错误err != nil。
我们只收集了进程标准输出管道的结果,但也可以用同样的方法收集进程的标准错误输出的信息。
注意,在生成命令进程时,我们需要分开提供命令和参数数组,而不能只传递一个命令行字符串。如果您想用一个字符串生成完整的命令,则可以使用bash的-c选项:生成的命令进程产生的结果与直接在命令行运行它们得到的结果是一样的。
![1e039c501fa6fcc239ee1677af006f02.png](https://img-blog.csdnimg.cn/img_convert/1e039c501fa6fcc239ee1677af006f02.png)
结果:
$ go run spawning-processes.go
> date
Wed Oct 10 09:53:11 PDT 2012
> grep hello
hello grep
> ls -a -l -h
drwxr-xr-x 4 mark 136B Oct 3 16:29 .
drwxr-xr-x 91 mark 3.0K Oct 3 12:50 ..
-rw-r--r-- 1 mark 1.3K Oct 3 16:28 spawning-processes.go
Exec'ing Processe 替换进程
在前面的例子中,我们研究了如何在Go程序中生成外部进程。这样做,是因为我们需要在运行Go进程的过程中访问一个外部进程。但是,有时想用另一个(也许是非Go程序)进程完全替换当前的Go进程。要达到这一目的,使用经典函数exce的Go实现。
在下面的示例中,我们将执行ls命令,Go需要它的二进制文件的绝对路径,因此我们将使用exec.LookPath来查找(可能是/bin/ls)。Exec需要切片形式的参数(与一长串字符串相反)。例子中给ls一些常见的参数,注意,第一个参数应该是程序名。Exec还需要一组环境变量才能使用,获取当前环境。
所有准备工作完毕,调用函数syscall.Exec。如果此调用成功,则Go进程的执行将在此处结束,并被命令为/bin/ls -a-l-h的进程替换。如果有错误,我们将得到一个返回值继续执行原Go进程。
当我们运行程序时,Go程序将被ls命令替换了。请注意,Go不提供Unix经典的fork函数。不过,通常这不是问题,因为启动协程、生成进程和替换进程涵盖了fork的大多数用例。
![75aedf4a4029ec52da4df0f55e8eafd6.png](https://img-blog.csdnimg.cn/img_convert/75aedf4a4029ec52da4df0f55e8eafd6.png)
结果:
$ go run execing-processes.go
total 16
drwxr-xr-x 4 mark 136B Oct 3 16:29 .
drwxr-xr-x 91 mark 3.0K Oct 3 12:50 ..
-rw-r--r-- 1 mark 1.3K Oct 3 16:28 execing-processes.go