Нужна помощь.У меня есть код для выполнения команды из контейнера докеров. Необходимо правильно получить стандартный вывод из команды exec.
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)
}
Из вывода я вижу интересную ситуацию: Экран от гязо
Как правильно удалить байты?
Отправляю просто команду: = [] строка {"echo", "- n", "hello word"}


Я столкнулся с той же проблемой, вот как меня выглядят stderr и stdout:
StdOut: "\x01\x00\x00\x00\x00\x00\x00\thello world\n"
StdErr: "\x01\x00\x00\x00\x00\x00\x00fError: Exec command has already run\r\n"
Я проверил исходный код докера и нашел здесь ответ:
похоже, что эти ведущие байты используются специально для маркировки байтов stdout и stderr.
И есть библиотека "github.com/docker/docker/pkg/stdcopy", которая может разделить stdout и stderr из потокового ридера:
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
}
Меня устраивает! Спасибо, что указали интеграционные тесты прямо на кодовой базе moby / moby! +1 за это. :-)