30

我的Golang热重载工具Air不好使了

 3 years ago
source link: https://blog.huoding.com/2020/08/23/843
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

我使用 VSCode Remote-Containters 作为 golang 开发环境,因为生产环境使用的镜像主要是 alpine,所以开发环境自然而然使用了 golang:alpine,对应 Dockerfile 的内容如下:

FROM golang:alpine
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.cloud.tencent.com/g' /etc/apk/repositories
RUN apk add alpine-sdk
RUN go env -w GO111MODULE=on
RUN go env -w GOPROXY=https://goproxy.cn,direct
RUN go get github.com/cosmtrek/air

如上所示,安装了一个名为 air 的工具,熟悉 golang 的朋友都知道,它是用来实现热重载的,本来一切都正常,结果突然报错:「Setctty set but Ctty not valid in child」:

EBriq2.png!mobile

air

在 air 的 issue 里没找到对应的报告,不过在 golang 的 issue 里倒是发现了一些线索:

If tty is going to be open in the child process, then it must have a file descriptor in the child process. When using os/exec.Cmd as the creack/pty code does, tty must be in Stdin or Stdout or Stderr or ExtraFiles. If it isn’t in any of those, then it will be closed when the child process runs. If it is in one of those, that gives you the file descriptor number that you should use in Ctty.
Right now the creack code is setting Ctty to the parent’s file descriptor number. That is working (assuming that it is working) by accident. The correct fix is to ensure that tty is passed to the child somewhere, and set Ctty to the appropriate descriptor number. If it is possible for all of Stdin, Stdout, Stderr to be set, the simplest approach would be to always add tty to ExtraFiles, and set Ctty to 3. That will work for old versions of Go and also for the upcoming 1.15 release.

我只想让 air 正常工作,并不想花时间深究工作原理,好在里面提到了 creack/pty ,而 air 正好 依赖 它,于是顺藤摸瓜找到了对应的 issue ,发现此问题是新版 1.15 才出现的,并且已经 修复 了,可惜 air 没有升级 pty 版本,于是遇到 1.15 后,问题就出来了。

恰好前几天 Golang 放出来 1.15 的正式版,因为我在 Dockerfile 里使用 golang:alpine 作为标签,并没有明确版本,相当于是 latest,也就是最新版 1.15,所以触发了问题。知道了问题的缘由后,在 air 修复此问题前改用 golang:1.14.7-alpine3.12 作为标签就行了。

此问题给我提了个醒:在 Dockerfile 里要明确版本,不要使用 latest,切记!


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK