深入理解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 管理系统程序中的后门
Aug 05 PHP
通用PHP动态生成静态HTML网页的代码
Mar 04 PHP
9个PHP开发常用功能函数小结
Jul 15 PHP
测试PHP连接MYSQL成功与否的代码
Aug 16 PHP
php获取网卡的MAC地址支持WIN/LINUX系统
Apr 30 PHP
Windows下的PHP安装pear教程
Oct 24 PHP
PHP中Memcache操作类及用法实例
Dec 12 PHP
php简单实现发送带附件的邮件
Jun 10 PHP
PHP实现适用于自定义的验证码类
Jun 15 PHP
PHP实现路由映射到指定控制器
Aug 13 PHP
Laravel框架分页实现方法分析
Jun 12 PHP
PHP实现浏览器格式化显示XML的方法示例
Jan 22 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中HTTP方式下的Gzip压缩传输方法举偶
2007/02/15 PHP
PHP查找数值数组中不重复最大和最小的10个数的方法
2015/04/20 PHP
Yii使用migrate命令执行sql语句的方法
2016/03/15 PHP
用HTML/JS/PHP方式实现页面延时跳转的简单实例
2016/07/18 PHP
PHP类型约束用法示例
2016/09/28 PHP
Yii框架中sphinx索引配置方法解析
2016/10/18 PHP
让getElementsByName适应IE和firefox的方法
2007/09/24 Javascript
Javascript 日期对象Date扩展方法
2009/05/30 Javascript
Jquery下的26个实用小技巧(jQuery tips, tricks &amp; solutions)
2010/03/01 Javascript
jquery下checked取值问题的解决方法
2012/08/09 Javascript
刷新页面的几种方法小结(JS,ASP.NET)
2014/01/07 Javascript
使用jQuery实现返回顶部
2015/01/26 Javascript
js数组常见操作及数组与字符串相互转化实例详解
2015/11/10 Javascript
基于JavaScript如何实现ajax调用后台定义的方法
2015/12/29 Javascript
JSON+Jquery省市区三级联动
2016/01/13 Javascript
通过命令行生成vue项目框架的方法
2017/07/12 Javascript
基于Bootstrap框架菜鸟入门教程(推荐)
2017/09/17 Javascript
基于datepicker定义自己的angular时间组件的示例
2018/03/14 Javascript
Vuex实现数据共享的方法
2019/12/20 Javascript
多页vue应用的单页面打包方法(内含打包模式的应用)
2020/06/11 Javascript
Python SQLite3数据库操作类分享
2014/06/10 Python
详解Python中的Cookie模块使用
2015/07/06 Python
Python中str is not callable问题详解及解决办法
2017/02/10 Python
django创建自定义模板处理器的实例详解
2017/08/14 Python
tensorflow实现逻辑回归模型
2018/09/08 Python
使用Python的datetime库处理时间(RPA流程)
2019/11/24 Python
解决python replace函数替换无效问题
2020/01/18 Python
Python实现计算长方形面积(带参数函数demo)
2020/01/18 Python
迪拜领先运动补剂零售品牌中文站:Sporter商城
2019/08/20 全球购物
面临毕业的毕业生自荐书范文
2014/02/05 职场文书
竞选班干部演讲稿
2014/04/24 职场文书
介绍信范文大全
2015/05/07 职场文书
劳保用品管理制度范本
2015/08/06 职场文书
2016参观监狱警示教育活动心得体会
2016/01/15 职场文书
JDBC连接的六步实例代码(与mysql连接)
2021/05/12 MySQL
Pygame Time时间控制的具体使用详解
2021/11/17 Python