如何让我的服务器免受来自这个Ubuntu cron作业的僵尸的破坏,去除PHP会话?

我最近注意到当我login时,我有几千个标记为“僵尸”的进程。 经过进一步调查,我从ps fax发现以下内容:

  701 ? Ss 0:28 cron 3363 ? S 0:00 \_ CRON 3364 ? Ss 0:00 \_ /bin/sh -c [ -x /usr/lib/php5/maxlifetime ] && [ -d /var/lib/php5 ] && find /var/lib/php5/ -depth -mindepth 1 -maxdepth 1 -type f -cmin +$(/usr/lib/php5/maxlifetime) ! -execdir fuser -s {} 2>/dev/null \; -delete 3371 ? S 0:00 \_ find /var/lib/php5/ -depth -mindepth 1 -maxdepth 1 -type f -cmin +24 ! -execdir fuser -s {} ; -delete 3451 ? S 0:02 \_ fuser -s ./sess_jns5af2mvm81e2fg1rbuctlt54 3452 ? Z 0:00 \_ [fuser] <defunct> 3453 ? Z 0:00 \_ [fuser] <defunct> 3454 ? Z 0:00 \_ [fuser] <defunct> ... many, many lines omitted ... 13642 ? Z 0:00 \_ [fuser] <defunct> 

据我所知,这是/etc/cron.d/php中的一个脚本,应该在每小时10分钟和40分钟清理死PHP会话。

编辑:这是脚本的文本。 它在Ubuntu上默认安装了PHP。

 # /etc/cron.d/php5: crontab fragment for php5 # This purges session files older than X, where X is defined in seconds # as the largest value of session.gc_maxlifetime from all your php.ini # files, or 24 minutes if not defined. See /usr/lib/php5/maxlifetime # Look for and purge old sessions every 30 minutes 09,39 * * * * root [ -x /usr/lib/php5/maxlifetime ] && [ -d /var/lib/php5 ] && find /var/lib/php5/ -depth -mindepth 1 -maxdepth 1 -type f -cmin +$(/usr/lib/php5/maxlifetime) ! -execdir fuser -s {} 2>/dev/null \; -delete 

出于某种原因(目前我猜测每个请求都会有一个不正常的web爬虫做一个新的会话,但是我仍然在查看日志),有时在/var/lib/php/ ,当这个脚本运行时,它会很高兴地为每个脚本产生一个新的定影过程。 这很快就达到了stream程限制,并带来了一些问题。

我可以做些什么,除了只是删除这个cron作业和手动清理东西呢?

将逻辑从find移动到脚本可能是最好的,该脚本遍历命令行中的所有文件,以查看它们是否被访问,如果不是,则删除它们:

 #!/bin/bash for x; do if ! /bin/fuser -s "$x" 2>/dev/null; then rm "$x" fi done 

然后将cron作业更改为

 09,39 * * * * root [ -x /usr/lib/php5/maxlifetime ] && [ -d /var/lib/php5 ] && find /var/lib/php5/ -depth -mindepth 1 -maxdepth 1 -type f -cmin +$(/usr/lib/php5/maxlifetime) -execdir thatscript.sh {} + 

这将find收集所有会话文件匹配的最大年龄,然后运行thatscript.sh所有他们一次(由于+而不是; )。 然后该脚本负责确保该文件未被使用并将其删除。 这样, find应该只有一个直接的孩子本身,而且bash应该没有任何问题清理fuserrm孩子。

find的文档,目前还不清楚,如果超过shell / OS的限制,是否会自动将文件名列表分成多个执行(13000个文件可以这样做…老版本的bash有默认的命令行参数限制在5000左右的地方)在这种情况下,你可能会改变-execdir thatscript.sh {} + to -print0 | xargs -0 thatscript.sh -print0 | xargs -0 thatscript.shxargs分割文件。

或者,如果您没有安装驱动器,则更改-cmin-amin并完全-cmintesting:

  09,39 * * * * root [ -x /usr/lib/php5/maxlifetime ] && [ -d /var/lib/php5 ] && find /var/lib/php5/ -depth -mindepth 1 -maxdepth 1 -type f -amin +$(/usr/lib/php5/maxlifetime) -delete 

这将删除上次访问的所有会话文件超过[分钟前maxlifetime命令的输出]。 只要你没有任何打开会话的PHP进程,那么坐下来很长一段时间(Debian上的maxlifetime默认是24分钟,这对于一个页面来说是一个长的时间)无所事事,这不应该打破目前正在使用的任何会议。

我也有这个问题在Ubuntu 11.10和我通过编辑解决了这个问题:

 /etc/cron.d/php5 

并用以下代码replace:

 09,39 * * * * root [ -x /usr/lib/php5/maxlifetime ] && [ -d /var/lib/php5 ] && find /var/lib/php5/ -depth -mindepth 1 -maxdepth 1 -type f -cmin +$(/usr/lib/php5/maxlifetime) -delete 

这是php的Ubuntu 11.04 cron作业。

修复脚本,使其等待其子项或忽略SIG_CHILD。 你能把脚本放在我们可以看到的地方吗?

更新 :看起来你正在触发一个find错误!

我通过将会话从文件系统移动到memcache来解决此问题。 他们没有僵尸进程,但仍然有无数的会话,cronjob无法跟上删除。 花费10分钟来安装memcache,重新configurationphp.ini,testing它,并添加一些munin图来观察memcache大小。 Presto – 服务器负载下降,大家高兴。

http://www.dotdeb.org/2008/08/25/storing-your-php-sessions-using-memcached/ http://www.ducea.com/2009/06/02/php-sessions-in- memcached的/

这也将是最有帮助的:

https://bugs.launchpad.net/ubuntu/+source/php5/+bug/876387

阅读评论#4和#8,后者甚至修复了热熔器本身!