如何使用Golang SDK运行`docker exec -it bash -c “some commands”`命令。

huangapple go评论89阅读模式
英文:

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(
			&quot;cannot create command \&quot;%s\&quot;:\n %v&quot;,
			strings.Join(cmd, &quot; &quot;),
			err,
		)
	}

	res, err := dn.InspectExecResp(ctx, execId.ID)
	if err != nil {
		return nil, fmt.Errorf(
			&quot;cannot execute command \&quot;%s\&quot;:\n %v&quot;,
			strings.Join(cmd[:], &quot; &quot;),
			err,
		)
	}

	if res.exitCode != 0 {
		return &amp;res, fmt.Errorf(
			&quot;command \&quot;%s\&quot; exit with code %d:\n %+v&quot;,
			strings.Join(cmd[:], &quot; &quot;),
			res.exitCode,
			res)
	}

	return &amp;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 &quot;cd mydir &amp;&amp; ./my_shell.sh&quot;. This is because the cd command only works with docker exec bash -c. I tried passing this with

	res, err = dn.execCommand(
		ctx,
		[]string{
			&quot;bash&quot;,
			&quot;-c&quot;,
		    &quot;\&quot;cd mydir &amp;&amp; ./my_shell.sh\&quot;&quot;,
		},
	)

But it gave me command &quot;bash -c &quot;cd mydir &amp;&amp; ./my_shell.sh&quot; &quot; 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{
        &quot;bash&quot;,
        &quot;-c&quot;,
        &quot;cd mydir &amp;&amp; ./my_shell.sh&quot;,
//      ^^no quotes inside string^^
}

If you were to run a similar command on the host

bash -c &quot;cd mydir &amp;&amp; ./my_shell.sh&quot;

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 &#39;&quot;cd mydir &amp;&amp; ./my_shell.sh&quot;&#39;

Also note that the &quot;github.com/docker/docker/api/types&quot;.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.

huangapple
  • 本文由 发表于 2021年12月20日 12:25:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/70417373.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定