golang读取键盘功能按键输入
需求
最近业务上需要做一个终端工具,能够直接连到docker容器中进行交互。
技术选型
docker官方提供了python sdk、go sdk和remote api。
因为我们需要提供命令行工具,因此采用golang进行开发。
遇到的问题
通过sdk可以正常和容器连接,但是在使用方向键、退格等功能按键时总是出现乱码,导致不能正常使用,
通过万能的google终于解决了golang读取输入键盘按键不能正常使用的问题,特此记录。
解决方案
go
ctx := context.Background()
// 自定义http docker client,可以使用官方推荐初始化方式
// cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
client, err := cmdutil.NewDockerTcpClient(task.ExecNode, GetApiPort())
waiter, err := client.ContainerAttach(ctx, task.Info.ID, types.ContainerAttachOptions{
Stderr: true,
Stdout: true,
Stdin: true,
Stream: true,
})
go io.Copy(os.Stdout, waiter.Reader)
go io.Copy(os.Stderr, waiter.Reader)
// "golang.org/x/crypto/ssh/terminal"
//此处是关键,需要将标准输入转成标准终端输入
fd := os.Stdin.Fd()
if terminal.IsTerminal(int(fd)) {
oldState, err := terminal.MakeRaw(int(fd))
if err != nil {
zap.S().Fatalln(err)
}
defer terminal.Restore(int(fd), oldState)
}
go io.Copy(waiter.Conn, os.Stdin)
if err != nil {
panic(err)
}
//此处将阻塞直到容器被释放
statusCh, errCh := client.ContainerWait(ctx, task.Info.ID, container.WaitConditionNotRunning)
select {
case err := <-errCh:
if err != nil {
panic(err)
}
case <-statusCh:
}
return err
参考: