this applies to : Linux 3.16.0-4-amd64 #1 SMP Debian 3.16.36-1+deb8u2 (2016-10-19) x86_64 GNU/Linux) cat /etc/debian_version 8.6 PHP Version 5.6.28-0+deb8u1

Linux debian home tmp sess can accumulate a lot of files… they stem from mysql but also from php sessions.

the reason why debian is not using php’s build-in-garbage collector is as follows:

Because Debian sets very stringent permissions on /var/lib/php5 (1733, owner root, group root) to prevent PHP session hijacking. Unfortunately, this also prevents the native PHP session garbage collector from working, because it can’t see the session files there. The cron job runs as root, which does have sufficient access to see and clean up the session files.

Edit: Supporting documentation: The behavior was established in response to bug #267720. (There used to be comments in the stock php.ini file about this, but I don’t see them there now in my wheezy-based PHP install.)

https://serverfault.com/questions/511609/why-does-debian-clean-php-sessions-with-a-cron-job-instead-of-using-phps-built

usually this script: /usr/lib/php5/sessionclean
and this cronjob: /etc/cron.d/php5

should take care of it.

if not, to clean up manually try this: (may take a while, slow)

find /home/*/tmp -follow -maxdepth 1 -type f | wc -l; # count the files and symlinks in this folder
21

nice find /home/*/tmp -type f -name 'sess_*' -ctime +3 -delete; # delete those files older than 3 days

# -ctime n
# File's status was last changed n*24 hours ago. See the comments
# for -atime to understand how rounding affects the interpretation
# of file status change times.

To handle session properly, take a look at http://ar.php.net/manual/en/session.configuration.php

There you’ll find these variables:

session.gc_probability
session.gc_divisor
session.gc_maxlifetime

These control the garbage collector (GC) probability of running with each page request.

You could set those with ini_set() at the beginning of your script or .htaccess file so you get certainty to some extent they will get deleted sometime.

vim /etc/php5/*/php.ini; # let us checkout the php.ini config file
# you can find the php.ini file in use by creating a info.php file with
# <?php
# phpinfo();
# as content and run it

# in the php.ini one can find:

; After this number of seconds, stored data will be seen as 'garbage' and
; cleaned up by the garbage collection process.
; http://php.net/session.gc-maxlifetime
session.gc_maxlifetime = 1440

session.gc_maxlifetime specifies the number of seconds after which data will be seen as ‚garbage‘ and potentially cleaned up. Garbage collection may occur during session start (depending on session.gc_probability and session.gc_divisor).

Note: If different scripts have different values of session.gc_maxlifetime but share the same place for storing the session data then the script with the minimum value will be cleaning the data. In this case, use this directive together with session.save_path.

http://php.net/session.gc-maxlifetime

so why do they NOT get deleted after this time?

debian/ubuntu seem to employ a cronjob to clean up those files… but somehow this cronjob does not seem to exist on my system?

# my version:

# /etc/cron.d/php5: crontab fragment for php5
#  This purges session files in session.save_path older than X,
#  where X is defined in seconds as the largest value of
#  session.gc_maxlifetime from all your SAPI php.ini files
#  or 24 minutes if not defined.  The script triggers only
#  when session.save_handler=files.
#
#  WARNING: The scripts tries hard to honour all relevant
#  session PHP options, but if you do something unusual
#  you have to disable this script and take care of your
#  sessions yourself.

# Look for and purge old sessions every 30 minutes
09,39 *     * * *     root   [ -x /usr/lib/php5/sessionclean ] && /usr/lib/php5/sessionclean

# some other version? Ubuntu?

# /etc/cron.d/php5: crontab fragment for php5
#  This purges session files older than X, where X is defined in seconds
#  as the largest value of session.gc_maxlifetime from all your php.ini
#  files, or 24 minutes if not defined.  See /usr/lib/php5/maxlifetime

# Look for and purge old sessions every 30 minutes
09,39 *     * * *     root   [ -d /var/lib/php5 ] && find /var/lib/php5/ -type f -cmin +$(/usr/lib/php5/maxlifetime) -print0 | xargs -r -0 rm

so there is a script which is supposed to run every 30minutes:

vim /usr/lib/php5/sessionclean

#!/bin/sh -e
#
# sessionclean - a script to cleanup stale PHP sessions
#
# Copyright 2013-2015 Ondřej Surý <ondrej@sury.org>
#
# 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:php5 fpm:php5-fpm cli:php5"

# Iterate through all web SAPIs
(
proc_names=""
for sapi in ${SAPIS}; do
    conf_dir=${sapi%%:*}
    proc_name=${sapi##*:}
    if [ -e /etc/php5/${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/php5/${conf_dir}/conf.d/ php5 -c /etc/php5/${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 $proc_name";
            printf "%s:%s\n" "$save_path" "$gc_maxlifetime"
        fi
    fi
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

a script called maxlifetime.sh which returns you the supposed lifetime (in minutes) of those php-session-files.

vim maxlifetime.sh; # create new file

i; # go into insert mode in vim

# copy paste this content (sometimes under Debian MATE Desktop / Gnome2 you simply highlight the ext with your mouse and then press the middle mouse button to insert...

#!/bin/sh -e

max=1440

for ini in /etc/php5/*/php.ini; do
        cur=$(sed -n -e 's/^[[:space:]]*session.gc_maxlifetime[[:space:]]*=[[:space:]]*\([0-9]\+\).*$/\1/p' $ini 2>/dev/null || true);
        [ -z "$cur" ] && cur=0
        [ "$cur" -gt "$max" ] && max=$cur
done

echo $(($max/60))

exit 0

:wq; # save and quit vim

chmod u+x ./maxlifetime.sh; # set the script to executable

./maxlifetime.sh; # run the script
24 minutes, that the /home/*/tmp/sess_... files should be kept alive

Links:

https://stackoverflow.com/questions/654310/cleanup-php-session-files

https://serverfault.com/questions/138214/are-php-session-files-ever-deleted

Deleting millions of files from a directory can be a daunting task.

rm -rf will expand the to glob every file in the directory and return an error such as „Argument list too long“.

find . -type f -delete will try to get a list of all files before deleting them, and is very slow.

The answer is to bypass BASH completely:

perl -e 'chdir "BADnew" or die; opendir D, "."; while ($n = readdir D) { unlink $n }'

Thanks to Randal L. Schwartz

www.binarysludge.com/2012/01/01/how-to-delete-millions-of-files-linux/

admin