3

I have a problem with my PHP session data folder. It seems to not be expiring sessions and has hit some sort of limit, presumably the filesystem limit for files in a directory. Requests that involve writing sessions fail with fatal error due to not enough disk space.

I have temporarily worked around it by pointing the sessions.save_path to a new directory.

Would like to know what is wrong with my php.ini that is preventing sessions being expired.

Also I tried truncating the sessions directory using rm but it just seems to hang forever?

Problem directory:

drwxr-xr-x  2 www-data www-data 294215680 Jan  5 13:42 sessions

Session section of php.ini:

[Session]
session.save_handler = files
session.save_path = "N;/var/www/data/sessions"
session.use_strict_mode = 0
session.use_cookies = 1
session.use_only_cookies = 1
session.name = PHPSESSID
session.auto_start = 0
session.cookie_lifetime = 2592000
session.cookie_path = /
session.cookie_domain =
session.cookie_httponly =
session.serialize_handler = php
session.gc_probability = 0
session.gc_divisor = 1000
session.gc_maxlifetime = 1440
session.referer_check =
session.cache_limiter = nocache
session.cache_expire = 180
session.use_trans_sid = 0
session.hash_function = 0
session.hash_bits_per_character = 5
Tony H
  • 133
  • 1
  • 4

3 Answers3

5
session.save_path = "N;/var/www/data/sessions"

The doesn't seem to be causing a problem (as PHP is obviously generating sessions), but isn't right.

The two formats for this option are:

/path/to/sessions
N;/path/to/sessions

The integer N defines how many sub-directories to create under the specified path, useful to spread the session files out over lots of directories if you expect a lot of session files. (You've already discovered that systems don't like lots of files in one directory...)

session.gc_probability = 0

This is most likely the main problem (unless PHP automatically handles someone setting this incorrectly to 0)

The probability that the cleanup will happen is defined by probability/divisor. 0/1000 is 0 so will likely never run.

Edit: Regarding deleting the files, you may just have to wait for it to finish. If it's millions of files it probably will seem like it's hanging.

USD Matt
  • 5,321
  • 14
  • 23
2

You need a cron job to clean the session files, they are not being cleaned by themselves. Ubuntu/Debian have a script (/etc/cron.d/php) to do the cleanup automatically.

If you don't have such script, put find /var/www/data/sessions -cmin +1440 -print0 | xargs -0 -r rm on a cronjob.

It will clean files 24 hours older or more.

ThoriumBR
  • 5,272
  • 2
  • 23
  • 34
2

Your config includes the following setting:

session.save_path = "N;/var/www/data/sessions"

which seems incorrect. The leading N in the session.save_path should be an integer that defines the number of subdirectory levels that will be used to distribute session files.

Using "N" (correctly or not) would also prevent garbage collection according to the manual and you'll need a cron job to delete old sessions files:

There is an optional N argument to this directive that determines the number of directory levels your session files will be spread around in. For example, setting to "5;/tmp" may end up creating a session file and location like /tmp/4/b/1/e/3/sess_4b1e384ad74619bd212e236e52a5a174 . In order to use N you must create all of these directories before use. A small shell script exists in ext/session to do this, it's called mod_files.sh, with a Windows version called mod_files.bat. Also note that if N is used and greater than 0 then automatic garbage collection will NOT be performed, see a copy of php.ini for further information. Also, if you use N, be sure to surround session.save_path in "quotes" because the separator (;) is also used for comments in php.ini.

HBruijn
  • 72,524
  • 21
  • 127
  • 192
  • Don't forget that when the session.save_path is used with the subdirectory level integer, you need to create the directory tree before. In the offical PHP repository there is an script for it: https://github.com/php/php-src/blob/master/ext/session/mod_files.sh and use a cron scheduled script with something similar to this to clean the sessions: find /var/lib/php/sessions/* -cmin +60 -type f | sed 's/\/var\/lib\/php\/sessions\///g' | xargs -i rm /var/lib/php/sessions/"{}" – rfmoz May 06 '18 at 16:52