Yesterday I faced with really weird issue with PHP’s session handling. At work we are hosting dozens of sites on our servers and suddenly on one server we were getting lot of weird out of space errors when PHP tried to open session files. Error message was “Warning Unknown: open(/path/to/sessions/sess_somehash, O_RDWR) failed: No space left on device (28)” . Because of those errors I was believing we were somehow running out of space on apache’s temp file partition. Truth was there was only few megabytes data, but the problem was that we had over 200 000 files on one folder and PHP got crazy of that.
I tried to figure out how that was possible. Why wasn’t PHP’s garbage collector cleaned up those files? I didn’t find any reason for that but today I checked out session save path and everything looked fine. There was only files which were created recently and file count was around 1000 files.
Removing lot of files
To get server back in business I had to remove those session files. When I first tried to remove over 200 000 files I got weird error “bash: /bin/rm: Argument list too long”. I got answer for that from Google. I should use find to remove those files:
find . -name 'sess_*' |xargs rm
Improving PHP’s session handling and garbage collection
When I had removed those files I had to ensure I won’t face same issue second time. I started to looking PHP manual and reading php.ini comments to fix the cause for this issue. First thing which I noticed was that our session.gc_divisor value was 1000 and session.gc_probability value was 1 which means there 1/1000 chance that garbage collector process starts on each request. Default value for session.gc_divisor is 100 so I reverted our setting to default. I don’t know was it that change or what but as I mentioned earlier today garbage collection seems to work.
When was tweaking on PHP’s session settings I found interesting comment. You can start your session.save_path value with number and semicolon and PHP will use subdirectories for sessions files. The number before semicolon defines how deep directory structure will be used. There is two things you should note if you want to use this option. Firstly, PHP won’t create those directories automatically, but luckily PHP’s source package provides shell script for you to create these directories:
/path/to/php/source/ext/session/mod_files.sh session_dir depth
Another thing to note is that garbage collector won’t clean up you session files anymore. For that documentation recommend you to run following command in cron or some equivalent method:
cd /path/to/sessions; find -cmin +24 | xargs rm
Number value should be more than your maximum session lifetime in minutes. I think I will take this subdirectory feature and my own garbage collection script to use when we have next maintenance window on our server.

Comments