dongshuo2752 2018-10-12 07:53
浏览 694

来自Golang API的Docker exec命令

Need help.I have code to exec command from docker container. Need corrently get stdout from exec command.

execConfig:= types.ExecConfig{Tty:false,AttachStdout:true,AttachStderr:false,Cmd:command}
    respIdExecCreate,err := cli.ContainerExecCreate(context.Background(),dockerName,execConfig)
    if err != nil {
        fmt.Println(err)
    }
    respId,err:=cli.ContainerExecAttach(context.Background(),respIdExecCreate.ID,types.ExecStartCheck{})
    if err != nil {
        fmt.Println(err)
    }
    scanner := bufio.NewScanner(respId.Reader)
    for scanner.Scan() {
       fmt.Println(output)
}

From output i see interesting situation: Screen from gyazo

How corrently remove bytes ?

I send simply command := []string{"echo","-n", "hello word"}

  • 写回答

1条回答 默认 最新

  • dongzhong5833 2019-07-21 11:45
    关注

    I've faced with same issue, this is how stderr and stdout looks for me:

    StdOut: "\x01\x00\x00\x00\x00\x00\x00\thello world
    "
    StdErr: "\x01\x00\x00\x00\x00\x00\x00fError: Exec command has already run
    "
    

    I've cheched docker source code and found answer here:

    https://github.com/moby/moby/blob/8e610b2b55bfd1bfa9436ab110d311f5e8a74dcb/integration/internal/container/exec.go#L38

    looks like this leading bytes used especially for marking stdout and stderr bytes.

    And there is a library "github.com/docker/docker/pkg/stdcopy" which can split stdout and stderr from stream reader:

    type ExecResult struct {
        StdOut string
        StdErr string
        ExitCode int
    }
    
    func Exec(ctx context.Context, containerID string, command []string) (types.IDResponse, error) {
        docker, err := client.NewEnvClient()
        if err != nil {
            return types.IDResponse{}, err
        }
        defer closer(docker)
    
        config :=  types.ExecConfig{
            AttachStderr: true,
            AttachStdout: true,
            Cmd: command,
        }
    
        return docker.ContainerExecCreate(ctx, containerID, config)
    }
    
    func InspectExecResp(ctx context.Context, id string) (ExecResult, error) {
        var execResult ExecResult
        docker, err := client.NewEnvClient()
        if err != nil {
            return execResult, err
        }
        defer closer(docker)
    
        resp, err := docker.ContainerExecAttach(ctx, id, types.ExecConfig{})
        if err != nil {
            return execResult, err
        }
        defer resp.Close()
    
        // read the output
        var outBuf, errBuf bytes.Buffer
        outputDone := make(chan error)
    
        go func() {
            // StdCopy demultiplexes the stream into two buffers
            _, err = stdcopy.StdCopy(&outBuf, &errBuf, resp.Reader)
            outputDone <- err
        }()
    
        select {
        case err := <-outputDone:
            if err != nil {
                return execResult, err
            }
            break
    
        case <-ctx.Done():
            return execResult, ctx.Err()
        }
    
        stdout, err := ioutil.ReadAll(&outBuf)
        if err != nil {
            return execResult, err
        }
        stderr, err := ioutil.ReadAll(&errBuf)
        if err != nil {
            return execResult, err
        }
    
        res, err := docker.ContainerExecInspect(ctx, id)
        if err != nil {
            return execResult, err
        }
    
        execResult.ExitCode = res.ExitCode
        execResult.StdOut = string(stdout)
        execResult.StdErr = string(stderr)
        return execResult, nil
    }
    
    评论

报告相同问题?

悬赏问题

  • ¥15 如何在scanpy上做差异基因和通路富集?
  • ¥20 关于#硬件工程#的问题,请各位专家解答!
  • ¥15 关于#matlab#的问题:期望的系统闭环传递函数为G(s)=wn^2/s^2+2¢wn+wn^2阻尼系数¢=0.707,使系统具有较小的超调量
  • ¥15 FLUENT如何实现在堆积颗粒的上表面加载高斯热源
  • ¥30 截图中的mathematics程序转换成matlab
  • ¥15 动力学代码报错,维度不匹配
  • ¥15 Power query添加列问题
  • ¥50 Kubernetes&Fission&Eleasticsearch
  • ¥15 報錯:Person is not mapped,如何解決?
  • ¥15 c++头文件不能识别CDialog