gocommand:一个跨平台的golang命令行执行package-阿里云开发者社区

开发者社区> 李宗申> 正文

gocommand:一个跨平台的golang命令行执行package

简介:     最近在做一个项目的时候,需要使用golang来调用操作系统中的命令行,来执行shell命令或者直接调用第三方程序,这其中自然就用到了golang自带的exec.Command.     但是如果直接使用原生exec.
+关注继续查看

    最近在做一个项目的时候,需要使用golang来调用操作系统中的命令行,来执行shell命令或者直接调用第三方程序,这其中自然就用到了golang自带的exec.Command.

    但是如果直接使用原生exec.Command会造成大量的重复代码,网上搜了一圈又没有找到对exec.Command相应的封装包,索性自己封装了一个,取名为gocommand.目前支持Linux和Windows,欢迎各位大神在github上提交代码补充其他平台的实现.

    下面介绍一下gocommand库的实现思路:

package gocommand

// 命令行接口
type Commander interface {
	// 执行命令行并返回结果
	// args: 命令行参数
	// return: 进程的pid, 命令行结果, 错误消息
	Exec(args ...string) (int, string, error)

	// 异步执行命令行并通过channel返回结果
	// stdout: chan结果
	// args: 命令行参数
	// return: 进程的pid
	// exception: 协程内的命令行发生错误时,会panic异常
	ExecAsync(stdout chan string, args ...string) int

	// 执行命令行(忽略返回值)
	// args: 命令行参数
	// return: 错误消息
	ExecIgnoreResult(args ...string) error
}

    gocommand目前的命令行执行函数都是源于Commander接口,目前该接口定义了3个函数,分别是:执行命令行病返回结果;异步执行命令行并得到结果;执行命令行并忽略结果.

package gocommand
 
import (
    "runtime"
)
 
// Command的初始化函数
func NewCommand() Commander {
    var cmd Commander
 
    switch runtime.GOOS {
    case "linux":
        cmd = NewLinuxCommand()
    case "windows":
        cmd = NewWindowsCommand()
    default:
        cmd = NewLinuxCommand()
    }
 
    return cmd
}
    创建一个Command的实现,并根据当前的操作系统,返回对应的实现函数,目前只实现了Linux和Windows,(Mac留给各位大神(土豪)了),其中LinuxCommand的代码实现如下:

package gocommand
 
import (
    "io/ioutil"
    "os"
    "os/exec"
    "syscall"
)
 
// LinuxCommand结构体
type LinuxCommand struct {
}
 
// LinuxCommand的初始化函数
func NewLinuxCommand() *LinuxCommand {
    return &LinuxCommand{}
}
 
// 执行命令行并返回结果
// args: 命令行参数
// return: 进程的pid, 命令行结果, 错误消息
func (lc *LinuxCommand) Exec(args ...string) (int, string, error) {
    args = append([]string{"-c"}, args...)
    cmd := exec.Command(os.Getenv("SHELL"), args...)
 
    cmd.SysProcAttr = &syscall.SysProcAttr{}
 
    outpip, err := cmd.StdoutPipe()
    defer outpip.Close()
    if err != nil {
        return 0, "", err
    }
 
    err = cmd.Start()
    if err != nil {
        return 0, "", err
    }
 
    out, err := ioutil.ReadAll(outpip)
    if err != nil {
        return 0, "", err
    }
 
    return cmd.Process.Pid, string(out), nil
}
 
// 异步执行命令行并通过channel返回结果
// stdout: chan结果
// args: 命令行参数
// return: 进程的pid
// exception: 协程内的命令行发生错误时,会panic异常
func (lc *LinuxCommand) ExecAsync(stdout chan string, args ...string) int {
    var pidChan = make(chan int, 1)
 
    go func() {
        args = append([]string{"-c"}, args...)
        cmd := exec.Command(os.Getenv("SHELL"), args...)
 
        cmd.SysProcAttr = &syscall.SysProcAttr{}
 
        outpip, err := cmd.StdoutPipe()
	defer outpip.Close()

        if err != nil {
            panic(err)
        }
 
        err = cmd.Start()
        if err != nil {
            panic(err)
        }
 
        pidChan <- cmd.Process.Pid
 
        out, err := ioutil.ReadAll(outpip)
        if err != nil {
            panic(err)
        }
 
        stdout <- string(out)
    }()
 
    return <-pidChan
}
 
// 执行命令行(忽略返回值)
// args: 命令行参数
// return: 错误消息
func (lc *LinuxCommand) ExecIgnoreResult(args ...string) error {
    args = append([]string{"-c"}, args...)
    cmd := exec.Command(os.Getenv("SHELL"), args...)
 
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr
    cmd.SysProcAttr = &syscall.SysProcAttr{}
 
    err := cmd.Run()
 
    return err
}

    Exec函数会在执行命令行后阻塞,直到得到命令的执行结果;ExecAsync函数在内部使用了协程来执行命令行,并通过参数中的chan变量把结果传递出去;ExecNoWait会无阻赛地执行命令行.Windows平台上的实现类似,只是Shell命令换成了cmd.

    使用示例如下:

package main
 
import (
    "log"
 
    "github.com/lizongshen/gocommand"
)
 
func main() {
    _, out, err := gocommand.NewCommand().Exec("ls /")
    if err != nil {
        log.Panic(err)
    }
 
    log.Println(out)
 
}
  代码的单元测试情况:

[lizongshen@localhost gocommand]$ go test
bin   dev  home  lib64  mnt  proc  run   srv  tmp  var
boot  etc  lib   media  opt  root  sbin  sys  usr
PASS
ok      gocommand   0.007s
    github开源地址:https://github.com/lizongshen/gocommand.

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
Flink运行时之TaskManager执行Task
TaskManager执行任务 当一个任务被JobManager部署到TaskManager之后,它将会被执行。本篇我们将分析任务的执行细节。 submitTask方法分析 一个任务实例被部署所产生的实际影响就是JobManager会将一个TaskDeploymentDescriptor对象封装在SubmitTask消息中发送给TaskManager。
1209 0
快速搭建平头哥安全处理器的可信执行环境
平头哥安全处理器系列包括CK802T, CK803T, CK804T和E902T等, 结合平头哥SoC安全机制,搭建的芯片平台具有良好的兼容性和健壮性。基于平头哥TEE OS接口的扩展性和移植性,可以方便地快速地移植到其他平头哥安全处理器的芯片平台上。本文介绍了如何在不同的芯片平台快速创建可信执行环境的步骤和注意点,帮助设计开发者迅速的在平头哥安全处理器上开发TEE OS。
1116 0
MaxCompute客户端(odpscmd)在windows命令行下查询中文乱码问题处理实践
MaxCompute客户端工具是阿里云大数据计算服务MaxCompue产品官方客户端工具,通过客户端工具可以连接MaxCompute项目,完成包括数据管理、数据上下传、作业执行、用户及授权管理等各项操作。
5303 0
Apache Dubbo 被曝出“高危”远程代码执行漏洞
6 月 23 日,360 网络安全响应中心(360CERT)发布《CVE-2020-1948:Apache Dubbo 远程代码执行漏洞通告》(以下简称《通告》)。《通告》称,Apache Dubbo 存在远程代码执行漏洞,受影响的版本有 Dubbo 2.5.x、Dubbo 2.6.0 - 2.6.7 和 Dubbo 2.7.0 - 2.7.6。
697 0
AngularJs中,如何在render完成之后,执行Js脚本
AngularJs是Google开源的前端JS框架。使用AngularJs, 我们能够容易地、健壮的开发出类似于Gmail一样的单页Web应用。AngularJs这个新兴的MVC前端框架,具有以下特点: MVC, 模块化,自动化双向数据绑定,语义化标签、依赖注入等。
721 0
+关注
李宗申
某医疗软件公司架构师。
6
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
文娱运维技术
立即下载
《SaaS模式云原生数据仓库应用场景实践》
立即下载
《看见新力量:二》电子书
立即下载