K
K
Konstantin2020-12-14 20:36:57
linux
Konstantin, 2020-12-14 20:36:57

Why doesn't /usr/lib/php/sessionclean clean up stale sessions?

Hello.
We take ubuntu 18.04 and install php/php-fpm. And surprisingly, you can see that the cron task does not delete obsolete sessions in the /var/lib/php/sessions directory

in php.ini
session.save_path="/var/lib/php/sessions"
In syslog

Dec 14 20:09:01 srv CRON[12814]: (root) CMD (  [ -x /usr/lib/php/sessionclean ] && if [ ! -d /run/systemd/system ]; then /usr/lib/php/sessionclean; fi)
Dec 14 20:09:03 srv systemd[1]: Starting Clean php session files...
Dec 14 20:09:03 srv sessionclean[12815]: /usr/lib/php/sessionclean: 38: /usr/lib/php/sessionclean: arithmetic expression: expecting primary: "/60"
Dec 14 20:09:03 srv systemd[1]: Started Clean php session files.


file /etc/cron.d/php
09,39 *     * * *     root   [ -x /usr/lib/php/sessionclean ] && if [ ! -d /run/systemd/system ]; then /usr/lib/php/sessionclean; fi


FILE /usr/lib/php/sessionclean
#!/bin/sh -e
#
# sessionclean - a script to cleanup stale PHP sessions
#
# Copyright 2013-2015 Ondřej Surý <[email protected]>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the "Software"), to deal in
# the Software without restriction, including without limitation the rights to
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
# the Software, and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

SAPIS="apache2:apache2 apache2filter:apache2 cgi:[email protected]@ fpm:[email protected]@ cli:[email protected]@"

# 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"]."\n";')
            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,@[email protected],$version,")";
                printf "%s:%s\n" "$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


Why does the standard kit out of the box not clean sessions? Do you need to tweak something extra?
Thank you.

Answer the question

In order to leave comments, you need to log in

3 answer(s)
K
Konstantin, 2020-12-16
@webmaster

The cause of the problem was the presence of the ini_get_all function in disable_functions.
Removed it and everything worked as it should.

O
Oleg, 2020-12-14
@402d

find /var/lib/php/sessions/sess_* -mmin +240 -delete;
well, clean the desired directory in the forehead;)
for example, with such a task once an hour. whichever is older min +240 (240 minutes = 4 hours)

G
galaxy, 2020-12-14
@galaxy

Something is wrong with the session.gc_maxlifetime setting, it seems.
Do for each PHP config:

php -c /etc/php/VERSION/CONFD/php.ini -d "error_reporting='~E_ALL'" -r 'var_dump(ini_get_all("session"));'

where VERSION - version, CONFD - directories with configs in /etc/php/VERSION (i.e. cli, fpm, apache2...).
And check that in session.gc_maxlifetime

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question