Go 插件每日推荐之 go-sh | Go 主题月

1,240 阅读2分钟

大家好,我是 @洛竹

本文首发于 洛竹的官方网站

本文同步于公众号『洛竹早茶馆』,转载请联系作者。

创作不易,养成习惯,素质三连!

安装

go get github.com/codeskyblue/go-sh

管道示例

package main

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

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

因为我喜欢 os/exec,所以 go-sh 和它非常相似。 但是,go-sh 提供了更好的开发体验。

这是它的一些特性:

  • 保持环境变量(比如 export
  • 支持别名 (例如 shell 中的别名)
  • 记住当前的目录
  • 管道命令
  • 内置 shell 命令 echotest
  • timeout 支持

Examples are important:

  • 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")

如果您需要保留 envdir,则最好创建一个会话:

session := sh.NewSession()
session.SetEnv("BUILD_ID", "123")
session.SetDir("/")
# 然后调用 cmd
session.Command("echo", "hello").Run()
# 设置 ShowCMD 为 true 来调试程序
session.ShowCMD = true

默认情况下,仅当最后一个命令以非零状态退出时,管道才会返回错误。但是,你也可以启用 bash 之类的 pipefail 选项。在这种情况下,如果任何命令失败,则管道将返回错误;对于多个失败的命令,管道将返回最右边的失败命令的错误。

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

默认情况下,管道的标准错误设置为上一个命令的标准错误。但是,你也可以使用 session.PipeStdErrors = true 将所有命令的标准错误合并到管道的标准错误中。

使用 Go shell 的原因

有时我们需要编写 Shell 脚本,但是 Shell 脚本不擅长跨平台工作,而 Go 则擅长于此。是否有使用 Go 编写类似脚本的 Shell 的好方法呢? 答案是使用 go-sh 帮助你更方便的工作。