深入理解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 相关文章推荐
PHPMailer 中文使用说明小结
Jan 22 PHP
PHP开发中四种查询返回结果分析
Jan 02 PHP
PHP flock 文件锁详细介绍
Dec 29 PHP
PHP中::、-&amp;gt;、self、$this几种操作符的区别介绍
Apr 24 PHP
探讨:如何编写PHP扩展
Jun 13 PHP
ThinkPHP3.1新特性之动态设置自动完成和自动验证示例
Jun 19 PHP
PHP使用feof()函数读文件的方法
Nov 07 PHP
php循环table实现一行两列显示的方法
Jun 04 PHP
php类的扩展和继承用法实例
Jun 20 PHP
Laravel中Facade的加载过程与原理详解
Sep 22 PHP
PHP使用星号替代用户名手机和邮箱的实现代码
Feb 07 PHP
ThinkPHP框架实现定时执行任务的两种方法分析
Sep 04 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下使用SMTP发邮件的代码
2008/01/10 PHP
PHP中的MYSQL常用函数(php下操作数据库必备)
2010/09/12 PHP
PHP 5.3 下载时 VC9、VC6、Thread Safe、Non Thread Safe的区别分析
2011/03/28 PHP
PHP中substr_count()函数获取子字符串出现次数的方法
2016/01/07 PHP
PHP文件上传类实例详解
2016/04/08 PHP
RR vs IO BO3 第一场2.13
2021/03/10 DOTA
Aster vs Newbee BO5 第一场2.19
2021/03/10 DOTA
js右键菜单效果代码
2007/07/21 Javascript
FLASH 广告之外的链接
2008/12/16 Javascript
javascript 写类方式之八
2009/07/05 Javascript
AJAX异步从优酷专辑中采集所有视频及信息(JavaScript代码)
2010/11/20 Javascript
javascript 循环调用示例介绍
2013/11/20 Javascript
Jquery 分页插件之Jquery Pagination
2015/08/25 Javascript
基于Arcgis for javascript实现百度地图ABCD marker的效果
2015/09/12 Javascript
jQuery实现点击按钮弹出可关闭层的浮动层插件
2015/09/19 Javascript
js下将金额数字每三位一逗号分隔
2016/02/19 Javascript
jQuery如何获取动态添加的元素
2016/06/24 Javascript
BootStrap无限级分类(无限极分类封装版)
2016/08/26 Javascript
AngularJs  Understanding Angular Templates
2016/09/02 Javascript
轻松实现js选项卡切换效果
2016/09/24 Javascript
Angular.js实现多个checkbox只能选择一个的方法示例
2017/02/24 Javascript
Vue2.0实现购物车功能
2017/06/05 Javascript
微信小程序Redux绑定实例详解
2017/06/07 Javascript
深究AngularJS中ng-drag、ng-drop的用法
2017/06/12 Javascript
深入研究jQuery图片懒加载 lazyload.js使用方法
2017/08/16 jQuery
jquery ui 实现 tab标签功能示例【测试可用】
2019/07/25 jQuery
JS实现星星海特效
2019/12/24 Javascript
python使用wmi模块获取windows下硬盘信息的方法
2015/05/15 Python
python导入csv文件出现SyntaxError问题分析
2017/12/15 Python
python简易远程控制单线程版
2018/06/20 Python
Python3实现计算两个数组的交集算法示例
2019/04/03 Python
Pytorch GPU显存充足却显示out of memory的解决方式
2020/01/13 Python
tensorflow 初始化未初始化的变量实例
2020/02/06 Python
SQL SERVER面试资料
2013/03/30 面试题
文明村镇申报材料
2014/05/06 职场文书
普通党员对照检查材料
2014/09/24 职场文书