直接 exec.command("sh", "script.sh") 常不工作,因 go 不经 shell 解析,将 "script.sh" 当作可执行文件名在 path 中查找,而非脚本;正确写法是 exec.command("sh", "-c", "exec ./script.sh") 或带参数防注入的 exec.command("sh", "-c", "exec "$1"", "sh", scriptpath)。

为什么直接 exec.Command("sh", "script.sh") 常常不工作
因为 exec.Command 默认不启用 shell 解析,传入的 "script.sh" 被当作一个可执行文件名直接调用,而系统找不到同名二进制 —— 它不是命令,是脚本。必须显式调用 shell 解释器,并把脚本路径作为参数传给它。
- 正确写法是:
exec.Command("sh", "-c", "sh script.sh")或更稳妥的exec.Command("sh", "-c", "exec ./script.sh") - 如果脚本有 shebang(如
#!/bin/bash)且已加执行权限,可直接exec.Command("./script.sh"),但前提是当前工作目录正确、PATH 无关、权限到位 - 常见错误现象:
exec: "script.sh": executable file not found in $PATH—— 这说明 Go 没把它当脚本,而是当命令搜 PATH
如何安全传参并避免 shell 注入
用 -c 启动 shell 时,如果脚本路径或参数来自用户输入,拼接字符串会引发 shell 注入。不能写 exec.Command("sh", "-c", "sh "+scriptPath)。
- 推荐做法:把脚本路径和参数作为额外
exec.Command参数传入,让 shell 自己解析,例如:cmd := exec.Command("sh", "-c", "exec "$1"", "sh", scriptPath) - 其中
"$1"是占位符,"sh"是占位参数(被$0消耗),scriptPath成为$1,不会被 shell 展开或执行任意命令 - 若需传多个参数给脚本:
cmd := exec.Command("sh", "-c", "exec "$1" "$2" "$3"", "sh", scriptPath, arg1, arg2)
如何捕获输出、判断成功、处理超时
exec.Command 返回的 cmd 对象必须显式启动,且默认不等待完成;不检查 err 或 cmd.Wait() 的返回值,就会误判执行结果。
本文档主要讲述的是Android 操作系统的介绍;Android是基于Linux内核的操作系统,是Google公司在2007年11月5日公布的手机操作系统,早期由Google开发,后由开放手持设备联盟(Open Handset Alliance)开发。它采用了软件堆层(software stack,又名以软件叠层)的架构,主要分为三部分。底层Linux内核只提供基本功能;其他的应用软件则由各公司自行开发,部分程序以Java编写。希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看
- 获取 stdout/stderr:
cmd.Stdout = &stdoutBuf<br>cmd.Stderr = &stderrBuf
,别用cmd.Output()—— 它自动调用Run()但吞掉 stderr,出错时看不到报错信息 - 设置超时(重要!shell 脚本卡住很常见):
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)<br>defer cancel()<br>cmd := exec.CommandContext(ctx, "sh", "-c", "...")
- 判断是否真正成功:
err为nil只表示启动成功,要调cmd.Wait()或检查err是否为*exec.ExitError类型,并用exitErr.ExitCode()获取状态码
跨平台注意事项:Windows 上怎么跑 shell 脚本
Go 的 exec.Command 在 Windows 上默认不识别 sh,即使装了 Git Bash 或 WSL,也不会自动用它执行 .sh 文件。
- Windows 下想运行 bash 脚本,得明确指定解释器路径,例如:
exec.Command("C:\Program Files\git\usr\bin\bash.exe", scriptPath) - 更兼容的做法是检测 OS:
shell := "sh"<br>if runtime.GOOS == "windows" {<br> shell = "bash"<br>},再配合完整路径或要求用户提前配置环境变量 - 注意换行符:Linux/macOS 脚本用 LF,Windows 编辑保存可能变成 CRLF,某些 shell 解释器(尤其旧版)会因
#!/bin/bash^M报错/bin/bash^M: bad interpreter—— 用dos2unix或编辑器转格式
真正麻烦的从来不是“怎么调”,而是“怎么确保它在所有机器上稳定、安全、可调试”。参数传错、路径不对、权限缺失、超时没设、输出没捕获 —— 这些细节漏一个,线上就静默失败。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










