最近在做一个项目的时候,需要使用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.

gocommand:一个跨平台的golang命令行执行package的更多相关文章

  1. PHP下的命令行执行 php -S localhost -t public

    PHP 的命令行模式     以下是 PHP 二进制文件(即 php.exe 程序)提供的命令行模式的选项参数,您随时可以通过 PHP -h 命令来查询这些参数. Usage: php [option ...

  2. PHP下的命令行执行

    PHP 的命令行模式 以下是 PHP 二进制文件(即 php.exe 程序)提供的命令行模式的选项参数,您随时可以通过 PHP -h 命令来查询这些参数. Usage: php [options] [ ...

  3. PHP下的命令行执行 php -S localhost -t public(public是根目录,也是入口文件所在目录,是LARAVEL的)

    PHP 的命令行模式     以下是 PHP 二进制文件(即 php.exe 程序)提供的命令行模式的选项参数,您随时可以通过 PHP -h 命令来查询这些参数. Usage: php [option ...

  4. Linux 下一个很棒的命令行工具

    导读 Taskwarrior 是 Ubuntu/Linux 下一个简单而直接的基于命令行的 TODO 工具.这个开源软件是我曾用过的最简单的基于命令行的工具之一.Taskwarrior 可以帮助你更好 ...

  5. android程序中使用命令行及获得命令行执行后的内容

    在开发android项目中,需要在程序中使用命令行执行,获得命令行执行后的结果并做处理. 下面是自己写的一个小例子,供以后参考使用: public String android_command(){ ...

  6. 命令行执行php脚本 中$argv和$argc

    在实际工作中有可能会碰到需要在nginx命令行执行php脚本的时候,当然你可以去配置一个conf用外网访问. 在nginx命令行中 使用 php index.php 就可以执行这个index.php脚 ...

  7. yii2 命令行执行php命令 commands(命令)

    YII2可以在命令行执行php命令,作为半路出家的撩妹君可谓是抠脚福音.作为一个屌丝级的程序员必须要有智能提示代码的IDE,比如PHPstorm.至于如何免费使用嘛..... 首先明白YII2自带的c ...

  8. 使用命令行执行jmeter的方法

    1. 简介 使用非 GUI 模式,即命令行模式运行 JMeter 测试脚本能够大大缩减所需要的系统资 本文介绍windows下以命令行模式运行的方法. 1.1. 命令介绍 jmeter -n -t & ...

  9. 编码用命令行执行的C语言词语统计程序

    需求介绍 程序处理用户需求的模式为: wc.exe [parameter][filename] 在[parameter]中,用户通过输入参数与程序交互,需实现的功能如下: 1.基本功能 支持 -c   ...

随机推荐

  1. telerik:RadGrid 在表格中编辑更新数据

    对于 telerik 这个框架 我也不是很熟悉 也是刚刚开始学习  有兴趣的可以去官网看下 https://www.telerik.com/ 啥也不多说 直接上代码 首先是 telerik:RadGr ...

  2. asp.net——公共帮助类

    在项目开发中公共帮助类是必不可少的,这里记录一些自己摘录或自己编写的帮助类. 64位编码与解码: #region URL的64位编码 /// <summary> /// URL的64位编码 ...

  3. webapi 用腾讯云手机短信验证码

    #region 验证码相关 public class SmsSDK { #region 短信发送的必要参数 /// <summary> /// appId /// </summary ...

  4. Win(Phone)10开发第(5)弹,本地媒体服务器的一些注意事项

    首先有个wp上的http服务器 http://wphttpserver.codeplex.com/ 使用方式: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ...

  5. log4j学习(一)最简单的例子

    前言: 之前笔者一直是在System.out中打日志的,由于笔者大部分时候是编写在tomcat容器里运行的一些个小web应用,所以这么做似乎没什么问题:打印出来的日志都可以在tomcat自己的log目 ...

  6. Java基础学习篇---------继承

    一.覆写(重写) 1.含义:子类的定义方法.属性和父类的定义方法.属性相同时候 方法名称相同,参数相同以及参数的个数也相同,此时为覆写(重写) 扩充知识点: 覆盖:只有属性名字和方法名字相同,类型.个 ...

  7. Weekly Contest 132

    1025. Divisor Game Alice and Bob take turns playing a game, with Alice starting first. Initially, th ...

  8. 二:MyBatis学习总结(二)——使用MyBatis对表执行CRUD操作

    上一篇博文MyBatis学习总结(一)——MyBatis快速入门中我们讲了如何使用Mybatis查询users表中的数据,算是对MyBatis有一个初步的入门了,今天讲解一下如何使用MyBatis对u ...

  9. Java堆内存溢出模拟

    先了解一下Java堆: 关于Java内存区域的分配,可以查看Java运行时数据区域一篇文章. Java堆是虚拟机内存管理中最大的一块区域,该区域是线程共享的,某Java进程中所有的线程都可以访问该区域 ...

  10. bzoj 3027: [Ceoi2004]Sweet (生成函数)

    题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=3027. 题目大意:有$n$种数,每种有$C_i$个,问你在这些数中取出$[l,r]$个 ...