深入理解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的控制语句
Oct 09 PHP
帖几个PHP的无限分类实现想法~
Jan 02 PHP
PHP4和PHP5性能测试和对比 测试代码与环境
Aug 17 PHP
PHP的cURL库功能简介 抓取网页、POST数据及其他
Apr 07 PHP
PHP fopen 读取带中文URL地址的一点见解
Sep 25 PHP
php定义数组和使用示例(php数组的定义方法)
Mar 29 PHP
php数组索引的Key加引号和不加引号的区别
Aug 19 PHP
php根据日期或时间戳获取星座信息和生肖等信息
Oct 20 PHP
php操纵mysqli数据库的实现方法
Sep 18 PHP
php使用parse_str实现查询字符串解析到变量中的方法
Feb 17 PHP
关于php 高并发解决的一点思路
Apr 16 PHP
PHP开发中csrf攻击的简单演示和防范
May 07 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
星际中一些鲜为人知的详细资料
2020/03/04 星际争霸
php设计模式小结
2013/02/15 PHP
PHP提交表单失败后如何保留已经填写的信息
2014/06/20 PHP
PHP查看当前变量类型的方法
2015/07/31 PHP
javascript 一段左右两边随屏滚动的代码
2009/06/18 Javascript
js 文本滚动效果的实例代码
2013/08/17 Javascript
jquery 追加元素append、prepend、before、after用法与区别分析
2016/12/02 Javascript
Vue input控件通过value绑定动态属性及修饰符的方法
2017/05/03 Javascript
NodeJS链接MySql数据库的操作方法
2017/06/27 NodeJs
详解ES6之async+await 同步/异步方案
2017/09/19 Javascript
关于Mac下安装nodejs、npm和cnpm的教程
2018/04/11 NodeJs
超出JavaScript安全整数限制的数字计算BigInt详解
2018/06/24 Javascript
vuex提交state&amp;&amp;实时监听state数据的改变方法
2018/09/16 Javascript
electron实现qq快捷登录的方法示例
2018/10/22 Javascript
一次让你了解全部JavaScript的作用域
2019/06/24 Javascript
JS实现滑动插件
2020/01/15 Javascript
Vue插件之滑动验证码用法详解
2020/04/05 Javascript
Python while、for、生成器、列表推导等语句的执行效率测试
2015/06/03 Python
python批量制作雷达图的实现方法
2016/07/26 Python
Python随机数用法实例详解【基于random模块】
2017/04/18 Python
python使用Tkinter实现在线音乐播放器
2018/01/30 Python
完美解决Python 2.7不能正常使用pip install的问题
2018/06/12 Python
浅谈Tensorflow由于版本问题出现的几种错误及解决方法
2018/06/13 Python
python opencv实现gif图片分解的示例代码
2019/12/13 Python
Manuka Doctor美国官网:麦卢卡蜂蜜和蜂毒护肤
2016/12/25 全球购物
课例研修方案
2014/05/31 职场文书
服务明星事迹材料
2014/12/29 职场文书
北京故宫的导游词
2015/01/31 职场文书
实习证明格式范文
2015/06/16 职场文书
母亲去世追悼词
2015/06/23 职场文书
换届选举主持词
2015/07/03 职场文书
物业保洁员管理制度
2015/08/05 职场文书
班主任远程培训研修日志
2015/11/13 职场文书
《草船借箭》教学反思
2016/02/23 职场文书
Java Spring Boot 正确读取配置文件中的属性的值
2022/04/20 Java/Android
python绘制简单直方图(质量分布图)的方法
2022/04/21 Python