深入理解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 insert语法详解
Jun 07 PHP
PHP连接MongoDB示例代码
Sep 06 PHP
PHP捕获Fatal error错误的方法
Jun 11 PHP
服务器上配置PHP运行环境教程
Feb 12 PHP
PHP+redis实现添加处理投票的方法
Nov 14 PHP
分享php邮件管理器源码
Jan 06 PHP
Yii2 输出xml格式数据的方法
May 03 PHP
php获取网站根目录物理路径的几种方法(推荐)
Mar 04 PHP
thinkPHP5框架设置404、403等http状态页面的方法
Jun 05 PHP
分享8个Laravel模型时间戳使用技巧小结
Feb 12 PHP
PHP数组访问常用方法解析
Sep 05 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 getimagesize 上传图片的长度和宽度检测代码
2010/05/15 PHP
php实现SAE上使用storage上传与下载文件的方法
2015/06/29 PHP
PHP中一个有趣的preg_replace函数详解
2018/08/15 PHP
accesskey 提交
2006/06/26 Javascript
用js实现的模拟jquery的animate自定义动画(2.5K)
2010/07/20 Javascript
js 窗口抖动示例
2013/09/04 Javascript
按Enter键触发事件的jquery方法实现代码
2014/02/17 Javascript
JavaScript实现数字数组按照倒序排列的方法
2015/04/06 Javascript
js当前页面登录注册框,固定div,底层阴影的实例代码
2016/10/04 Javascript
微信小程序开发一键登录 获取session_key和openid实例
2016/11/23 Javascript
js return返回多个值,通过对象的属性访问方法
2017/02/21 Javascript
jquery图片放大镜效果
2017/06/23 jQuery
基于JS对象创建常用方式及原理分析
2017/06/28 Javascript
layui获取多选框中的值方法
2018/08/15 Javascript
微信小程序wx:for循环的实例详解
2018/10/07 Javascript
深入浅析Vue 中 ref 的使用
2019/04/29 Javascript
Vue axios 将传递的json数据转为form data的例子
2019/10/29 Javascript
vue.js路由mode配置之去掉url上默认的#方法
2019/11/01 Javascript
js实现文章目录索引导航(table of content)
2020/05/10 Javascript
js实现头像上传并且可预览提交
2020/12/25 Javascript
[01:05:24]Ti4 冒泡赛第二天 iG vs NEWBEE 3
2014/07/15 DOTA
[50:02]完美世界DOTA2联赛循环赛 Magma vs IO BO2第一场 11.01
2020/11/02 DOTA
python网络编程实例简析
2014/09/26 Python
在Python中使用mongoengine操作MongoDB教程
2015/04/24 Python
Python第三方库xlrd/xlwt的安装与读写Excel表格
2017/01/21 Python
python 对dataframe下面的值进行大规模赋值方法
2018/06/09 Python
Python整数对象实现原理详解
2019/07/01 Python
Python 私有化操作实例分析
2019/11/21 Python
使用Python爬虫库BeautifulSoup遍历文档树并对标签进行操作详解
2020/01/25 Python
Python多线程获取返回值代码实例
2020/02/17 Python
Python使用Selenium实现淘宝抢单的流程分析
2020/06/23 Python
Expedia挪威官网:酒店、机票和租车
2018/03/03 全球购物
澳大利亚优质的家居用品和生活方式公司:Bed Bath N’ Table
2019/04/16 全球购物
阿尔卡特(中国)的面试题目
2014/08/20 面试题
党的群众路线教育实践活动查摆问题及整改措施
2014/10/10 职场文书
西安事变观后感
2015/06/12 职场文书