shx

package
v1.0.18 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 19, 2026 License: MIT Imports: 12 Imported by: 0

Documentation

Overview

Package shx 提供了基于 mvdan.cc/sh/v3 的纯 Go shell 命令执行功能。

本包是 ShellX 的子包, 提供了与主包相似的 API 风格, 但具有更好的跨平台一致性。 它使用 mvdan.cc/sh/v3 进行命令解析和执行, 不依赖系统 shell。

主要特性:

  • 纯 Go 实现, 不依赖系统 shell
  • 更好的跨平台一致性 (Windows/Linux/macOS 行为一致)
  • 链式调用 API, 支持流畅的方法链
  • 支持超时控制和上下文取消
  • 最小并发保护 (使用 atomic.Bool 防止重复执行)

基本用法:

import "gitee.com/MM-Q/shellx/shx"

// 简单执行
err := shx.Exec("echo hello world")

// 获取输出
output, err := shx.Output("ls -la")

// 链式配置
output, err := shx.New("echo hello").
	WithTimeout(5 * time.Second).
	WithDir("/tmp").
	ExecOutput()

// 使用上下文
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
err := shx.New("long-running-command").WithContext(ctx).Exec()

注意事项:

  • Shx 对象的配置方法 (WithXxx) 不是并发安全的, 不要在多个 goroutine 中并发配置
  • 每个 Shx 对象只能执行一次, 重复执行会返回错误
  • mvdan/sh 是同步执行的, 不提供异步 API, 如需异步请使用 goroutine 包装
  • 不支持进程控制 (无 PID、Kill、Signal) , 只能通过 context 取消

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrAlreadyExecuted 表示命令已经执行过
	ErrAlreadyExecuted = errors.New("command has already been executed")

	// ErrNilContext 表示上下文为 nil
	ErrNilContext = errors.New("context cannot be nil")

	// ErrNilReader 表示 reader 为 nil
	ErrNilReader = errors.New("reader cannot be nil")

	// ErrNilWriter 表示 writer 为 nil
	ErrNilWriter = errors.New("writer cannot be nil")
)

预定义错误

Functions

func IsExitStatus

func IsExitStatus(err error) (uint8, bool)

IsExitStatus 检查错误是否是退出状态错误

参数:

  • err: 错误对象

返回:

  • uint8: 退出码
  • bool: 是否是退出状态错误

func Out

func Out(cmd string) ([]byte, error)

Out 执行并获取输出

参数:

  • cmd: 命令字符串

返回:

  • []byte: 命令输出
  • error: 执行错误

示例:

output, err := shx.Out("ls -la")

func OutCtx

func OutCtx(ctx context.Context, cmd string) ([]byte, error)

OutCtx 使用上下文执行并获取输出

参数:

  • ctx: 上下文
  • cmd: 命令字符串

返回:

  • []byte: 命令输出
  • error: 执行错误

示例:

ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
output, err := shx.OutCtx(ctx, "ls -la")

func OutWith

func OutWith(cmd string, timeout time.Duration) ([]byte, error)

OutWith 超时执行并获取输出

参数:

  • cmd: 命令字符串
  • timeout: 超时时间

返回:

  • []byte: 命令输出
  • error: 执行错误

示例:

output, err := shx.OutWith("sleep 5", 10*time.Second)

func OutWithIO

func OutWithIO(cmd string, stdin io.Reader, stdout, stderr io.Writer) ([]byte, error)

OutWithIO 使用自定义输入输出执行并获取输出

参数:

  • cmd: 命令字符串
  • stdin: 标准输入
  • stdout: 标准输出
  • stderr: 标准错误

返回:

  • []byte: 命令输出
  • error: 执行错误

示例:

var buf bytes.Buffer
output, err := shx.OutWithIO("cat", strings.NewReader("hello"), &buf, os.Stderr)

func Run

func Run(cmd string) error

Run 执行命令

参数:

  • cmd: 命令字符串

返回:

  • error: 执行错误

示例:

err := shx.Run("echo hello")

func RunCtx

func RunCtx(ctx context.Context, cmd string) error

RunCtx 使用上下文执行

参数:

  • ctx: 上下文
  • cmd: 命令字符串

返回:

  • error: 执行错误

示例:

ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
err := shx.RunCtx(ctx, "sleep 10")

func RunToTerminal

func RunToTerminal(cmd string) error

RunToTerminal 执行命令并输出到终端

参数:

  • cmd: 命令字符串

返回:

  • error: 执行错误

示例:

err := shx.RunToTerminal("echo hello")

func RunWith

func RunWith(cmd string, timeout time.Duration) error

RunWith 超时执行

参数:

  • cmd: 命令字符串
  • timeout: 超时时间

返回:

  • error: 执行错误

示例:

err := shx.RunWith("sleep 10", 5*time.Second)

func RunWithIO

func RunWithIO(cmd string, stdin io.Reader, stdout, stderr io.Writer) error

RunWithIO 使用自定义输入输出执行

参数:

  • cmd: 命令字符串
  • stdin: 标准输入
  • stdout: 标准输出
  • stderr: 标准错误

返回:

  • error: 执行错误

示例:

var buf bytes.Buffer
err := shx.RunWithIO("cat", strings.NewReader("hello"), &buf, os.Stderr)

Types

type ExitStatus

type ExitStatus struct {
	Code uint8
}

ExitStatus 包装退出状态错误

func (ExitStatus) Error

func (e ExitStatus) Error() string

Error 实现 error 接口

type Shx

type Shx struct {
	// contains filtered or unexported fields
}

Shx 表示一个待执行的 shell 命令

func New

func New(cmdStr string) *Shx

New 从字符串创建命令

参数:

  • cmdStr: 命令字符串

返回:

  • *Shx: 命令对象

示例:

cmd := shx.New("echo hello world")
cmd := shx.New("ls -la | grep .go")

func NewArgs

func NewArgs(cmd string, args ...string) *Shx

NewArgs 从命令名和可变参数创建命令

参数:

  • cmd: 命令名
  • args: 可变参数列表

返回:

  • *Shx: 命令对象

示例:

cmd := shx.NewArgs("ls", "-la", "/tmp")
cmd := shx.NewArgs("git", "commit", "-m", "message")

func NewCmds

func NewCmds(cmds []string) *Shx

NewCmds 从命令切片创建命令

参数:

  • cmds: 命令切片,每个元素是一个完整的命令部分

返回:

  • *Shx: 命令对象

示例:

cmd := shx.NewCmds([]string{"ls", "-la", "|", "grep", ".go"})
cmd := shx.NewCmds([]string{"echo", "hello", ">", "output.txt"})

func NewWithParser

func NewWithParser(cmdStr string, parser *syntax.Parser) *Shx

NewWithParser 使用自定义解析器创建命令

参数:

  • cmdStr: 命令字符串
  • parser: 自定义解析器

返回:

  • *Shx: 命令对象

func (*Shx) Context

func (s *Shx) Context() context.Context

Context 获取上下文

返回:

  • context.Context: 上下文

func (*Shx) Dir

func (s *Shx) Dir() string

Dir 获取工作目录

返回:

  • string: 工作目录

func (*Shx) Env

func (s *Shx) Env() expand.Environ

Env 获取环境变量

返回:

  • expand.Environ: 环境变量

func (*Shx) Exec

func (s *Shx) Exec() error

Exec 执行命令 (阻塞)

返回:

  • error: 执行过程中的错误, 不包含退出码错误

线程安全:

  • 使用 atomic.Bool 确保重复执行检测的线程安全

示例:

err := shx.New("echo hello").Exec()
if err != nil {
    log.Fatal(err)
}

func (*Shx) ExecContext

func (s *Shx) ExecContext(ctx context.Context) error

ExecContext 在指定上下文中执行命令

参数:

  • ctx: 上下文 (用于取消执行)

返回:

  • error: 执行过程中的错误

注意:

  • 此方法会覆盖之前通过 WithContext 设置的上下文
  • 此方法不受 WithTimeout 影响 (上下文的超时优先)

func (*Shx) ExecContextOutput

func (s *Shx) ExecContextOutput(ctx context.Context) ([]byte, error)

ExecContextOutput 在指定上下文中执行并返回输出

参数:

  • ctx: 上下文

返回:

  • []byte: 命令输出
  • error: 执行过程中的错误

func (*Shx) ExecOutput

func (s *Shx) ExecOutput() ([]byte, error)

ExecOutput 执行命令并返回输出

返回:

  • []byte: 命令输出 (stdout 和 stderr 合并)
  • error: 执行过程中的错误

注意:

  • 内部会自动捕获 stdout 和 stderr
  • 如果需要区分 stdout 和 stderr, 请使用 WithStdout 和 WithStderr 自定义

func (*Shx) IsExecuted

func (s *Shx) IsExecuted() bool

IsExecuted 检查命令是否已经执行过

返回:

  • bool: 是否已执行

func (*Shx) Raw

func (s *Shx) Raw() string

Raw 获取原始命令字符串

返回:

  • string: 原始命令字符串

func (*Shx) Timeout

func (s *Shx) Timeout() time.Duration

Timeout 获取超时时间

返回:

  • time.Duration: 超时时间

func (*Shx) WithContext

func (s *Shx) WithContext(ctx context.Context) *Shx

WithContext 设置上下文

参数:

  • ctx: 上下文

返回:

  • *Shx: 命令对象 (支持链式调用)

注意:

  • 如果命令已经执行过, 会 panic
  • 设置的上下文会完全覆盖 WithTimeout 设置的超时

func (*Shx) WithDir

func (s *Shx) WithDir(dir string) *Shx

WithDir 设置工作目录

参数:

  • dir: 工作目录路径

返回:

  • *Shx: 命令对象 (支持链式调用)

注意:

  • 如果命令已经执行过, 会 panic
  • 如果目录不存在或不是目录, 会 panic

func (*Shx) WithEnv

func (s *Shx) WithEnv(key, value string) *Shx

WithEnv 设置环境变量

参数:

  • key: 环境变量名
  • value: 环境变量值

返回:

  • *Shx: 命令对象 (支持链式调用)

注意:

  • 如果命令已经执行过, 会 panic
  • 如果 key 为空, 则忽略

func (*Shx) WithEnvMap added in v1.0.14

func (s *Shx) WithEnvMap(envs map[string]string) *Shx

WithEnvMap 批量设置环境变量

参数:

  • envs: 环境变量映射 (key-value)

返回:

  • *Shx: 命令对象 (支持链式调用)

注意:

  • 如果命令已经执行过, 会 panic

func (*Shx) WithEnvs

func (s *Shx) WithEnvs(envs []string) *Shx

WithEnvs 批量设置环境变量

参数:

  • envs: 环境变量切片, 每个元素格式为 "key=value"

返回:

  • *Shx: 命令对象 (支持链式调用)

注意:

  • 如果命令已经执行过, 会 panic
  • 格式错误的项会被忽略
  • 同名的变量, 后出现的会覆盖先出现的

func (*Shx) WithStderr

func (s *Shx) WithStderr(w io.Writer) *Shx

WithStderr 设置标准错误

参数:

  • w: 错误输出写入器

返回:

  • *Shx: 命令对象 (支持链式调用)

注意:

  • 如果命令已经执行过, 会 panic

func (*Shx) WithStdin

func (s *Shx) WithStdin(r io.Reader) *Shx

WithStdin 设置标准输入

参数:

  • r: 输入读取器

返回:

  • *Shx: 命令对象 (支持链式调用)

注意:

  • 如果命令已经执行过, 会 panic

func (*Shx) WithStdout

func (s *Shx) WithStdout(w io.Writer) *Shx

WithStdout 设置标准输出

参数:

  • w: 输出写入器

返回:

  • *Shx: 命令对象 (支持链式调用)

注意:

  • 如果命令已经执行过, 会 panic

func (*Shx) WithTimeout

func (s *Shx) WithTimeout(d time.Duration) *Shx

WithTimeout 设置超时时间

参数:

  • d: 超时时间

返回:

  • *Shx: 命令对象 (支持链式调用)

注意:

  • 如果命令已经执行过, 会 panic
  • 如果 d <= 0, 则忽略 (不设置超时)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL