有几种方法可以限制CGI资源使用,我按照实施难易程度来介绍:
1. Apache配置级别限制(推荐优先使用)
在Apache配置文件中添加:
apache
# 在 /etc/apache2/sites-available/your-site.conf 或主配置文件中
<Directory "/var/www/cgi-bin">
Options +ExecCGI
SetHandler cgi-script
# 限制CPU时间(秒)
RLimitCPU 30 60 # 软限制30秒,硬限制60秒
# 限制内存使用(字节)
RLimitMEM 67108864 134217728 # 64MB-128MB
# 限制进程数
RLimitNPROC 5 10 # 每个CGI最多5个子进程,硬限制10个
</Directory>
# 全局超时设置
Timeout 30 # 降低到30秒
KeepAliveTimeout 5 # 减少长连接时间
2. 使用 mod_fcgid(强烈推荐)
安装和配置FastCGI:
bash
# 安装mod_fcgid
sudo a2enmod fcgid
sudo a2dismod cgi
# 重启Apache
sudo systemctl restart apache2
配置fcgid:
apache
# 在配置文件中添加
<IfModule mod_fcgid.c>
# 最大进程数
FcgidMaxProcesses 20
# 每个应用最大进程数
FcgidMaxProcessesPerClass 5
# 最小进程数
FcgidMinProcessesPerClass 1
# 空闲超时时间(秒)
FcgidIdleTimeout 60
# 进程生命周期(秒)
FcgidProcessLifeTime 120
# 最大请求数后重启进程
FcgidMaxRequestsPerProcess 100
# IO超时
FcgidIOTimeout 40
</IfModule>
3. 系统级别限制
创建CGI专用用户:
bash
# 创建专用用户
sudo useradd -r -s /bin/false cgiuser
# 设置用户资源限制
sudo nano /etc/security/limits.conf
在limits.conf中添加:
# 限制cgiuser用户资源
cgiuser soft nproc 10 # 最多10个进程
cgiuser hard nproc 20 # 硬限制20个进程
cgiuser soft nofile 100 # 最多100个文件描述符
cgiuser hard nofile 200 # 硬限制200个文件描述符
cgiuser soft cpu 2 # CPU时间限制2分钟
cgiuser hard cpu 5 # 硬限制5分钟
cgiuser soft as 134217728 # 虚拟内存限制128MB
cgiuser hard as 268435456 # 硬限制256MB
4. 监控和自动清理脚本
创建监控脚本:
bash
sudo nano /usr/local/bin/cgi_monitor.sh
bash
#!/bin/bash
# CGI进程监控和清理脚本
MAX_CGI_PROCESSES=10
MAX_MEMORY_PERCENT=80
# 检查CGI进程数量
CGI_COUNT=$(ps aux | grep -c '[p]erl.*\.cgi')
if [ $CGI_COUNT -gt $MAX_CGI_PROCESSES ]; then
echo "$(date): Too many CGI processes ($CGI_COUNT), killing oldest ones"
# 杀死运行时间最长的CGI进程
ps aux --sort=time | grep '[p]erl.*\.cgi' | head -5 | awk '{print $2}' | xargs kill
fi
# 检查内存使用率
MEMORY_USAGE=$(free | grep Mem | awk '{printf("%.0f", $3/$2 * 100.0)}')
if [ $MEMORY_USAGE -gt $MAX_MEMORY_PERCENT ]; then
echo "$(date): High memory usage ($MEMORY_USAGE%), killing CGI processes"
pkill -f 'perl.*\.cgi'
fi
设置定时任务:
bash
sudo chmod +x /usr/local/bin/cgi_monitor.sh
sudo crontab -e
# 添加以下行,每2分钟检查一次
*/2 * * * * /usr/local/bin/cgi_monitor.sh >> /var/log/cgi_monitor.log 2>&1
5. 临时紧急措施
如果系统已经出现问题:
bash
# 立即杀死所有CGI进程
sudo pkill -f 'perl.*\.cgi'
# 重启Apache
sudo systemctl restart apache2
# 临时降低Apache进程数
sudo nano /etc/apache2/mods-available/mpm_prefork.conf
修改为:
apache
<IfModule mpm_prefork_module>
StartServers 2
MinSpareServers 2
MaxSpareServers 5
MaxRequestWorkers 20 # 大幅降低
MaxConnectionsPerChild 100
</IfModule>
实施建议顺序:
你想从哪个开始实施?建议先配置Apache的RLimit,这个最简单且立即生效。