深入理解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安装方法及简单实例
Nov 25 PHP
执行、获取远程代码返回:file_get_contents 超时处理的问题详解
Jun 25 PHP
浅析php插件 Simple HTML DOM 用DOM方式处理HTML
Jul 01 PHP
php实现的一个很好用HTML解析器类可用于采集数据
Sep 23 PHP
PHP中使用break跳出多重循环代码实例
Jan 21 PHP
php数组比较实现查找连续数的方法
Jul 29 PHP
php通过smtp邮件验证登陆的方法
May 11 PHP
Thinkphp批量更新数据的方法汇总
Jun 29 PHP
php封装的page分页类完整实例
Oct 18 PHP
PHP生成zip压缩包的常用方法示例
Aug 22 PHP
PHP中isset、empty的用法与区别示例详解
Nov 05 PHP
phpstorm最新激活码分享亲测phpstorm2020.2.3版可用
Nov 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
星际争霸中的热键
2020/03/04 星际争霸
PHP setcookie() cannot modify header information 的解决方法
2009/01/09 PHP
phpMyAdmin 链接表的附加功能尚未激活问题的解决方法(已测)
2012/03/27 PHP
解析PHP中$_FILES的使用以及注意事项
2013/07/05 PHP
文件上传之SWFUpload插件(代码)
2015/07/30 PHP
php打乱数组二维数组多维数组的简单实例
2016/06/17 PHP
javascript验证只能输入数字和一个小数点示例
2013/10/21 Javascript
加随机数引入脚本不让浏览器读取缓存
2014/09/04 Javascript
浅谈js 闭包引起的内存泄露问题
2015/06/22 Javascript
jquery读写cookie操作实例分析
2015/12/24 Javascript
js与jQuery实现checkbox复选框全选/全不选的方法
2016/01/05 Javascript
基于javascript实现图片预加载
2016/01/05 Javascript
前端实现文件的断点续传(前端文件提交+后端PHP文件接收)
2016/11/04 Javascript
JQuery学习总结【一】
2016/12/01 Javascript
解决ajax不能访问本地文件问题(利用js跨域原理)
2017/01/24 Javascript
vue-router路由简单案例介绍
2017/02/21 Javascript
js截取字符串功能的实现方法
2017/09/27 Javascript
vue webpack打包优化操作技巧
2018/02/22 Javascript
详解vue 兼容IE报错解决方案
2018/12/29 Javascript
Vue通过配置WebSocket并实现群聊功能
2019/12/31 Javascript
Vue中keep-alive的两种应用方式
2020/07/15 Javascript
nuxt 路由、过渡特效、中间件的实现代码
2020/11/06 Javascript
[04:09]2018年度DOTA2社区贡献奖-完美盛典
2018/12/16 DOTA
使用Python的Django框架实现事务交易管理的教程
2015/04/20 Python
PyCharm中代码字体大小调整方法
2019/07/29 Python
Python中pymysql 模块的使用详解
2019/08/12 Python
德国二手设计师时装和复古时装跳蚤市场:Mädchenflohmarkt
2020/11/09 全球购物
银行职业规划书范文
2013/12/28 职场文书
文员岗位职责范本
2014/03/08 职场文书
竞争与合作演讲稿
2014/05/12 职场文书
高考标语大全
2014/06/05 职场文书
领导班子对照检查剖析材料
2014/10/13 职场文书
企业宣传稿范文
2015/07/23 职场文书
开学典礼致辞
2015/07/29 职场文书
企业反腐倡廉心得体会
2015/08/15 职场文书
MySQL悲观锁与乐观锁的实现方案
2021/11/02 MySQL