Home  >  Article  >  Backend Development  >  How to remove cursor position ANSI escape code from "HijackedResponse" in Go?

How to remove cursor position ANSI escape code from "HijackedResponse" in Go?

PHPz
PHPzforward
2024-02-09 09:42:19632browse

如何从 Go 中的“HijackedResponse”中删除光标位置 ANSI 转义代码?

In Go language development, sometimes we may encounter the need to delete the ANSI escape code at the cursor position from "HijackedResponse". These escape codes are usually used to display colored text on the terminal or control the cursor position, but in some cases we may need to remove them. This article will introduce how to remove these ANSI escape codes from "HijackedResponse" by using the Go language's string manipulation functions and regular expressions. Whether you are a beginner of Go language or an experienced developer, this article will help you solve this problem.

Question content

I am trying to use go to execute (interactively) a docker container. This is the code I'm using:

func (docker *docker) redirectresponsetooutputstream(outputstream, errorstream io.writer, resp io.reader) error {
    _, err := stdcopy.stdcopy(outputstream, errorstream, resp)
    return err
}

func (docker *docker) holdhijackedconnection(inputstream io.reader, outputstream, errorstream io.writer, resp types.hijackedresponse) error {
    receivestdout := make(chan error)
    if outputstream != nil || errorstream != nil {
        go func() {
            receivestdout <- docker.redirectresponsetooutputstream(outputstream, errorstream, resp.reader)
        }()
    }

    stdindone := make(chan struct{})
    go func() {
        if inputstream != nil {
            io.copy(resp.conn, inputstream)
        }
        resp.closewrite()
        close(stdindone)
    }()

    select {
    case err := <-receivestdout:
        return err
    case <-stdindone:
        if outputstream != nil || errorstream != nil {
            return <-receivestdout
        }
    }

    return nil
}

...and call holdhijackedconnection here:

func (docker *Docker) ContainerExec(ctx context.Context, container *injection.Container) error {
    createResponse, err := docker.client.ContainerExecCreate(ctx, container.ID, types.ExecConfig{
        AttachStdout: true,
        AttachStderr: true,
        AttachStdin:  true,
        Detach:       true,
        Tty:          true,
        Cmd:          []string{"sh"},
    })
    if err != nil {
        return err
    }

    stream, err := docker.client.ContainerExecAttach(ctx, createResponse.ID, types.ExecStartCheck{})
    if err != nil {
        return err
    }

    defer stream.Close()
    docker.holdHijackedConnection(os.Stdin, os.Stdout, os.Stderr, stream)
    return nil
}

Some notes:

  • sh is required, it is a mountain image
  • injection.container Just saves information about the container, it is a custom structure
  • docker is a structure used to save the docker client (an instance of client from github.com/docker/docker/client)

If I execute my application, the cli result I get is this:

/usr/app $ ^[[43;12r

As far as I know, ^[[43;12r is the ansi escape code for the cursor position. I can execute commands like ls or npm i etc. but I always get back these ansi escape codes.

My question is, is there a way to remove them from the standard output?

Solution

I finally found it.

The problem is that I should use the github.com/docker/cli/cli/command package and its dockercli instead of os.std... . This manages this issue for me by setting up the output, error and input streams like this:

func (docker *Docker) holdHijackedConnection(resp types.HijackedResponse) error {
    cli, _ := command.NewDockerCli()
    outputStream := cli.Out()
    errorStream := cli.Err()
    inputStream := cli.In()

    inputStream.SetRawTerminal()
    defer inputStream.RestoreTerminal()

    receiveStdout := make(chan error)
    if outputStream != nil || errorStream != nil {
        go func() {
            receiveStdout <- docker.redirectResponseToOutputStream(outputStream, errorStream, resp.Reader)
        }()
    }

    stdinDone := make(chan struct{})
    go func() {
        if inputStream != nil {
            io.Copy(resp.Conn, inputStream)
        }
        resp.CloseWrite()
        close(stdinDone)
    }()

    select {
    case err := <-receiveStdout:
        return err
    case <-stdinDone:
        if outputStream != nil || errorStream != nil {
            return <-receiveStdout
        }
    }

    return nil
}

If you want to add ctrl c escape, you need to set detachkeys in execconfig at containerexeccreate. Otherwise executing exit will detach it.

The above is the detailed content of How to remove cursor position ANSI escape code from "HijackedResponse" in Go?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:stackoverflow.com. If there is any infringement, please contact admin@php.cn delete