深入理解PHP原理之Session Gc的一个小概率Notice


Posted in PHP onApril 12, 2011

如果在ubuntu/Debian下, 采用apt安装的PHP, 那么在使用Session的时候, 就可能会有小概率遇到这个提示.

PHP Notice: session_start(): ps_files_cleanup_dir: 
opendir(/var/lib/php5) failed: Permission denied (13) 
in /home/laruence/www/htdocs/index.php on line 22

这是因为, 在PHP中, 如果使用file_handler作为Session的save handler, 那么就有概率在每次session_start的时候运行Session的Gc过程.
//有省略 
int nrdels = -1; 
nrand = (int) ((float) PS(gc_divisor) * php_combined_lcg(TSRMLS_C)); 
if (nrand < PS(gc_probability)) { 
PS(mod)->s_gc(&PS(mod_data), PS(gc_maxlifetime), &nrdels TSRMLS_CC); 
} 
//有省略

这个警告的原因是因为在apt的PHP中, session的默认目录/var/lib/php5的权限是733 with sticky bit, 也就是
drwx-wx-wt root roo

而一般PHP的worker都运行在非root身份下, 所以是没有权限来打开这个文件夹的(但是因为可以write, 所以不影响正常的Session文件读取). 于是在s_gc中的如下代码, 就会触发开头所说的Notice:
//对于file handler来说, s_gc间接调用ps_files_cleanup_dir: 
dir = opendir(dirname); 
if (!dir) { 
php_error_docref(NULL TSRMLS_CC, E_NOTICE, 
"ps_files_cleanup_dir: opendir(%s) failed: %s (%d)", 
dirname, strerror(errno), errno); 
return (0); 
}

当然, 在ubuntu/Debian下, 还是有gc回收的, 只不过是外部的cron进程来完成的, 默认的在/etc/cron.d/php5:,
09,39 * * * * root [ -x /usr/lib/php5/maxlifetime ] 
&& [ -d /var/lib/php5 ] && find /var/lib/php5/ 
-type f -cmin +$(/usr/lib/php5/maxlifetime) -print0 
| xargs -n 200 -r -0 r

另外, 可以看到, 在判别s_gc是否运行的时候, 有俩个关键变量: PS(gc_divisor)和PS(gc_probability), 这俩个变量分别对应着session的运行时配置项的俩个同名配置项:
session.gc_probability和session.gc_divisor, 他们分别默认为1和100.
而php_combined_lcg是一个随机数发生器, 生成0到1范围的随机数, 所以上面的判别相当于:
rand < probability / gc_diviso

也就是说, 默认情况下, 差不多是100次能调用一次gc过程. 所以也就是小概率的可以看到这个Notice.
要关闭这个Notice, 只需要设置:
session.gc_probability = 0, 让s_gc完全没有运行的可能即可.
当然, 你也可以改变这个文件夹的权限…
最后, 感谢CFC4N提供这个问题.
作者: Laruence( )
本文地址: http://www.laruence.com/2011/03/29/1949.html
PHP 相关文章推荐
PHP操作mysql函数详解,mysql和php交互函数
May 19 PHP
redis 队列操作的例子(php)
Apr 12 PHP
解析thinkphp中的M()与D()方法的区别
Jun 22 PHP
phpmailer中文乱码问题的解决方法
Apr 22 PHP
php实现转换html格式为文本格式的方法
May 16 PHP
php实现基于openssl的加密解密方法
Sep 30 PHP
php根据年月获取当月天数及日期数组的方法
Nov 30 PHP
PHP通过curl获取接口URL的数据方法
May 31 PHP
PHP date()格式MySQL中插入datetime方法
Jan 29 PHP
TP5框架实现的数据库备份功能示例
Apr 05 PHP
PHP优化之批量操作MySQL实例分析
Apr 23 PHP
php框架知识点的整理和补充
Mar 01 PHP
php表单提交问题的解决方法
Apr 12 #PHP
使用NetBeans + Xdebug调试PHP程序的方法
Apr 12 #PHP
php产生随机数的两种方法实例代码 输出随机IP
Apr 08 #PHP
PHP随机数生成代码与使用实例分析
Apr 08 #PHP
PHP的cURL库功能简介 抓取网页、POST数据及其他
Apr 07 #PHP
php curl 登录163邮箱并抓取邮箱好友列表的代码(经测试)
Apr 07 #PHP
The specified CGI application misbehaved by not returning a complete set of HTTP headers
Mar 31 #PHP
You might like
PHP 函数学习简单小结
2010/07/08 PHP
PHP访问MYSQL数据库封装类(附函数说明)
2010/12/04 PHP
php实现的支持imagemagick及gd库两种处理的缩略图生成类
2014/09/23 PHP
用PHP生成excel文件到指定目录
2015/06/22 PHP
iOS10推送通知开发教程
2016/09/19 PHP
PHP rmdir()函数的用法总结
2019/07/02 PHP
JS+CSS制作DIV层可(最小化/拖拽/排序)功能实现代码
2013/02/25 Javascript
JSON+JavaScript处理JSON的简单例子
2013/03/20 Javascript
深入理解Javascript动态方法调用与参数修改的问题
2013/12/10 Javascript
jsPDF生成pdf后在网页展示实例
2014/01/16 Javascript
jquery分页插件jpaginate在IE中不兼容问题
2014/04/22 Javascript
JQuery实现表格动态增加行并对新行添加事件
2014/07/30 Javascript
让JavaScript的Alert弹出框失效的方法禁止弹出警告框
2014/09/03 Javascript
JavaScript中使用Math.PI圆周率属性的方法
2015/06/14 Javascript
JavaScript字符串常用的方法
2016/03/10 Javascript
JavaScript定义全局对象的方法示例
2017/01/12 Javascript
jquery表单验证实例仿Toast提示效果
2017/03/03 Javascript
在vue中,v-for的索引index在html中的使用方法
2018/03/06 Javascript
JS基于Location实现访问Url、重定向及刷新页面的方法分析
2018/12/03 Javascript
微信小程序实现获取用户信息并存入数据库操作示例
2019/05/07 Javascript
实例分析JS中的相等性判断===、 ==和Object.is()
2019/11/17 Javascript
最近Python有点火? 给你7个学习它的理由!
2017/06/26 Python
Python中的默认参数实例分析
2018/01/29 Python
Flask之flask-script模块使用
2018/07/26 Python
在python中实现同行输入/接收多个数据的示例
2019/07/20 Python
python实现一次性封装多条sql语句(begin end)
2020/06/06 Python
生物科学专业个人求职信范文
2013/12/05 职场文书
大学生职业规划范文:象牙塔生活的四年计划
2014/01/14 职场文书
2014大学生全国两会学习心得体会
2014/03/13 职场文书
营销部内勤岗位职责
2014/04/30 职场文书
父亲节活动总结
2015/02/12 职场文书
党员转正党支部意见
2015/06/02 职场文书
化工厂员工工作总结
2015/10/15 职场文书
Python 发送SMTP邮件的简单教程
2021/06/24 Python
Python爬虫框架之Scrapy中Spider的用法
2021/06/28 Python
如何通过简单的代码描述Angular父组件、子组件传值
2022/04/07 Javascript