目录

GO第三方库-go-sh

像 python-sh 一样,可以轻松使用 golang 调用 shell .

使用介绍

Go 标准库有 os/exec 也可以执行 shell ,不过用起来并不顺手, go-sh 和它非常相似。不过,go-sh 提供了更好的开发体验。 官方 GitHub

Pipe 示例:

1
2
3
4
5
6
7
8

package main

import "github.com/codeskyblue/go-sh"

func main() {
	sh.Command("echo", "hello\tworld").Command("cut", "-f2").Run()
}

这是它的以下特性:

  • 保持环境变量(比如 export)

  • 支持别名 (例如 shell 中的别名)

  • 记住当前的目录

  • 管道命令

  • 内置 shell 命令 echo 和 test

  • timeout 支持

使用示例

比较常用的使用场景。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
sh: echo hello
go: sh.Command("echo", "hello").Run()

sh: export BUILD_ID=123
go: s = sh.NewSession().SetEnv("BUILD_ID", "123")

sh: alias ll='ls -l'
go: s = sh.NewSession().Alias('ll', 'ls', '-l')

sh: (cd /; pwd)
go: sh.Command("pwd", sh.Dir("/")).Run()

sh: test -d data || mkdir data
go: if ! sh.Test("dir", "data") { sh.Command("mkdir", "data").Run() }

sh: cat first second | awk '{print $1}'
go: sh.Command("cat", "first", "second").Command("awk", "{print $1}").Run()

sh: count=$(echo "one two three" | wc -w)
go: count, err := sh.Echo("one two three").Command("wc", "-w").Output()

sh(in ubuntu): timeout 1s sleep 3
go: c := sh.Command("sleep", "3"); c.Start(); c.WaitTimeout(time.Second) # default SIGKILL
go: out, err := sh.Command("sleep", "3").SetTimeout(time.Second).Output() # set session timeout and get output)

sh: echo hello | cat
go: out, err := sh.Command("cat").SetInput("hello").Output()

sh: cat # read from stdin
go: out, err := sh.Command("cat").SetStdin(os.Stdin).Output()

sh: ls -l > /tmp/listing.txt # write stdout to file
go: err := sh.Command("ls", "-l").WriteStdout("/tmp/listing.txt")

如果需要保持环境变量和工作目录,可以创建 session 来实现。

1
2
3
4
5
6
7
8
9
session := sh.NewSession()
session.SetEnv("BUILD_ID", "123")
session.SetDir("/")

# then call cmd
session.Command("echo", "hello").Run()

# set ShowCMD to true for easily debug
session.ShowCMD = true

如果使用管道,默认情况下,只有在管道最后一个环节命令退出状态不为 0 的情况,才任务命令失败,如果想要在执行管道的过程中,其中一个环节出现命令退出状态不为 0 就抛出错误的话,需要设置 pipefail 属性为 true 来实现。

1
2
3
session := sh.NewSession()
session.PipeFail = true
session.Command("cat", "unknown-file").Command("echo").Run()

同样的,想要捕获整个执行过程中所有环节的 stderr ,也需要设置参数来启用,设置 session.PipeStdErrors = true 即可。