exec 的可执行决议。命令 + 路径

Executable Resolution for exec.Command + PATH

提问人:404 提问时间:10/19/2023 最后编辑:404 更新时间:10/19/2023 访问量:46

问:

具有非常相似的命令调用

cmdDirect := exec.Command("theExecutable")
cmdShell := exec.Command(os.GetEnv("SHELL"),  "-c",  "theExecutable")

两者都具有相同的环境设置

envWithPath := append(os.Environ(), fmt.Sprintf("PATH=/real/existing/path/to/theExecutable/holder:%s", os.GetEnv("PATH")))

cmdDirect.Env = envWithPath
cmdShell.Env = envWithPath

尽管如此,虽然按预期工作良好,但失败cmdShellcmdDirect

exec: "theExecutable": executable file not found in $PATH

对于上述相同的环境设置,调用也是成功的

cmdWhich := exec.Command("which", "theExecutable")

正确返回/real/existing/path/to/theExecutable/holder/theExecutable

那么,造成这种差异的原因可能是什么呢?

P.S. 以及这两种方法肯定具有完全相同的设置。例如$PATH

exec.Command("env")
exec.Command(os.GetEnv("SHELL"),  "-c",  "env")

两个输出是否具有相同的序列PATH=....

感谢

shell go 路径 环境变量

评论

1赞 JimB 10/19/2023
您正在使用的 shell 可以加载与当前进程不同的环境。 从同一个外壳中,看看它是什么。echo $PATH
0赞 404 10/19/2023
@JimB是完全相同的。向问题添加了信息PATH
0赞 JimB 10/19/2023
那条线应该做什么?除了无效的语法之外,它不是在修改变量,而是在添加一个以可执行路径命名的新变量。cmd*.Env = append(PATH
0赞 404 10/19/2023
@JimB 哦,它只是一个伪代码通配符(即 for 和后缀)。对于格式,对不起,它是在问题中输入错误的问题(已修复),原始代码是有效的 -cmd*DirectShellPATH=

答:

1赞 maxm 10/19/2023 #1

exec.Command查找使用 PATH 的可执行文件的路径,而不是在 cmd 上设置的路径。exec.LookPath

如果您希望对特定可执行文件进行更可靠的查找(或像您一样生成子 shell),我建议设置为可执行文件的路径。Cmd.Path

评论

0赞 404 10/19/2023
啊!!伟大。谢谢。该行为非常符合您的描述。是否有任何捷径可以额外序列化/取消引用/转义引擎盖下的 args 切片?据我了解,它本身与“PATH”不同,应该只包含一个最终目标路径,不是吗?或者我可以使用自定义的“PATH”值即时解决它。我看不出明确提供它的方法。exec.Command(os.GetEnv("SHELL"), "-c", "command with args")Cmd.Pathexec.LookPath
0赞 404 10/19/2023
或者组合真的足以满足一般需求吗?os.GetEnv("SHELL"), "-c"cross shell
0赞 maxm 10/19/2023
是的,如果你这样做,你应该能够检查的值,它将是你尝试调用的可执行文件的绝对路径。如果它不是您期望的样子,您可以将其设置为其他内容。我同意没有办法控制正在访问的 PATH,如果您想对运行的内容进行非常精细的控制,我可能会考虑手动填充 Cmd。cmd, _ := exec.Command("theExecutable")cmd.Pathexec.LookPath