英文:
How to run `docker exec -it <container_name> bash -c "some commands"` using golang sdk
问题
我正在使用Golang中的Docker SDK执行docker exec
命令。
func (dn *dockerNode) execCommand(ctx context.Context, cmd []string) (*execResult, error) {
execId, err := dn.cl.ContainerExecCreate(ctx, dn.contId, types.ExecConfig{
AttachStderr: true,
AttachStdout: true,
Tty: true,
Cmd: cmd,
})
if err != nil {
return nil, fmt.Errorf(
"无法创建命令\"%s\":\n %v",
strings.Join(cmd, " "),
err,
)
}
res, err := dn.InspectExecResp(ctx, execId.ID)
if err != nil {
return nil, fmt.Errorf(
"无法执行命令\"%s\":\n %v",
strings.Join(cmd[:], " "),
err,
)
}
if res.exitCode != 0 {
return &res, fmt.Errorf(
"命令\"%s\"退出代码为%d:\n %+v",
strings.Join(cmd[:], " "),
res.exitCode,
res)
}
return &res, nil
}
这个dn.execCommand
函数对于一些基本的docker exec foo bar
格式的命令可以正常工作,但现在我想使用它来运行类似于docker exec bash -c "cd mydir && ./my_shell.sh"
的命令。这是因为cd
命令只能与docker exec bash -c
一起使用。我尝试通过以下方式传递参数:
res, err = dn.execCommand(
ctx,
[]string{
"bash",
"-c",
"\"cd mydir && ./my_shell.sh\"",
},
)
但是它给出了命令 "bash -c \"cd mydir && ./my_shell.sh\" " 退出代码为127
的错误。
我想知道如何修改原始函数以支持docker exec bash -c
的用例。
英文:
I'm using docker's sdk in golang to execute a docker exec
command.
func (dn *dockerNode) execCommand(ctx context.Context, cmd []string) (*execResult, error) {
execId, err := dn.cl.ContainerExecCreate(ctx, dn.contId, types.ExecConfig{
AttachStderr: true,
AttachStdout: true,
Tty: true,
Cmd: cmd,
})
if err != nil {
return nil, fmt.Errorf(
"cannot create command \"%s\":\n %v",
strings.Join(cmd, " "),
err,
)
}
res, err := dn.InspectExecResp(ctx, execId.ID)
if err != nil {
return nil, fmt.Errorf(
"cannot execute command \"%s\":\n %v",
strings.Join(cmd[:], " "),
err,
)
}
if res.exitCode != 0 {
return &res, fmt.Errorf(
"command \"%s\" exit with code %d:\n %+v",
strings.Join(cmd[:], " "),
res.exitCode,
res)
}
return &res, nil
}
This dn.execCommand
works fine just for some vanilla docker exec foo bar
format command, but now I'd like to use it to run something equivalent to docker exec bash -c "cd mydir && ./my_shell.sh"
. This is because the cd
command only works with docker exec bash -c
. I tried passing this with
res, err = dn.execCommand(
ctx,
[]string{
"bash",
"-c",
"\"cd mydir && ./my_shell.sh\"",
},
)
But it gave me command "bash -c "cd mydir && ./my_shell.sh" " exit with code 127
I wonder how to modify the original function to make it support the docker exec bash -c
use case.
答案1
得分: 1
你的最后一个命令有一个额外的引号层级。
command := []string{
"bash",
"-c",
"cd mydir && ./my_shell.sh",
// ^^字符串内部没有引号^^
}
如果你在主机上运行类似的命令
bash -c "cd mydir && ./my_shell.sh"
shell会将双引号字符串转换为一个单词,然后丢弃引号。你可以通过在命令行前面加上echo
来查看这一点,这样处理后的命令会被打印出来而不是执行;双引号将会消失。你运行的命令更类似于
bash -c '\'\"cd mydir && ./my_shell.sh\"\''
另外请注意,"github.com/docker/docker/api/types".ExecConfig
结构体包含一个 WorkingDir
字段,所以你也许可以避免使用这个包装器。使用脚本的 docker exec
通常也不是最佳设计,因为你需要在主机上拥有无限制的管理员级权限才能使用它,并且容器通常只运行一个进程。
英文:
Your last command has an extra layer of quotes.
command := []string{
"bash",
"-c",
"cd mydir && ./my_shell.sh",
// ^^no quotes inside string^^
}
If you were to run a similar command on the host
bash -c "cd mydir && ./my_shell.sh"
the shell would take the double-quoted string and turn it into a single word, and then discard the quotes. You can see this in part by putting the word echo
in front of the command line, so the processed command gets printed out rather than executed; the double-quotes will be gone. What you're running is more similar to
bash -c '"cd mydir && ./my_shell.sh"'
Also note that the "github.com/docker/docker/api/types".ExecConfig
structure contains a WorkingDir
field, so you might be able to avoid this wrapper. Scripting docker exec
also frequently isn't the best design, since you need unlimited administrator-level permissions over the host to use it, and since a container typically only runs one process.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论