自定义session_save_path后PHP会话无法按设置的gc_maxlifetime自动过期问题排查
我来帮你梳理几个实用的排查方向,这类自定义session存储路径导致GC(垃圾回收)不工作的问题在PHP里挺常见的:
检查自定义session目录的权限
PHP负责执行GC的进程(通常是Web服务器的运行用户,比如www-data、nginx)需要对../sessions/目录拥有读、写、执行权限。如果权限不足,GC进程既没法读取目录里的session文件,也没法删除过期文件。你可以用命令调整权限:chmod 700 /path/to/your/sessions/ chown www-data:www-data /path/to/your/sessions/替换成实际的路径和服务器用户。
验证
session_save_path的实际路径是否正确
有时候$_SERVER['DOCUMENT_ROOT']的结尾可能带或不带斜杠,拼接后可能生成错误的路径。可以在代码里临时添加一行输出实际路径:var_dump(session_save_path());确认输出的路径和你预期的一致,并且这个路径确实存在、能被PHP访问。
检查GC触发概率与站点访问量
你设置的session.gc_probability=1和session.gc_divisor=100意味着每100次请求才会触发一次GC。如果你的站点访问量很低,可能GC根本没机会运行。可以临时修改这两个值来测试:ini_set('session.gc_probability', 1); ini_set('session.gc_divisor', 1);这样每次请求都会触发GC,等5分钟后刷新页面,看看过期的session文件是否被删除。测试完成后记得改回原设置,避免影响性能。
排查系统级的Session清理任务
很多Linux发行版会用系统cron任务来统一清理session文件,而不是依赖PHP内置的GC。比如Ubuntu/Debian系统可能有/etc/cron.d/php8.2这类定时脚本,它会读取php.ini里的全局session.gc_maxlifetime设置来清理,忽略你代码里的自定义配置。你可以用以下命令检查是否存在这类任务:crontab -l | grep php ls /etc/cron.d/ | grep php如果存在,要么修改全局php.ini的
session.gc_maxlifetime,要么禁用这个系统级清理任务,让PHP自己处理GC。确认Session文件的修改时间
PHP的GC是根据session文件的最后修改时间判断是否过期的,而不是创建时间。如果用户在会话有效期内有操作,session会被重新写入,文件的修改时间会更新,自然不会被清理。你可以直接去../sessions/目录下,用ls -l查看过期session文件的修改时间,确认是否真的超过了300秒。避免多应用共享Session目录的冲突
如果你的服务器上还有其他PHP应用,并且它们也使用了同一个自定义session目录,那其他应用的session.gc_maxlifetime设置可能会覆盖你的配置。确保这个../sessions/目录只有当前应用在使用。
内容的提问来源于stack exchange,提问作者OliverTwist

