PHP FPM not cleaning session files in tmp folder

While creating virtual servers php-fpm create tmp folder under username in /home/username/tmp folder and assigns that folder to be used as session folder via configuration in /etc/php/7.0/fpm/pool.d/domain.com.conf. But as files keep growing PHP-FPM automatically does not clean the directory and directory becomes full of session files causing space not available problem.

I think system should automatically cleanup the expired session files.

I have my gc_maxlifetime as 1440 but still files keep building up.

Status: 
Active

Comments

Howdy -- you may want to try enabling automatic cleanup of temp files. That can be enabled in Webmin -> Webmin -> Webmin Configuration -> Advanced Options -> Maximum age of temporary files.

You could try setting it to something like 30 days for starters.

The Webmin setting "Maximum age of temporary files" won't help with files in ~/tmp , only in /tmp/.webmin .

It's really up to PHP to clean up the former ... are these files owned by the domain user on your system?

Yeap, the folder is owned by the domain user. I am running PHP-FPM so each home folder for user such as /home/foo is owned by the user "foo" and there is tmp folder under it. /home/foo/tmp which is not automatically cleaned and is building pile of files around 1.8 million in a month time. the tmp folder is also created in subdomains such as /home/foo/domains/dev.example.com/tmp and is not cleaned automatically.

Is it bug or missing feature or i did not configure properly?

Ah, it sounds like you may have a PHP application which is generating temp files and not cleaning them afterwards.

You may need to look into the individual PHP applications that are being used to either have them clean up their temp files, or create a script to clear out temp files that are left over, and then have that script run from cron.

I checked all those tmp folder and php-fpm is configured to use that folder for session storage. But php itself is not clearing those session files and smallsession files are piling up. Shouldn't php itself clear up old obsolete session files?

It's up to the PHP application to do that... it sounds like the PHP application in question isn't clearing those out.

However, you can always create a script to run from cron to do that for you.

https://stackoverflow.com/a/654547/3657200

Take a look to the first comment:

NOTE: If you are using the subdirectory option for storing session files (see session.save_path above), then garbage collection does not happen automatically. You will need to do your own garbage collection through a shell script, cron entry, or some other method. For example, the following script would is the equivalent of setting session.gc_maxlifetime to 1440 (1440 seconds = 24 minutes): cd /path/to/sessions; find -cmin +24 | xargs rm

How can I run single cron file say every 1 hour and run the above command for all the tmp folders under "home" directory. currently even subdomains have their own tmp folders so eiher 1. setup each cron for all domains and subdomains (hectic) or 2. setup single cron on root so as to clean all the tmp folders under home directory.

My Directory looks like this

/home/foo/tmp {main user}
/home/foo/domains/dev.example.com/tmp {subdomain }
/home/foo/domains/eng.example.com/tmp {subdomain }
/home/foo/domains/nep.example.com/tmp {subdomain }
/home/foo/domains/blog.example.com/tmp {subdomain }

Please suggest what my php cron command should contain for it be able to clear all tmp folders under home

<?php
chdir('/home/foo/tmp');
exec('find -cmin +24 | xargs rm');
chdir('/home/foo/domains/dev.example.com/tmp'); // and so on
exec('find -cmin +24 | xargs rm');
die;

How can I do above task in single linux command?

In my case I have only 30days old session files in my /home/*/tmp folders but I can't understand wheere is configurated like this.

I searched in my config files but I can't figured out.

find -cmin +24 -path "tmp"  -not -path "Maildir" -not -path "mail" -not -path ".tmp"

Helped me to list the files 24 minutes older and following command helps me to delete

find -type f -cmin +24 -path "*tmp*"  -not -path "*Maildir*" -not -path "*mail*" -not -path "*.tmp*" | xargs rm

Maybe useful for others too :)

Status: Active » Closed (fixed)

I ran into the same issue. Running a virgin php7.x ini file. I did some digging and here is what I found:

One thing you might not have noticed is that in the Debian/Ubuntu distro, by default PHP disables its session garbage collection mechanism

(eg. the default php.ini contains the line ;session.gc_probability = 0 in Ubuntu).

Instead, it runs a cron job every half hour (see the script /etc/cron.d/php5) to purge session files in the /var/lib/php5/ directory. In most cases, this doesn't do the session cleanup job for us as session data may not be saved in files under the /var/lib/php5/ directory (like in Drupal). Thus by default PHP session garbage collection does not run in Debian/Ubuntu as many may expect. To solve this, you can modify the php.ini file by adding the line

session.gc_probability = 1

hello @roshanbudhathoki and others

did anyone fix the problem? I have the same issue. The topic is closed, however nothing been fixed.

Thanks

philmck's picture
Submitted by philmck on Fri, 02/28/2020 - 19:38

I've hit this problem as well. As far as I can tell it's a commonly reported problem, the session files are being created as expected, but the periodic cleanup is failing and that is supposed to be done by a cron job (in recent versions of Ubuntu).

There is a cron job that calls /usr/lib/sessionclean periodically. At the moment I can't see anything obviously wrong with that file - it seems to be called as expected and it's trying to do sensible things to parse the php.ini files, find the gc_maxlifetime settings (which I have confirmed are set to 1440), find the locations of the sess_* files and delete the old ones. I haven't found anyone with a solution so it'll have to be debugged the old-fashioned way.

Let me see if I can add support for cleaning up session files in all the ~/tmp directories automatically.

By default in virtualmin a server in php-fpm mode puts the php sessions forever, it is very possible that this is the problem, you can check the configuration options of each virtual server among the php-fpm configuration options. session

philmck's picture
Submitted by philmck on Tue, 04/21/2020 - 10:23

I think @ciberweb is talking about setting session.gc_maxlifetime but it's more complicated than that. See https://www.getpagespeed.com/server-setup/php/cleanup-php-sessions-like-... for a good explanation. I have been fixing the problem by just commenting out the session.save_path setting. Note that the comment character in these files is a semicolon.

;php_admin_value[session.save_path] = /home/[your site]/tmp

No, by default virtualmin crushes many of the options that you can configure. When putting a virtual server in php-fpm mode, configure the default sessions in "FOREVER", you can see it in the php-fpm configuration section of each virtual server, in the session configuration icon. The cron reads that configuration so it never deletes the sess_ files. It is also true that in php-fpm mode it changes the storage directory of the sess_ files and looking at the cron script in case it fails. To me this has caused me problems denying the service for filling the inodes. At the moment I have not wanted to modify the configuration to analyze it more carefully and what I have done is create a very simple cron for the moment with the following script: find /home/*/tmp/* -mmin +600 -type f -delete

At the moment it works very well ... but it is something simple I'm going to analyze my own clean scrip but it seems the problem is that it doesn't look in the / home / * / tmp directories

And the "FOREVER" configuration of virtualmin seems to crush the manuals ... I have not tried to modify the duration of the sessions in the configuration zone of php-fpm which would possibly be the most logical and simple ... but with the problem of inodes, modify the php script that lifts many sessions on a web with thousands of visits ... and then I found this problem that ends up solving radically with the cron. I feel my English

Yep, we just had two servers down today and I've managed to track both server's issues down to this problem. Discs with no available inodes; millions of tmp files. Both servers running PHP-FPM.

This is a really (really) bad default behaviour and I'm looking at how to change it.

Using Ubuntu - The default PHP-FPM config file has

session.gc_probability = 0

and

session.gc_maxlifetime = 1440

The issue being that the second value seems to be ignored because the first value is 0 - garbage collection is never run.

I assume there's supposed to be a CRON job somewhere taking care of it instead; but it sure as hell isn't working, if there is one.

There's a CRON file at /etc/cron.d/php

#  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/php/sessionclean ] && if [ ! -d /run/systemd/system ]; then /usr/lib/php/sessionclean; fi

This (clearly) is not working, but ... I have no idea why not.

For those who are seeing this - which directory are these session files in?

/home/PROJECTTITLE/tmp/*

That's where the default setting put them; I have not adjusted any session paths anywhere myself.

It looks like the CRON itself runs, but does not clear the session files. By way of testing I ran this:

cd /home

find . -xdev -printf '%h\n' | sort | uniq -c | sort -k 1 -n

To list the number of files/inodes in all sub-folders; which resulted in:

1190 ./REDACTED/craft/storage/runtime/cache
1597 ./REDACTED-1/tmp
2224 ./REDACTED-2/craft/storage/runtime/cache/Cr
3094 ./REDACTED-3/tmp
3883 ./REDACTED-4/tmp
5188 ./REDACTED-5/tmp
7267 ./REDACTED-6/tmp
7743 ./REDACTED-7/tmp
9722 ./REDACTED-8/tmp
13708 ./REDACTED-9/tmp
21046 ./REDACTED-10/tmp

I then ran the same script that the CRON job is supposed to trigger:

/usr/lib/php/sessionclean

And once again checked the file/inode counts:

find . -xdev -printf '%h\n' | sort | uniq -c | sort -k 1 -n

1190 ./REDACTED/craft/storage/runtime/cache
1597 ./REDACTED-1/tmp
2224 ./REDACTED-2/craft/storage/runtime/cache/Cr
3094 ./REDACTED-3/tmp
3884 ./REDACTED-4/tmp
5190 ./REDACTED-5/tmp
7267 ./REDACTED-6/tmp
7743 ./REDACTED-7/tmp
9724 ./REDACTED-8/tmp
13711 ./REDACTED-9/tmp
21051 ./REDACTED-10/tmp

They're increasing, not decreasing.

jimr's picture
Submitted by jimr on Fri, 10/16/2020 - 05:49 Pro Licensee

simple fix - install tmpreaper(debain)/tmpwatch(centos) add a cron like /usr/sbin/tmpreaper 1440s /home//tmp or /usr/sbin/tmpwatch 24m /home//tmp tmpwatch does not support seconds so convert session.gc_maxlifetime to mins hit this issue years ago with virtualmin and the above fix has worked fine for a number of years with no problems

jimr's picture
Submitted by jimr on Fri, 10/16/2020 - 05:52 Pro Licensee

simple fix - install tmpreaper(debain)/tmpwatch(centos)

add a cron like

/usr/sbin/tmpreaper 1440s /home/project_name/tmp

or

/usr/sbin/tmpwatch 24m /home/project_name/tmp

tmpwatch does not support seconds so convert session.gc_maxlifetime to mins hit this issue years ago with virtualmin and the above fix has worked fine for a number of years with no problems

Yeah, the default cron job likely only cleans up files in /tmp

I'm working on a feature in Virtualmin to do this for each domain's ~/tmp directory.

Ok, the next release of Virtualmin will clean up sess_* files in each domain tmp dir that are older than 7 days by default.

Excellent news, thank's very much! :)