Debian Apache2 执行 Shell CGI:动态时间页面配置与验证

Debian Apache2 执行 Shell CGI:动态时间页面配置与验证

1. 服务介绍

Apache CGI(Common Gateway Interface)允许 Web 服务器把 HTTP 请求交给外部程序处理,再把程序输出返回给浏览器。本实验使用 Bash Shell 编写 CGI 脚本,动态生成包含当前系统时间的 HTML 页面。

Shell CGI 适合教学演示、简单系统状态页面和内部运维工具;不适合承载高并发业务,也不应直接执行用户提交的命令。生产环境优先使用 PHP、Python、Go 等应用运行时,并限制脚本目录和运行权限。

2. 准备运行环境

• 操作系统:Debian 10/11 或同类 Debian 系统。

• 操作账号:root 或具备 sudo 权限的管理员。

• 软件:Apache2、bash、date。

• CGI 目录:/usr/lib/cgi-bin。

• 测试 URL:http://服务器地址/cgi-bin/time.sh。

确认环境:

bash 复制代码
cat /etc/os-release
apache2ctl -v
command -v bash date
ss -lntp | grep ':80'

3. 相关知识与注意事项

3.1 CGI 响应格式

CGI 程序必须先输出响应头,再输出空行,最后输出正文:

text 复制代码
Content-Type: text/html

<html>...</html>

缺少 Content-Type 或响应头后的空行,浏览器可能返回 500 Internal Server Error。

3.2 CGI 配置范围

• ExecCGI:允许目录中的文件作为 CGI 执行。

• AddHandler cgi-script .sh:把 .sh 文件交给 CGI 处理。

• ScriptAlias:把 URL 路径映射到 CGI 目录,并默认启用 CGI 语义。

• Require all granted:允许客户端访问该目录。

推荐只使用独立 CGI 目录和 .cgi 扩展名。若必须执行 .sh,只在专用目录配置,不要对整个网站根目录全局开放 Shell 执行。

3.3 安全注意事项

• CGI 脚本由 Apache 工作进程执行,脚本权限和进程权限决定风险范围。

• 脚本不要拼接或执行未经校验的 URL 参数、Cookie 或请求头。

• 关闭目录索引:使用 Options -Indexes。

• 脚本文件归属 root,权限建议 0755 或更严格;不需要写入权限。

• CGI 访问日志和错误日志必须保留,便于排查脚本退出码和权限问题。

• 修改配置后先运行语法检查,再 reload Apache2。

4. 实验步骤

4.1 安装并启用 CGI 模块

bash 复制代码
apt update
apt install -y apache2
a2enmod cgid
systemctl enable --now apache2

Debian prefork MPM 通常使用 mod_cgi;event/worker MPM 通常使用 mod_cgid。以 apache2ctl -M 的实际结果为准:

bash 复制代码
apache2ctl -M | grep -E 'cgi|cgid'

4.2 创建 Shell CGI 脚本

bash 复制代码
install -d -o root -g root -m 0755 /usr/lib/cgi-bin
cat > /usr/lib/cgi-bin/time.sh <<'EOF'
#!/bin/bash
set -eu

printf 'Content-Type: text/html; charset=UTF-8\n\n'
printf '<!doctype html><html><body>\n'
printf '<h1>Current system time is: %s</h1>\n' "$(date '+%Y/%m/%d %r')"
printf '</body></html>\n'
EOF
chown root:root /usr/lib/cgi-bin/time.sh
chmod 0755 /usr/lib/cgi-bin/time.sh

原截图中的脚本使用 Echo 和不规范引号。Shell 命令区分大小写,实际应使用小写 echo 或 printf;本文使用 printf,避免引号和转义混乱。

4.3 配置专用 CGI 目录

Debian 默认 ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/ 通常已经配置。先检查:

bash 复制代码
grep -R "ScriptAlias.*cgi-bin" /etc/apache2

若没有,创建 /etc/apache2/conf-available/local-cgi.conf:

apache 复制代码
ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/

<Directory "/usr/lib/cgi-bin">
    Options +ExecCGI -Indexes
    AllowOverride None
    Require all granted
    AddHandler cgi-script .cgi .sh
</Directory>

启用配置:

bash 复制代码
a2enconf local-cgi
apache2ctl configtest
systemctl reload apache2

原实验站点配置启用了 ExecCGI 并把 .sh 注册为 CGI:

旧配置可能同时启用 Indexes。专用 CGI 目录不需要目录索引,建议改为 -Indexes。

4.4 检查配置并访问页面

bash 复制代码
apache2ctl configtest
systemctl reload apache2
curl -i http://127.0.0.1/cgi-bin/time.sh

若服务器有域名,使用 Host 头验证对应虚拟主机:

bash 复制代码
curl -i -H 'Host: www.example.test' http://127.0.0.1/cgi-bin/time.sh

浏览器访问:

text 复制代码
http://服务器地址/cgi-bin/time.sh

页面应显示当前系统时间。刷新页面后,时间随服务器当前时间变化。

5. 验证结果

5.1 检查模块、监听和服务状态

bash 复制代码
apache2ctl -M | grep -E 'cgi|cgid'
apache2ctl configtest
systemctl status apache2 --no-pager
ss -lntp | grep ':80'

5.2 检查 HTTP 响应

bash 复制代码
curl -sS -D - http://127.0.0.1/cgi-bin/time.sh -o /tmp/time.html
grep -E 'HTTP/|Content-Type' /tmp/time.html
cat /tmp/time.html

正确结果应包含 200 OK、Content-Type: text/html 和当前时间文本。未找到脚本时返回 404;无执行权限或脚本错误时常见返回 403/500。

5.3 查看 CGI 错误日志

bash 复制代码
tail -n 50 /var/log/apache2/error.log
tail -n 50 /var/log/apache2/access.log
journalctl -u apache2 -n 50 --no-pager

验证成功条件:模块已加载、配置检查为 Syntax OK、脚本返回 200、响应头先于正文输出、日志没有 CGI 执行错误。

6. 常见问题与排错

6.1 返回 403 Forbidden

bash 复制代码
namei -l /usr/lib/cgi-bin/time.sh
ls -l /usr/lib/cgi-bin/time.sh

检查脚本是否有执行权限、父目录是否可遍历、<Directory> 是否包含 ExecCGI 和 Require all granted。

6.2 返回 500 Internal Server Error

bash 复制代码
bash -n /usr/lib/cgi-bin/time.sh
/usr/lib/cgi-bin/time.sh
tail -n 50 /var/log/apache2/error.log

命令行直接运行时应先看到 Content-Type,再看到 HTML。检查 shebang、换行格式、引号和响应头空行。

6.3 页面下载脚本而不是执行

bash 复制代码
apache2ctl -M | grep -E 'cgi|cgid'
apache2ctl -t -D DUMP_RUN_CFG
grep -R 'AddHandler\|ScriptAlias\|ExecCGI' /etc/apache2

确认 CGI 模块已启用,URL 命中 CGI 目录,扩展名已注册为 cgi-script。

6.4 回退配置

bash 复制代码
a2disconf local-cgi
rm -f /usr/lib/cgi-bin/time.sh
apache2ctl configtest
systemctl reload apache2

删除脚本前保留配置和错误日志,便于核对访问记录和故障原因。

相关推荐
Ruiery41 分钟前
Linux 6.6内核 CPU 深度解析(七):调度器启动 — 从单核到多核,调度器分阶段点亮
linux·运维·服务器
50万马克的面包44 分钟前
CSDN-栈队列数组-知识点整理
linux·运维·服务器
MicrosoftCloud1 小时前
用户权限 04|/etc/sudoers 安全配置:从最小授权到「别把 ALL 随便给人」
运维·安全·ubuntu·sudo·sudoers
wjkjpcba2 小时前
PCBA烧录程序是什么:PCBA包工包料厂家解析烧录与测试
linux·数据库·人工智能·smt贴片加工·pcba贴片加工厂
꯭自꯭闭꯭2 小时前
达梦事物特性及MVCC
linux·运维·数据库
亚川楼宇自控系统数据中心厂家4 小时前
实验室智能化管理系统|人环物智一体化管控平台
运维
羔羊++4 小时前
18_实验十七_其他命令与自定义启动变量
linux
zmsup5 小时前
Agent 上下文调优:结合 OpsArk 运维智能体,设计模型每一步真正需要的信息
运维·agent·上下文压缩·运维智能体·上下文调优
DYWorker0016 小时前
Linux驱动:RK3568 GMAC + YT8531C 千兆以太网全流程解剖
linux
吴声子夜歌8 小时前
Nginx应用与运维——Nginx负载均衡应用实战(二)
运维·nginx·负载均衡