使用Go Exec库执行远程Docker命令时出现错误
解决Go执行docker远程SSH命令时的"ssh resolves to executable in current directory"错误
问题场景
手动执行以下命令可正常在树莓派远程部署容器:
docker -H ssh://pi@raspberrypi.local compose -f /tmp/code/docker-compose.yml up -d
但通过Go代码执行相同命令时,出现如下错误:
error during connect: Get "http://docker.example.com/v1.24/containers/json?all=1&filters=%7B%22label%22%3A%7B%22com.docker.compose.project%3Djanus%22%3Atrue%7D%7D": ssh resolves to executable in current directory (./ssh) exit status 1
原因分析
Go的exec.Command默认不会继承shell的完整环境变量,尤其是PATH。当docker尝试调用ssh建立远程连接时,会优先在当前工作目录查找名为ssh的文件/可执行文件,而非系统PATH中配置的ssh命令。
解决方案
方案1:指定ssh绝对路径给docker
修改docker的-H参数,通过ssh-path指定系统ssh的绝对路径(树莓派默认路径为/usr/bin/ssh):
command := "docker -H ssh://pi@raspberrypi.local?ssh-path=/usr/bin/ssh compose -f /tmp/code/docker-compose.yml up -d"
方案2:为Go命令设置完整环境变量
让exec.Command继承系统完整的环境变量,确保docker能找到系统ssh:
cmd := exec.Command(parsedCommand[0], parsedCommand[1:]...) // 继承当前进程的所有环境变量,包括正确的PATH cmd.Env = os.Environ() cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr
方案3:清理当前目录的同名文件
如果当前工作目录下存在名为ssh的文件或可执行文件,直接删除即可解决冲突。
修改后代码示例
package main import ( "fmt" "os" "os/exec" "strings" ) func parseCommand(cmd string) []string { return strings.Fields(cmd) } func main() { command := "docker -H ssh://pi@raspberrypi.local?ssh-path=/usr/bin/ssh compose -f /tmp/code/docker-compose.yml up -d" parsedCommand := parseCommand(command) fmt.Println(command) cmd := exec.Command(parsedCommand[0], parsedCommand[1:]...) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr // 可选:继承系统环境变量 // cmd.Env = os.Environ() err := cmd.Run() if err != nil { fmt.Println(err) } }
内容的提问来源于stack exchange,提问作者Vitor Estevam
相关产品推荐
相关产品推荐

