gocommand:一個跨平台的golang命令列執行package

來源:互聯網
上載者:User

    最近在做一個項目的時候,需要使用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: 錯誤訊息ExecNoWait(args ...string) error}

    gocommand目前的命令列執行函數都是源於Commander介面,目前該介面定義了3個函數,分別是:執行命令列病返回結果;非同步執行命令列並得到結果;執行命令列並忽略結果.

package gocommandimport ("runtime")// Command的初始化函數func NewCommand() Commander {var cmd Commanderswitch runtime.GOOS {case "linux":cmd = NewLinuxCommand()case "windows":cmd = NewWindowsCommand()default:cmd = NewLinuxCommand()}return cmd}

    建立一個Command的實現,並根據當前的作業系統,返回對應的實現函數,目前只實現了Linux和Windows,(Mac留給各位大神(土豪)了),其中LinuxCommand的代碼實現如下:

package gocommandimport ("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()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()if err != nil {panic(err)}err = cmd.Start()if err != nil {panic(err)}pidChan <- cmd.Process.Pidout, err := ioutil.ReadAll(outpip)if err != nil {panic(err)}stdout <- string(out)}()return <-pidChan}// 執行命令列(忽略傳回值)// args: 命令列參數// return: 錯誤訊息func (lc *LinuxCommand) ExecNoWait(args ...string) error {args = append([]string{"-c"}, args...)cmd := exec.Command(os.Getenv("SHELL"), args...)cmd.Stdout = os.Stdoutcmd.Stderr = os.Stderrcmd.SysProcAttr = &syscall.SysProcAttr{}err := cmd.Run()return err}

    Exec函數會在執行命令列後阻塞,直到得到命令的執行結果;ExecAsync函數在內部使用了協程來執行命令列,並通過參數中的chan變數把結果傳遞出去;ExecNoWait會無阻賽地執行命令列.Windows平台上的實作類別似,只是Shell命令換成了cmd.

    使用樣本如下:

package mainimport ("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 testbin   dev  home  lib64mnt  proc  run srv  tmp  varboot  etc  lib mediaopt  root  sbin  sys  usrPASSok  gocommand0.007s

    github開源地址:https://github.com/lizongshen/gocommand.

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.