Exec 执行成功但失败!

类似以下代码,执行提示失败了,但是转码结果有输出。

错误是 ERROR exec: "ffmpeg": executable file not found in $PATH

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
func ffmpegPipeExec(ctx context.Context, in io.Reader, out io.Writer, args ...string) error {
	argsData := append(append([]string{"-y", "-hide_banner", "-loglevel", "error", "-i", "pipe:0"}, args...), "pipe:1")
	cmd := exec.CommandContext(ctx, "ffmpeg", argsData...) // nolint
	cmd.Stdin = in
	cmd.Stdout = out
	errOut := bytes.NewBuffer(nil)
	cmd.Stderr = errOut
	if err := cmd.Run(); err != nil {
    slog.Error(err.Error())
	}
	if err := errOut.String(); len(err) > 0 && strings.Contains(err, "Error") {
		return fmt.Errorf(err)
	}
	return nil
}

问题分析

通过断点检测 Go 基础库,在这里遇到错误。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
if filepath.Base(name) == name {
		lp, err := LookPath(name)
		if lp != "" {
			// Update cmd.Path even if err is non-nil.
			// If err is ErrDot (especially on Windows), lp may include a resolved
			// extension (like .exe or .bat) that should be preserved.
			cmd.Path = lp
		}
		if err != nil {
			cmd.Err = err
		}
	}

继续深入

1
path := os.Getenv("PATH")

exec.Command 会从环境变量中判断可执行文件是否存在。我通过 brew 安装的 ffmpeg,路径在 /opt/homebrew/bin 目录下,shell 是有写入 PATH 的。

在终端执行 echo $PATH ,可输出详细环境变量,是正常的,那么可能是 vscode 加载环境变量时出现异常。

解决方法在 vscode 的 settings 增加,vscode 可以通过 ${env:Name} 的语法引用环境变量。

1
2
3
 "go.toolsEnvVars": {
    "PATH": "${env:PATH}:/opt/homebrew/bin"
 }

为什么都找不到可执行文件,程序却执行成功输出结果了呢?

1
2
3
if err := cmd.Run(); err != nil {
    slog.Error(err.Error())
}

在这一行中,没有返回错误,上层执行认为没有错误,写了一个空文件。

这里避免返回的原因是认为 ffmpeg 的错误信息会提供更多详情用于分析,但不应该忽略这个错误,可以将此错误放到最后判断。

参考

Vscode 官方文档

本文阅读量 次, 总访问量 ,总访客数
Built with Hugo .   Theme Stack designed by Jimmy