air默认只监听.go文件,需在.air.toml的[watch]和[build]节显式配置include_ext=["go","yaml","yml","html","tmpl"];build.bin必须与build.cmd输出路径严格一致;改配置后须手动重启air。
直接用 air 启动默认只监听 .go 文件,改了 config.yaml 或 templates/index.html 完全没反应——这不是 bug,是它压根没被配置成监听这些后缀。
为什么改了非 .go 文件 air 不重启?
air 默认只 watch .go 后缀,连 go.mod 都不监听,更别说 YAML、HTML、TOML 了。它定位是 Go 代码热重载工具,不是全栈 Live Reload。
- 现象:改完
config.yaml保存,终端毫无动静;air -v显示版本但构建日志没刷新 - 原因:watch 配置里没声明这些扩展名,inotify 根本不注册对应文件事件
- 解决:必须在
.air.toml的[watch]和[build]两节都加include_ext = ["go", "yaml", "yml", "html", "tmpl"] - 注意:
include_ext是白名单,不是追加——漏写go就连main.go都不监听
build.bin 和 cmd 输出路径不一致导致 exec: "./tmp/main": file does not exist
这是 air 启动失败最常卡住的地方:它按 build.bin 去执行,但 build.cmd 没真把二进制写到那儿。
-
build.cmd = "go build -o ./tmp/main ."→ 输出路径是./tmp/main -
build.bin必须严格等于"./tmp/main",不能是"tmp/main"(少.)或"./tmp/main.exe"(Windows 没配后缀) - Linux/macOS 上如果
./tmp目录不可写,或go build输出的文件没+x权限,也会报这个错 - 稳妥写法:
build.cmd = "go build -o ./tmp/main . && chmod +x ./tmp/main"
air 启动后改代码没反应,ps 看不到进程,端口还占着
本质是旧进程没被正确终止,air 发了 SIGTERM,但你的程序没处理它,就僵在那儿了。
Content at Scale
SEO长内容自动化创作平台
下载
立即学习“go语言免费学习笔记(深入)”;
- Go 程序必须显式调用
http.Server.Shutdown(),否则os.Interrupt信号不会触发 graceful shutdown - 检查
build.delay是否太小(比如设成100),导致新进程还没起来,旧进程还没关完,端口就被抢 - 手动清理残留:
pkill -f 'tmp/main'(macOS/Linux)或taskkill /F /IM main.exe(Windows) - 别依赖
air init生成的默认配置——它不包含kill_delay,而某些框架启动慢,需要留出关闭时间
Windows 上 fork/exec: permission denied 怎么办?
不是权限设置问题,是 Windows Defender 或组策略拦截了未签名的临时可执行文件运行。
- 临时方案:把
build.bin改成"./tmp/main.exe",build.cmd对应改成"go build -o ./tmp/main.exe ." - 更稳做法:把
./tmp目录加进 Windows Defender 排除列表(不是关防护) - 避免用
brew install air或旧版go get,统一用go install github.com/cosmtrek/air@latest - 路径分隔符必须用
/或\,单个在 TOML 里会被解析为转义字符
真正容易被忽略的是:air 不 reload 自身配置。改完 .air.toml 必须 Ctrl+C 再 air 重启,它不会感知自己配置文件的变化。