PHP会话文件未达session.gc_maxlifetime即被删除问题求助
问题描述与环境配置
部分PHP会话文件在未达到session.gc_maxlifetime阈值时就被提前删除。
- 操作系统:
Ubuntu 18.04.6 LTS (GNU/Linux 4.15.0-188-generic x86_64) - PHP版本:
7.2.24-0ubuntu0.18.04.12
以下是PHP(php.ini)的部分配置:
session.gc_divisor => 10 => 10 session.gc_maxlifetime => 43200 => 43200 session.gc_probability => 1 => 1 session.save_path => /var/lib/php/sessions => /var/lib/php/sessions session.save_handler => files => files
原本预期所有超过12小时的会话会被PHP垃圾回收器或系统cron任务(路径/etc/cron.d/php)删除,cron任务内容如下:
09,39 * * * * root [ -x /usr/lib/php/sessionclean ] && if [ ! -d /run/systemd/system ]; then /usr/lib/php/sessionclean; fi
目前超过12小时的会话能正常被删除,但部分会话文件连12小时都维持不到就被删了。cron执行的/usr/lib/php/sessionclean脚本内容如下:
SAPIS="apache2:apache2 apache2filter:apache2 cgi:php@VERSION@ fpm:php-fpm@VERSION@ cli:php@VERSION@" # Iterate through all web SAPIs ( proc_names="" for version in $(/usr/sbin/phpquery -V); do for sapi in ${SAPIS}; do conf_dir=${sapi%%:*} proc_name=${sapi##*:} if [ -e /etc/php/${version}/${conf_dir}/php.ini ]; then # Get all session variables once so we don't need to start PHP to get each config option session_config=$(PHP_INI_SCAN_DIR=/etc/php/${version}/${conf_dir}/conf.d/ php${version} -c /etc/php/${version}/${conf_dir}/php.ini -d "error_reporting='~E_ALL'" -r 'foreach(ini_get_all("session") as $k => $v) echo "$k=".$v["local_value"]." ";') save_handler=$(echo "$session_config" | sed -ne 's/^session\.save_handler=\(.*\)$/\1/p') save_path=$(echo "$session_config" | sed -ne 's/^session\.save_path=\(.*;\)\?\(.*\)$/\2/p') gc_maxlifetime=$(($(echo "$session_config" | sed -ne 's/^session\.gc_maxlifetime=\(.*\)$/\1/p')/60)) if [ "$save_handler" = "files" -a -d "$save_path" ]; then proc_names="$proc_names $(echo "$proc_name" | sed -e "s,@VERSION@,$version,")"; printf "%s:%s " "$save_path" "$gc_maxlifetime" fi fi done done # first find all open session files and touch them (hope it's not massive amount of files) for pid in $(pidof $proc_names); do find "/proc/$pid/fd" -ignore_readdir_race -lname "$save_path/sess_*" -exec touch -c {} \; 2>/dev/null done ) | \ sort -rn -t: -k2,2 | \ sort -u -t: -k 1,1 | \ while IFS=: read -r save_path gc_maxlifetime; do # find all files older then maxlifetime and delete them find -O3 "$save_path/" -ignore_readdir_race -depth -mindepth 1 -name 'sess_*' -type f -cmin "+$gc_maxlifetime" -delete done exit 0
已尝试的解决方法
为测试会话文件留存时间,部署了以下页面并访问:
<?php session_start(); var_dump( session_id() ); phpinfo();
同时,将获取到的sessionid填入以下脚本,每分钟检查会话文件是否被删除:
#! /bin/bash file=/var/lib/php/sessions/sess_[sessionid] while test -f "$file"; do now=$(date +"%T") echo "$now: $file still exists" sleep 60 done now=$(date +"%T") echo "$now: $file was deleted!"
观察多个会话后发现,留存最久的也未超过5小时,但奇怪的是,session.save_path目录(/var/lib/php/sessions)中有超过100个会话文件能维持至少12小时。
已阅读以下文章但未找到解决方法:
- Session should never expire by itself
- How do I expire a PHP session after 30 minutes?
- How to change the session timeout in PHP?
已被该问题困扰4天,恳请技术帮助。
内容的提问来源于stack exchange,提问作者Alpaca
相关产品推荐
相关产品推荐

