Go语言调用Shell与可执行文件的实现

os/exec包可用于调用外部命令,可以使用管道连接输入输出,并支持阻塞与非阻塞方式执行命令。

os/exec包中关键的类型为Cmd,以下介绍的所有方法皆服务于该类型:

func Command(name string, 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命令或可执行文件

演示在当前目录创建一个空文件

package main

import (
  "fmt"
  "os/exec"
)

func main(){
  cmd := exec.Command("touch", "test_file")

  err := cmd.Run()
  if err != nil {
    fmt.Println("Execute Command failed:" + err.Error())
    return
  }

  fmt.Println("Execute Command finished.")
}

一般不建议使用这种默认方式调用Shell脚本:

cmd := exec.Command("my_shell.sh")

因为这种方式实际的执行结果和命令行执行#sh my_shell.sh一样,如果你的Shell脚本不满足sh的规范,就会调用失败。

调用Shell脚本

设置bash来调用指定Shell脚本,dir_size.sh为我们测试用的Shell脚本。调用完成后打印Shell脚本的标准输出到控制台。

package main

import (
  "fmt"
  "os/exec"
)

func main(){
  command := `./dir_size.sh .`
  cmd := exec.Command("/bin/bash", "-c", command)

  output, err := cmd.Output()
  if err != nil {
    fmt.Printf("Execute Shell:%s failed with error:%s", command, err.Error())
    return
  }
  fmt.Printf("Execute Shell:%s finished with output:\n%s", command, string(output))
}

dir_size.sh示例文件内容如下,用于输出当前目录的大小:

#!/bin/bash
du -h --max-depth=1 $1

Go程序运行结果:

[root@localhost opt]# ll
total 2120
-rwx------. 1 root root   36 Jan 22 16:37 dir_size.sh
-rwx------. 1 root root 2152467 Jan 22 16:39 execCommand
drwxrwxr-x. 11 1000 1000  4096 Jul 12 2017 kibana
drwx------. 2 root root  4096 Jan 16 10:45 sftpuser
drwx------. 3 root root  4096 Jan 22 16:41 upload
[root@localhost opt]# ./execCommand
Execute Shell:./dir_size.sh . finished with output:
4.0K  ./sftpuser
181M  ./kibana
1.1G  ./upload
1.2G  .

使用输入输出Pipe

演示使用管道连接到grep命令的标准输入,过滤包含test的字符串,并使用管道连接标准输出,打印运行结果:

package main

import (
  "fmt"
  "io/ioutil"
  "os/exec"
)

func main(){
  cmd := exec.Command("/bin/bash", "-c", "grep test")

  stdin, _ := cmd.StdinPipe()
  stdout, _ := cmd.StdoutPipe()

  if err := cmd.Start(); err != nil{
    fmt.Println("Execute failed when Start:" + err.Error())
    return
  }

  stdin.Write([]byte("go text for grep\n"))
  stdin.Write([]byte("go test text for grep\n"))
  stdin.Close()

  out_bytes, _ := ioutil.ReadAll(stdout)
  stdout.Close()

  if err := cmd.Wait(); err != nil {
    fmt.Println("Execute failed when Wait:" + err.Error())
    return
  }

  fmt.Println("Execute finished:" + string(out_bytes))
}

Go程序运行结果:

[root@localhost ~]# ./execCommand
Execute finished:go test text for grep

阻塞/非阻塞方式调用

文章开头方法介绍处已经介绍的很清楚,且前面示例都有涉及,就不另行说明了。

参考文档:
GoLang标准库文档

到此这篇关于Go语言调用Shell与可执行文件的实现的文章就介绍到这了,更多相关Go语言调用Shell内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

时间: 2020-10-16

linux中用shell快速安装配置Go语言的开发环境

介绍 go1.5+版本提供编译好的安装包,我们只需要解压到相应的目录,并添加一些环境变量的配置即可. Go语言的安装步骤 下载安装包go1.7.linux-amd64.tar.gz 解压文件到指定目录: tar -zxf go1.7.linux-amd64.tar.gz 设置环境变量:GOROOT, GOPATH, PATH 既然我们可以列出这些步骤,那么便可以将整个过程自动化. 下面是安装脚本 #!/bin/bash #Upgrade go version to 1.7 #wget https

Linux下从零开始安装配置Nginx服务器+PHP开发环境

Nginx是俄罗斯人编写的十分轻量级的HTTP服务器,以事件驱动的方式编写,所以有非常好的性能,同时也是一个非常高效的反向代理.负载平衡.其拥有匹配Lighttpd的性能,同时还没有Lighttpd的内存泄漏问题,而且Lighttpd的mod_proxy也有一些问题并且很久没有更新. 因此我打算用其替代Apache应用于Linux服务器上.但是Nginx并不支持cgi方式运行,原因是可以减少因此带来的一些程序上的漏洞.那么我们必须使用FastCGI方式来执行PHP程序. 下面是我成功地配置Ngi

win7下安装配置node.js+express开发环境

1.安装 node.js. 进入官网的下载地址:http://www.nodejs.org/download/ . 选择Windows Installer或者选择Windows Installer (.msi) 32-bit,下载安装包. 下载完成后,双击安装. 2.安装 Express. 通过nmp包管理器进行安装,安装分为: 全局安装:自动安装到"C:\Users\[当前用户]\AppData\Roaming\npm"下,并且自动将路径添加到环境变量"Path"

Linux系统MySQL8.0.19快速安装配置教程图解

一.环境介绍 Linux系统使用yum安装MySQL需要从网上下载MySQL的一系列组件,这个过程非常耗时且有下载中断的可能,如果想要快速安装MySQL,可以先在网上将MySQL的离线包下载下来传到系统内进行安装,本文以CentOS7和MySQL8.0.19为例讲解 MySQL的快速安装和配置方法. 1.操作系统:CentOS7_x64 2.数据库版本:MySQL-8.0.19 离线包下载: 链接: https://pan.baidu.com/s/1OdehL8MoCe44nJ-SkkW8xw

Linux下Kafka单机安装配置方法(图文)

介绍 Kafka是一个分布式的.可分区的.可复制的消息系统.它提供了普通消息系统的功能,但具有自己独特的设计.这个独特的设计是什么样的呢? 首先让我们看几个基本的消息系统术语: •Kafka将消息以topic为单位进行归纳. •将向Kafka topic发布消息的程序成为producers. •将预订topics并消费消息的程序成为consumer. •Kafka以集群的方式运行,可以由一个或多个服务组成,每个服务叫做一个broker. producers通过网络将消息发送到Kafka集群,集群

Linux 7.4上安装配置Oracle 11.2.0.4图文教程

1. 配置Yum源及关闭SeLinux [root@localhost ~]# mkdir /media/rhel [root@localhost ~]# mount /dev/cdrom /media/rhel mount: /dev/sr0 is write-protected, mounting read-only [root@localhost ~]# vi /etc/yum.repos.d/iso.repo [iso] name=iso baseurl=file:///media/rh

CentOS6.9下svn快速安装配置方法

本文实例为大家分享了CentOS6.9快速安装配置svn的具体代码,供大家参考,具体内容如下 环境介绍: 操作系统:CentOS release 6.9 (Final) 192.168.65.130 (svn服务器) 192.168.65.129 (svn客户端) 一.svn安装检查(在两台上都执行) if [ ! -f /usr/bin/svn ]; then yum -y install subversion >/dev/null echo "svn has been installe

小白教程! Linux服务器上JDK安装配置方法

本文实例为大家分享了Linux上JDK安装配置方法,供大家参考,具体内容如下 一.环境 VMware12 Pro CentOS-6.7-i386-bin-DVD1 jdk-8u151-linux-i586 二.详细安装步骤前提:需要卸载自己Linux上的jdk rpm-qa| grepjdk 会显示你所有包含jdk这个字符串的安装包 rpm-e--nodeps对应的每个包名 会卸载对应的包 之后如果java -version显示 就是卸完了. 我之前是装过jdk1.7的,所以我需要卸载 ,没装过

node安装--linux下的快速安装教程

前言 因为要使用koa2,所以要对node进行升级.(Koa requires node v7.6.0 or higher for ES2015 and async function support.翻译过来就是,koa需要node的版本至少为7.6,也就是说,需要node支持ES2015和async的语法) 我的操作系统是CentOS,安装的node版本是7.7. 如何升级 1.下载编译好的二进制包 然后将这个二进制包上传到服务器上,然后通过xz程序解压. 如果出现上边的这个错误的话,请杀掉吃

mysql 5.7.11 winx64快速安装配置教程

本文为大家分享了mysql 5.7.11安装配置方法,供大家参考,具体内容如下 一.安装总体思路: 在官网下载zip安装包: 解压拷贝到C盘下: 配置环境变量: 修改mysql根目录下配置文件my-default.ini: 初始化mysql,安装mysql,启动mysql服务: 修改root用户密码: 成功安装. 二.具体步骤说明 1.下载安装包. 2.拷贝到C盘: 解压后拷贝文件夹至C盘:C:\Program Files\mysql.建议文件夹名字简单些. 3.配置环境变量: 计算机->右键-