Maison  >  Article  >  développement back-end  >  Comment supprimer le code d'échappement ANSI de la position du curseur de « HijackedResponse » dans Go ?

Comment supprimer le code d'échappement ANSI de la position du curseur de « HijackedResponse » dans Go ?

PHPz
PHPzavant
2024-02-09 09:42:19630parcourir

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

Dans le développement du langage Go, nous pouvons parfois rencontrer la nécessité de supprimer le code d'échappement ANSI de la position du curseur de "HijackedResponse". Ces codes d'échappement sont généralement utilisés pour afficher du texte en couleur sur le terminal ou contrôler la position du curseur, mais dans certains cas, nous devrons peut-être les supprimer. Cet article explique comment supprimer ces codes d'échappement ANSI de « HijackedResponse » en utilisant les fonctions de manipulation de chaînes et les expressions régulières du langage Go. Que vous soyez débutant en langage Go ou développeur expérimenté, cet article vous aidera à résoudre ce problème.

Contenu de la question

J'essaie d'exécuter (de manière interactive) un conteneur Docker en utilisant go. Voici le code que j'utilise :

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
}

...et appelez holdhijackedconnection ici :

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
}

Quelques remarques :

  • sh est obligatoire, c'est une image de montagne
  • injection.container Enregistre simplement les informations sur le conteneur, c'est une structure personnalisée
  • docker 是一个结构体,用于保存 docker 客户端(来自 github.com/docker/docker/client 的 clientexemple)

Si j'exécute mon application, le résultat cli que j'obtiens est le suivant :

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

Pour autant que je sache, ^[[43;12r est le code d'échappement ansi pour la position du curseur. Je peux exécuter des commandes comme lsnpm i etc. mais je récupère toujours ces codes d'échappement ansi.

Ma question est la suivante : existe-t-il un moyen de les supprimer de la sortie standard ?

La solution

Je l'ai enfin trouvée.

La question est : dois-je utiliser github.com/docker/cli/cli/command 包及其 dockercli 而不是 os.std.... Cela gère cela pour moi en configurant les flux de sortie, d'erreur et d'entrée comme ceci :

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
}

Si vous souhaitez ajouter ctrl+c escape, vous devez le séparer en containerexeccreate处的execconfig中设置detachkeys。否则执行 exit.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer