Welcome Guest, Not a member yet? Register   Sign In
Session library not garbage collecting
#1

I have a site that is built on CI bonfire, running CI 3.1.6.

It's a popular site and uses the filesystem for session management, however it appears that the garbage collection, that should be deleting the old session files is not working as it should be. As a result we've ended up with a session directory totalling 1.5GB of session files, which we have estimated to number over 26 million!

As a solution for the moment a tmpfs mount point has been created for the sessions as writing that many files with that frequency to a physical disk can't have been doing it any good whatsoever. In addition to that I have written a shell script to delete and session files older than 4 hours.

This last fix feels like a bit of a hack for what I think CI should have been doing automatically.

The session settings are as follows:

$config['sess_cookie_name'] = 'bf_session_';
$config['sess_expiration'] = 7200;
$config['sess_time_to_update'] = 300;
$config['sess_match_ip'] = false;
$config['sess_driver'] = 'files';
$config['sess_regenerate_destroy'] = true;
$config['sess_save_path'] = 'sessions';

Has anyone experienced that same and if so what was your solution? Is the CI session management broken?
Reply
#2

(This post was last modified: 01-26-2020, 05:19 AM by jreklund.)

You need to set sess_save_path should be a absolute path. I think it's now saved in the default PHP catalog. So set it to an absolute path or specify NULL (and it will fallback to the default PHP folder). Absolute path are recommended, even if you are using the default path.

The garbage collector are based on PHP own functionally and need to be changed within those settings:
https://www.php.net/manual/en/session.co...robability
session.gc_probability
session.gc_divisor

You may have your gc_probability set to 0. So it will never run.

Personally I have sess_regenerate_destroy set to FALSE. As let the garbage collector take care of things. Instead of it constantly looking for a file and delete it. Please see this warning:
https://www.php.net/manual/en/function.s...ate-id.php
Reply
#3

(This post was last modified: 01-27-2020, 03:21 AM by jhob.)

Thanks for that, super-helpful response, and I think we have found the problem!

Code:
session.gc_probability = 0
session.gc_divisor = 0
session.gc_maxlifetime = 1440

Although from having done a bit more reading, I think the CRON task will achieve essentially thing but be potentially less expensive so I'm minded to leave it as it for now.  Opinions to the contrary welcome!
Reply
#4

If you are going with a CRON make a CRON script that execute Codeigniter's own gc.

This is a copy of Session_files_driver.php. I think you should execute that one instead.
PHP Code:
    /**
     * Garbage Collector
     *
     * Deletes expired sessions
     *
     * @param    int     $maxlifetime    Maximum lifetime of sessions
     * @return    bool
     */
    
public function gc($maxlifetime)
    {
        if ( ! 
is_dir($this->_config['save_path']) OR ($directory opendir($this->_config['save_path'])) === FALSE)
        {
            
log_message('debug'"Session: Garbage collector couldn't list files under directory '".$this->_config['save_path']."'.");
            return 
$this->_failure;
        }

        
$ts time() - $maxlifetime;

        
$pattern = ($this->_config['match_ip'] === TRUE)
            ? 
'[0-9a-f]{32}'
            
'';

        
$pattern sprintf(
            
'#\A%s'.$pattern.$this->_sid_regexp.'\z#',
            
preg_quote($this->_config['cookie_name'])
        );

        while ((
$file readdir($directory)) !== FALSE)
        {
            
// If the filename doesn't match this pattern, it's either not a session file or is not ours
            
if ( ! preg_match($pattern$file)
                OR ! 
is_file($this->_config['save_path'].DIRECTORY_SEPARATOR.$file)
                OR (
$mtime filemtime($this->_config['save_path'].DIRECTORY_SEPARATOR.$file)) === FALSE
                
OR $mtime $ts)
            {
                continue;
            }

            
unlink($this->_config['save_path'].DIRECTORY_SEPARATOR.$file);
        }

        
closedir($directory);

        return 
$this->_success;
    } 
Reply
#5

Thanks for that heads up - will look into implementing that.
Reply
#6

For what it's worth, using a CRON job to clean up old sessions is a perfectly valid approach. In fact, that approach is often suggested as a way to improve site performance.
Reply
#7

For what its worth. Setting the values in your php config to 1/100 works well.
Reply




Theme © iAndrew 2016 - Forum software by © MyBB