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.
CodePudding user response:
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.