
go 编写的 cgi 程序是二进制可执行文件,非脚本,无需解释器;apache 需启用 execcgi 并正确设置文件权限(如 755),而非依赖 addhandler 绑定扩展名。
在 Apache 中运行 Go 编写的 CGI 程序,关键在于理解其本质:Go 程序编译后是静态链接的 Unix 可执行文件(ELF 格式),不是需解释器执行的脚本(如 Python/Perl)。因此,AddHandler cgi-script .go 或 .exe 不仅无效,反而可能误导 Apache 尝试用脚本方式处理二进制文件,导致浏览器直接下载而非执行。
✅ 正确配置步骤如下:
确保 CGI 模块已启用
运行 a2enmod cgi(Debian/Ubuntu)或确认 LoadModule cgi_module modules/mod_cgi.so 在 httpd.conf 中未被注释。-
使用标准 cgi-bin 目录(推荐)
Apache 默认对 /cgi-bin/ 启用 ExecCGI,无需额外 AddHandler。将编译好的 Go 程序(如 hello.cgi)放入该目录:sudo cp ./hello /usr/lib/cgi-bin/hello.cgi sudo chmod 755 /usr/lib/cgi-bin/hello.cgi
⚠️ 注意:文件名后缀 .cgi 仅为约定,无实际作用;Apache 依据目录权限和 Options +ExecCGI 判断是否可执行,不依赖扩展名。
-
若必须自定义 CGI 目录(如 /var/www/html/cgi),请精简配置
移除无效的 AddHandler,仅保留权限与执行控制:Options +ExecCGI AddHandler cgi-script .cgi # 仅用于显式标识(可选),但非必需 Require all granted # 不要写 .go/.exe —— Go 二进制无需解释器 ? 关键点:AddHandler 在此场景中仅起“标记”作用,真正触发执行的是 Options +ExecCGI 和文件可执行权限(x 位)。
-
Go 程序需符合 CGI 规范
必须输出标准 HTTP 头(至少 Content-Type)并换行后输出正文:package main import ( "fmt" "os" ) func main() { fmt.Println("Content-Type: text/plain\n") // 注意两个换行符 fmt.Println("Hello from Go CGI!") }编译时建议静态链接,避免部署环境缺失动态库:
CGO_ENABLED=0 go build -o hello.cgi hello.go
-
权限与 SELinux(如启用)
- 文件权限必须为 755(所有者可读写执行,组/其他可读执行);
- 若使用 SELinux(如 CentOS/RHEL),需确保上下文允许执行:
sudo chcon -t httpd_exec_t /var/www/html/cgi/hello.cgi
? 总结:
- ❌ 不要为 Go 二进制添加 .go/.exe 等 AddHandler —— 它们不是脚本;
- ✅ 用 chmod 755 赋予执行权,配合 Options +ExecCGI;
- ✅ 优先使用标准 cgi-bin 目录,降低跨服务器迁移风险;
- ✅ Go 程序需输出合法 CGI 响应头,且推荐 CGO_ENABLED=0 静态编译。
配置完成后,访问 http://yoursite/cgi-bin/hello.cgi 即可看到输出,而非文件下载。










