解决cgi卡死问题

有几种方法可以限制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>

实施建议顺序:

  1. 立即:添加Apache RLimit配置
  2. 短期:安装并配置mod_fcgid
  3. 中期:设置系统级限制和监控脚本
  4. 长期:优化Perl CGI脚本本身

你想从哪个开始实施?建议先配置Apache的RLimit,这个最简单且立即生效。