cmd.output()适合预期成功且只关心stdout的场景,如date、hostname;它只捕获stdout、忽略stderr,失败时error不等于无输出,需用*exec.exiterror类型断言获取退出码。

cmd.Output() 是 Go 里最常用、但最容易误用的标准输出获取函数。它只捕获 stdout,不捕获 stderr;且命令失败时仍可能有有效输出,但 error 不等于“没结果”。
什么时候该用 cmd.Output()?
适合「预期成功 + 只关心 stdout」的简单场景,比如:date、hostname、whoami、git rev-parse HEAD 这类几乎总成功、错误极少、且 stderr 无关紧要的命令。
别用它处理 ls /nonexistent 或 curl https://bad.url —— 它们失败时 stderr 里有关键错误信息,而 Output() 默认丢弃这些内容,还容易让你误以为“没输出就是没执行”。
- ✅ 正确用法:命令本身设计为“成功才吐 stdout”,失败是异常情况
- ❌ 错误用法:用它诊断报错、或依赖 stderr 提示(比如编译器错误、curl 的 404 提示)
- ⚠️ 注意:
err != nil时,output依然可能是非空字节切片(比如go build编译失败时 stdout 可能为空,但 stderr 才有报错)
cmd.Output() 返回的 error 怎么判断退出码?
Output() 失败时返回的 error 通常是 *exec.ExitError 类型,不是普通字符串错误。直接 fmt.Println(err) 只能看到模糊提示,没法做逻辑分支。
- 必须先类型断言:
if exitErr, ok := err.(*exec.ExitError); ok { ... } - 再调
exitErr.ExitCode()获取真实退出码(Linux/macOS 下常见:1 表示一般错误,127 表示命令未找到) - Windows 上需用
exitErr.Sys().(syscall.WaitStatus).ExitStatus(),但多数服务端代码跑在 Unix 环境,优先按ExitCode()处理
示例:
output, err := cmd.Output()
if err != nil {
if exitErr, ok := err.(*exec.ExitError); ok {
fmt.Printf("命令退出码:%d\n", exitErr.ExitCode())
// 比如 exit code == 2 可能表示参数错误,可针对性提示
}
}
fmt.Printf("实际输出:%s", output)
为什么 cmd.Output() 有时输出为空但 err 为 nil?
这不是 bug,而是命令行为本身决定的。常见原因:
- 命令真的没输出任何内容(比如
true、touch file) - 命令把内容写到了 stderr 而非 stdout(比如某些工具把进度/警告打到 stderr)
- 命令输出被缓冲,且未显式 flush(尤其在管道或重定向场景下)
- 你传参时用了 shell 特性(如
echo $PATH),但exec.Command不经过 shell —— 它会字面执行echo和$PATH两个参数,导致输出$PATH字符串而非变量值
验证方式:把同一命令拿到终端手动执行,对比 stdout/stderr 分布。如果终端里能看到但 Go 里 Output() 拿不到,大概率是写到了 stderr。
替代方案:什么时候该换 CombinedOutput() 或手动接管 pipe?
CombinedOutput() 是 Output() 的“懒人加强版”:它把 stdout 和 stderr 合并进一个 []byte,适合快速调试或日志归档。
- ✅ 适用:你想看“命令到底干了啥”,比如 CI 脚本执行失败后需要完整日志
- ❌ 不适用:你需要区分“正常结果”和“错误提示”做不同处理(比如解析 JSON 成功响应 vs 捕获 curl 的 401 错误体)
- ⚠️ 注意:
CombinedOutput()同样不解决实时流问题 —— 它仍是等待命令结束才返回,对ping、tail -f无效
真要区分 stdout/stderr 或实时读取,就得手动设 Stdout/Stderr 为 bytes.Buffer 或用 StdoutPipe() 配 goroutine —— 这些不是“高级技巧”,而是面对真实运维场景时的必选项。
cmd.Output() 的陷阱不在语法,而在语义:它假装“输出 = 结果”,但系统命令的真实世界里,stdout 是数据,stderr 是上下文,退出码是状态。三者缺一不可。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











