English | 简体中文
轻量的二进制执行封装,支持:
- 直接执行本地已有二进制
- 从
embed.FS落盘后执行 - 从远程下载、缓存并处理二进制后执行
适合把命令行工具、辅助进程或嵌入式可执行文件封装成统一的 Go 调用入口。
- 统一入口:通过
New创建Engine,统一处理二进制准备、运行和释放 - 多种来源:支持本地文件、
embed.FS、DownloadUrl - 可扩展下载处理:兼容旧版
DownloadHandler,也支持带目标目录的DownloadHandlerWithDir - 运行控制:支持环境变量、工作目录、同步执行和流式执行;参数按 argv 原样传递,不经 shell 二次解析
- 安全边界清晰:外部
BinFile不会在Release()时被误删 - 下载格式支持:支持普通文件、
.zip、.tar.gz/.tgz和单文件.gz,解压时保留硬链接与符号链接
go get github.com/zlsgo/execpackage main
import (
"context"
"embed"
"fmt"
execbin "github.com/zlsgo/exec"
)
func main() {
engine, err := execbin.New(embed.FS{}, func(options *execbin.Options) {
options.BinFile = "/path/to/tool"
options.Dir = "/path/to/workdir"
options.Env = []string{"APP_MODE=prod"}
})
if err != nil {
panic(err)
}
defer engine.Release()
code, out, errOut, err := engine.Run(context.Background(), []string{"--version"})
fmt.Println(code, out, errOut, err)
}package main
import (
"context"
"embed"
execbin "github.com/zlsgo/exec"
)
//go:embed bin/*
var binFS embed.FS
func main() {
engine, err := execbin.New(binFS, func(options *execbin.Options) {
options.BinFile = "tool"
})
if err != nil {
panic(err)
}
defer engine.Release()
_, _, _, _ = engine.Run(context.Background(), []string{"--help"})
}package main
import (
"context"
"embed"
"fmt"
execbin "github.com/zlsgo/exec"
)
func main() {
engine, err := execbin.New(embed.FS{}, func(options *execbin.Options) {
options.BinFile = "tool"
options.DownloadUrl = "https://example.com/tool.zip"
options.DownloadProgress = func(percent float64, size int64) {
fmt.Printf("progress: %.2f%% size=%d\n", percent, size)
}
})
if err != nil {
panic(err)
}
defer engine.Release()
_, _, _, _ = engine.Run(context.Background(), []string{"--help"})
}如果下载产物不是最终可执行文件,可以通过 DownloadHandlerWithDir 自定义解包、重命名或安装逻辑。
回调参数分别是:
file:下载缓存文件路径dir:当前Engine的目标落盘目录
engine, err := execbin.New(embed.FS{}, func(options *execbin.Options) {
options.BinFile = "tool"
options.DownloadUrl = "https://example.com/tool.zip"
options.DownloadHandlerWithDir = func(file string, dir string) error {
// 在这里自行处理下载产物,例如解压到 dir、复制或重命名为目标文件
return nil
}
})创建执行引擎,并根据以下优先级准备二进制:
BinFile指向的本地文件存在:直接使用- 本地文件不存在,但
embed.FS中存在内容:落盘后使用 - embed 内容为空,且配置了
DownloadUrl:下载后使用
同步执行命令,返回:
- 退出码
- 标准输出
- 标准错误
- 执行错误
流式执行命令,适合长时间运行或需要实时消费输出的场景。
- 当二进制由当前
Engine创建的临时目录提供时,会清理该目录 - 当
BinFile指向外部已有文件时,只取消上下文,不删除外部目录
BinFile既表示目标文件名,也可能表示已存在的绝对/相对路径DownloadHandlerWithDir一旦配置,会优先接管下载产物处理,并负责把最终可执行文件放到当前Engine的目标目录- 旧版
DownloadHandler(file string) error仍然保留,用于兼容已有调用方 - 压缩包解压会校验目标路径,避免目录穿越
- 未自定义 handler 时,普通文件和单文件
.gz会默认落盘到BinFile对应路径 Run/KeepRun会正确透传覆盖后的Env和Dir