搞不清php session默认过期时间,回收机制踩坑记
- 2026年11月9日
- 18 次
上周三下午四点多,测试同事在后台填完一张表单,去接了杯水回来就被踢回登录页,登录态撑了还不到半小时。我第一反应是有人把 php session默认过期时间调小了,赶紧连上服务器翻配置,结果发现光看一个数字根本解释不通,索性把回收机制从头捋了一遍。
php session默认过期时间到底是多少
先把结论摆出来:session.gc_maxlifetime 的默认值是 1440 秒,也就是 24 分钟,写在 php.ini 的 [Session] 段里。很多人一眼就以为这就是 php session默认过期时间,其实只说对了一半。

我当初也这么以为,结果被现实打脸。这个 1440 秒管的是 session 文件的回收判定线,回收程序看文件有多久没被改动,超过就删掉,跟浏览器里 cookie 什么时候过期是两码事。
cookie 那边由 session.cookie_lifetime 决定,默认 0,意思是关掉浏览器就失效。所以 php session默认过期时间其实是两个计时器一起算出来的,只盯一个参数,你迟早要踩坑。
举个常见的场景,后台管理要求半小时无操作就退出,前台商城希望登录能撑七天。这种就得按站点分开配,一个全局值糊弄不了两边。
顺便说一句,session 文件本身不神秘,就是 save_path 目录下一个以 sess_ 开头的文件,内容是键值对加序列化字符串,cat 一下就能看见。
默认的 save_path 是空的,PHP 会落到系统临时目录,通常是 /tmp。这个目录谁都能写,多个应用混在一起,回收时很容易误伤,所以我一般会给站点单独指一个目录。
session.gc_maxlifetime 在哪里改
要改 php session默认过期时间,最直接的是 php.ini,找到 [Session] 那一段,三个参数一起看,别只动一个。
session.gc_maxlifetime = 1440
session.gc_probability = 1
session.gc_divisor = 100
上面是 php.ini 里的原始写法。gc_probability 除以 gc_divisor 就是每次请求触发回收的概率,1/100 意味着平均一百个请求里有一次去扫过期文件,这个 100 是编译默认值,发行版可能改过,以官方文档为准。
改完要让 PHP 重新加载。用 php-fpm 就重启进程池,只 reload nginx 没用,这点我白跑过一次。
老实说,改完最好再确认一遍生效值。配置文件里写了,不等于真的加载了,多版本 PHP 并存的时候尤其容易改错文件。
按环境挑一条就够,别三条一起上。自己一个人用的机器、有 root 权限,直接改 php.ini 最省心;一台机器跑好几个站,就在对应 pool 里写 php_admin_value[session.gc_maxlifetime] = 1800,只影响这个站;临时调试才用 ini_set,它必须在 session_start 之前调,而且只对当前请求有效。
.user.ini 我也试过,它只对同目录及子目录生效,还有缓存时间,改完要等一会儿才刷新,我图省事的时候宁可写进 pool。
session 为什么没到时间就失效
这就是我这次踩的坑。表面上 php session默认过期时间 是 24 分钟,可实际会话十几分钟就没了,问题出在回收程序身上。

第一个可能是配置被发行版改过。Debian、Ubuntu 的 php.ini 里常把 session.gc_probability 设成 0,回收交给 /etc/cron.d/php 这个定时任务。你要是照着老教程把概率改回 1,就变成两套回收同时在删文件。
这种情况我在好几台机器上都遇到过,顺序别搞反:先确认概率和定时任务,再去看 session 目录的权限和属主。
第二个可能是多个站点共用一个 session.save_path。A 站的 gc_maxlifetime 设成 600 秒,回收时它不管文件是谁的,一律按自己的标准删,你的站设 3600 秒也白搭。

如果你用的是 Redis 或者 Memcached 存 session,那 gc_probability 这套概率根本不参与,过期时间由 handler 自己接管,gc_maxlifetime 通常被当成 TTL 传进去。换存储之前先弄清这一点,能少走很多弯路。
还有一个容易漏的点:从 PHP 7 开始 session.lazy_write 默认是 1,数据没变化就不重写文件,时间戳也不刷新。用户一直在点页面,文件却停在原地,回收一看早超龄,顺手就删了。这一步我吃过亏,日志里全是莫名其妙的掉登录。
我的排查步骤
真遇到掉登录,我一般按下面两步走,比瞎猜快得多。想弄清 php session默认过期时间 到底怎么生效,这两步也比翻文档管用。
第一步,确认当前生效的值。别在命令行直接跑 php -i,CLI 读的是 CLI 那份 php.ini,跟你站点上 php-fpm 加载的可能不是同一个文件。稳妥点就跑 php-fpm -i,或者在站点目录放一个临时 phpinfo 页,重点看 local 那一列,它会盖掉 php.ini 里的全局值。
php-fpm -i | grep -E 'session\.(gc_maxlifetime|gc_probability|gc_divisor)'
第二步,去看 session 文件本身的年龄。文件都在 save_path 指向的目录里,按时间排一下,重点看时间列,哪个老得离谱,基本就是被回收的目标。
ls -lt --time-style=long-iso /var/lib/php/sessions | head -20
如果文件修改时间普遍比 gc_maxlifetime 还老,说明回收概率或者定时任务在偷偷动手。把概率调低、或者关掉概率回收改用 cron 统一清理,反而更可控。
顺手也看一眼 /etc/cron.d/php 或者 systemd 的定时单元,确认是不是有别的东西在固定时间清 session 目录。两套清理撞一起,你怎么调参数都对不上。
我还会顺手看一眼 php-fpm 的错误日志,里面有 session 相关的 warning 就别放过,权限不对、目录不可写,也会表现成掉登录。
把两个计时器对齐再收工
php session默认过期时间 从来不是一个孤立的数字。cookie 管浏览器什么时候丢,gc 管服务器什么时候删文件,两边对不齐,用户就会卡在中间那段空档里被踢出去。
真要我给个稳妥的组合,就是把 gc_maxlifetime 设成 1800 到 3600 之间,cookie 寿命跟它保持一致,回收只留 cron 一条路。cookie 那边在 php.ini 里写 session.cookie_lifetime = 1800,运行时要改就是 session_set_cookie_params(['lifetime' => 1800])。
这里有个顺序不能反:cookie 寿命要小于或等于 gc_maxlifetime,不然文件先被回收、浏览器还攥着 cookie,用户点进去照样是登录页。数字不用照抄我的,按你业务的实际在线时长来定就行。
我的做法是把 gc_maxlifetime 设得比 cookie 寿命略长一点,再固定一种回收方式,别让 cron 和概率回收打架。先看 cookie、再看 gc,两边对齐了再谈掉登录。
若非作者标注皆为李涛自留地原创文章,转载或复制请以超链接形式并注明出处。
- PHP文件打开、读取、关闭操作函数语法及实例 2022-11-09
- PHP抽象类使用方法 PHP抽象类作用及实例代码 2022-12-10
- PHP in_array()、array_search()、array_key_exists() 查找函数对比 2026-07-02
- PHP array_multisort() 函数详解:多维数组排序的 N 种姿势 2026-07-03
- 利用Python对字符串进行长度排序并输出保存到txt文本中 2021-08-19
- PHP析构方法如何使用 PHP析构方法使用实例代码 2022-12-04
