Comment dois-je gérer les fichiers de session qui deviennent trop nombreux?


43

J'agis en tant qu'administrateur système pour quelques serveurs hébergeant des sites Magento et, parfois, ils se remplissent de fichiers de session.

On m'a dit que la gestion de ces fichiers ne pouvait pas être effectuée depuis Magento et je suppose que leur utilisation temporaire signifie qu'ils ne peuvent pas être simplement désactivés, mais il semble étrange que Magento n'ait aucun moyen de gérer la suppression de ces fichiers. des dossiers?

Ma solution est une crontab nocturne qui exécute quelque chose comme ceci, find /path/to/magento/sessions/ -name "sess*" -type f -deletemais cela semble peu élégant pour le moins.

Quelle est la meilleure façon de gérer ces?

Réponses:


37

Outre la suppression de fichiers de session avec l' findutilisation d'une heure de modification personnalisée comme mentionné par d'autres, vous pouvez également:

  • Enregistrez les sessions dans votre base de données . Bien sûr, cela chargera votre base de données et ce n’est pas le moyen le plus rapide, mais vous pouvez gérer beaucoup plus de sessions de cette façon et vous pouvez partager des sessions entre plusieurs serveurs frontaux. Vous pouvez modifier le réglage en app/etc/local.xmlbasculant

    <session_save><![CDATA[files]]></session_save>

    à

    <session_save><![CDATA[db]]></session_save>
  • Utilisez memcached comme stockage de session. Magento le prend également en charge par défaut. Regardez app/etc/local.xml.additionalpour la configuration. Je ne l'ai jamais utilisé en production, mais j'ai entendu dire que cela pourrait être un peu délicat.

  • Gérez les sessions à Redis en utilisant l’extension brillante Cm_RedisSession de Colin Mollenhours . La configuration de Redis ne devrait pas prendre trop de temps, elle peut également être utilisée pour la mise en cache (voir Cm_Cache_Backend_Redis ) et associe un cache RAM à la persistance sur disque (par opposition à memcached, aux disques RAM, etc.) s'écraser.


1
L'enregistrement des sessions dans la base de données est également plus sécurisé. Si votre fichier .htaccess n'est pas là (parce que quelqu'un a supprimé le dossier var), vos fichiers de session ne seront pas accessibles de l'extérieur.
Erfan

8
L'enregistrement des sessions dans la base de données est une mauvaise idée. Il n’est pas conçu à cet effet et MySQL est un très mauvais outil pour le stockage de session, le verrouillage étant un problème clé - sans parler de la prise en charge intégrée de la purge.
Ben Lessani - Sonassi

28

Avec les sessions basées sur des fichiers, elles seront automatiquement supprimées par le cron de nettoyage de session PHP. Les fichiers risquent donc d'être supprimés dans les 7200 secondes environ suivant leur création. Ainsi, même sur un site occupé (30 000 uniques par jour), il n’ya généralement que 4 000 fichiers de session dans ./var/session - ce qui n’est même pas le cas pour un serveur Linux bas de gamme.

Cependant, le nettoyage repose en réalité sur le fonctionnement de cron, qui ne figure normalement pas dans le répertoire ./var/session de Magento. Donc, vous devriez configurer un nouveau système cron

/usr/bin/find /home/myuser/public_html/var/session -mindepth 1 -maxdepth 1 -type f -cmin +$(/usr/lib/php5/maxlifetime) -print0 -exec rm {} \; >/dev/null 2>&1

La période de nettoyage par défaut des sessions est de 7200 secondes, ce qui devrait être plus que suffisant, bien que vous puissiez modifier ce qui précède en conséquence.

Avec les sessions Memcache, TCP / IP est le seul surcoût, ce qui, pour un déploiement à serveur unique, le ralentirait par rapport à un fichier. Dans ce cas, vous utiliseriez plutôt un socket Unix, ce qui supprime cette surcharge et améliore la sécurité. Mais même quand même, vos sessions client seront tronquées / limitées quant à la quantité de RAM que vous pouvez allouer. La session moyenne de Magento est de 4 Ko - vous pourrez donc prendre en charge 256 sessions actives, par Mo alloué. Veillez donc à définir une limite appropriée pour éviter que les clients perdent leur panier / session au hasard. Et rappelez-vous également qu'un redémarrage du démon Memcache effacera toutes les sessions existantes (BAD!).

Avec Redis (non natif, mais disponible via une extension), vous obtenez un niveau de support similaire à celui de Memcache, mais avec les avantages supplémentaires de la persistance (si vous souhaitez l’utiliser). Avec l'extension Cm_Redis, vous pourrez également tirer parti de la compression de session. Nous avons constaté que cette extension fonctionnait très bien pour les déploiements CE et EE.

Avec with DB, le paramètre d'expiration d'élagage par défaut est une puissante semaine. Par conséquent, avec la taille de magasin ci-dessus à titre d'exemple (30 Ko uniques par jour), vous rechercherez une taille de table de base de données pour core_cache_session d'environ 7 Go - ce qui réduira à néant votre magasin à un arrêt complet, pour presque chaque opération basée sur la session.

Après une expérience dans l’accueil de grands (230 000 visiteurs uniques par jour) et de petits (<1 000 visiteurs uniques par jour), nous vous recommandons:

Déploiement sur un serveur unique - fichiers

Déploiement multi-serveur - Redis (en utilisant une base de données séparée du cache principal de Magento)

J'ai écrit quelques réponses très complètes ici http://magebase.com/magento-tutorials/magento-session-storage-which-to-choose-and-why/comment-page-1/#comment-1980


2
Si le cron de nettoyage est censé effacer les sessions, pourquoi échoue-t-il et comment peut-on résoudre ce problème au lieu de créer un nouveau cron qui ressemble à une solution de contournement?
Goose

12

J'ai posé une question connexe il y a quelque temps:

https://stackoverflow.com/questions/7828975/php-garbage-collection-clarification

Ce que je n'ai jamais découvert (j'ai quitté ce travail pour un nouveau et le problème initial est devenu celui de quelqu'un d'autre) est de savoir si les sessions de Magento respecteront ces paramètres ou si elles implémentent leur traitement de session à l'aide de Zend (et vraisemblablement une sorte de zend.ini). fichier de configuration).

Les paramètres php à regarder:

session.gc_maxlifetime session.gc_probability session.gc_divisor

http://php.net/manual/en/session.configuration.php#ini.session.gc-probability


J'aimerai bien le savoir moi-même. D'après mon expérience, il semblerait que Magento n'honore pas ces paramètres (compte tenu du volume considérable de fichiers de session de GB, il serait prudent de supposer qu'à un moment donné GC aurait déclenché). Donc, je viens de configurer le script recommandé par Ben comme un travail cron pour être sûr.
Javier Villanueva le

7

Généralement, un travail cron est suffisant, mais voici quelques points à garder à l'esprit:

1) Configurez la session pour qu'elle ne dure pas plus de session.gc_maxlifetime( php -i | grep session.gc_maxlifetime) secondes (ceci configurera les sessions expirées à préparer pour la récupération de place par le fichier php.ini ou .htaccess)

2) Vous voudrez peut-être stocker les sessions dans la base de données . Pour plus d’informations sur la procédure à suivre, cliquez ici (cette option sera peut-être plus facile à gérer via le module magento personnalisé).

3) Une autre option à considérer est Memcached qui peut également accélérer les serveurs (bien que pas complètement connecté à la question, je pense qu’il est utile de savoir à propos de)

Voir cette question pour plus d’informations: https://stackoverflow.com/questions/4353875/how-long-do-the-magento-session-files-need-to-be-kept


2
L'utilisation d'un travail cron pour simplement supprimer tous les fichiers de la session est inacceptable. Que se passe-t-il lorsqu'un utilisateur ajoute des éléments à son panier 10 minutes avant le lancement de cron? Leur panier est nettoyé! Si la poubelle de PHP ne fonctionne pas, il faut le comprendre.
davidalger

+1 @davidalger bon point, j'étais sous l'hypothèse (erronée) que seules les sessions expirées étaient supprimées via cronjob
pzirkind

1
@davidalger - La propre collection de déchets de PHP fonctionne via cron. Il finds agit simplement de sess.gc_maxlifetimesupprimer tous les fichiers plus anciens . Supprimer des sessions via cron est un comportement normal, sûr et acceptable.
Ben Lessani - Sonassi

1
En fait non. La récupération de place de la session est effectuée au démarrage de la session lors de l'exécution de scripts PHP. La fréquence à laquelle la récupération de place est exécutée dépend des valeurs de session.gc_probabilityet session.gc_divisor. Si différents scripts ont des valeurs différentes, session.gc_maxlifetimecelui avec la valeur la plus basse déterminera la durée pendant laquelle les données resteront vives depuis que le stockage de la session est global et l'exécution de ce script supprimera les objets des autres sessions de scripts.
davidalger

5

Sur toutes nos configurations, nous avons un fichier maintenance.php qui s'occupe du nettoyage des journaux et du répertoire var de temps en temps. Étant donné que les sessions doivent être enregistrées dans la base de données ou sur le système de fichiers, ce fichier de maintenance les nettoiera. (Voir code ci-dessous).

Vous pouvez exécuter la commande suivante en tant que tâche cron pour nettoyer les journaux:

php maintenance.php clean=log

La commande ci-dessus produira la sortie suivante:

catalogindex_aggregation has been truncated
catalogindex_aggregation_tag has been truncated
catalogindex_aggregation_to_tag has been truncated
catalog_compare_item has been truncated
dataflow_batch_export has been truncated
dataflow_batch_import has been truncated
log_customer has been truncated
log_quote has been truncated
log_summary has been truncated
log_summary_type has been truncated
log_url has been truncated
log_url_info has been truncated
log_visitor has been truncated
log_visitor_info has been truncated
log_visitor_online has been truncated
report_compared_product_index has been truncated
report_event has been truncated
report_viewed_product_index has been truncated

Vous pouvez exécuter la commande suivante en tant que tâche cron pour nettoyer le dossier var:

php maintenance.php clean=var

La commande ci-dessus produira la sortie suivante:

downloader/.cache/* has been emptied
downloader/pearlib/cache/* has been emptied
downloader/pearlib/download/* has been emptied
var/cache/ has been emptied
var/locks/ has been emptied
var/log/ has been emptied
var/report/ has been emptied
var/session/ has been emptied
var/tmp/ has been emptied

Le code actuel (n'oubliez pas de modifier le chemin d'accès à votre fichier local.xml):

<?php
$xml = simplexml_load_file('./app/etc/local.xml', NULL, LIBXML_NOCDATA);

$db['host'] = $xml->global->resources->default_setup->connection->host;
$db['name'] = $xml->global->resources->default_setup->connection->dbname;
$db['user'] = $xml->global->resources->default_setup->connection->username;
$db['pass'] = $xml->global->resources->default_setup->connection->password;
$db['pref'] = $xml->global->resources->db->table_prefix;

if (!isset($argv[1]) || !stristr($argv[1], 'clean=')) {
    echo 'Please use one of the commands below:' . PHP_EOL;
    echo 'php maintenance.php clean=log' . PHP_EOL;
    echo 'php maintenance.php clean=var' . PHP_EOL;
    die;
}

$method = str_replace('clean=', '', $argv[1]);

switch ($method) {
case 'log':
    clean_log_tables();
    break;
case 'var':
    clean_var_directory();
    break;
default:
    echo 'Please use one of the commands below:' . PHP_EOL;
    echo 'php maintenance.php clean=log' . PHP_EOL;
    echo 'php maintenance.php clean=var' . PHP_EOL;
    break;
}

function clean_log_tables() {
    global $db;

    $tables = array(
        'catalogindex_aggregation',
        'catalogindex_aggregation_tag',
        'catalogindex_aggregation_to_tag',
        'catalog_compare_item',
        'dataflow_batch_export',
        'dataflow_batch_import',
        'log_customer',
        'log_quote',
        'log_summary',
        'log_summary_type',
        'log_url',
        'log_url_info',
        'log_visitor',
        'log_visitor_info',
        'log_visitor_online',
        'report_compared_product_index',
        'report_event',
        'report_viewed_product_index'
    );

    mysql_connect($db['host'], $db['user'], $db['pass']) or die(mysql_error());
    mysql_select_db($db['name']) or die(mysql_error());

    foreach($tables as $v => $k) {
        @mysql_query('TRUNCATE `'.$db['pref'].$k.'`');
        echo $db['pref'] . $k . ' has been truncated' . PHP_EOL;
    }
}

function clean_var_directory() {
    $dirs = array(
        'downloader/.cache/*',
        'downloader/pearlib/cache/*',
        'downloader/pearlib/download/*',
        'var/cache/',
        'var/locks/',
        'var/log/',
        'var/report/',
        'var/session/',
        'var/tmp/'
    );

    foreach($dirs as $v => $k) {
        exec('rm -rf '.$k);
        echo $k . ' has been emptied' . PHP_EOL;
    }
}

5

Pour les CMS Magento et autres (qui ne nettoient pas les anciennes sessions), j’utilise simplement des tâches cron basées sur les paramètres php.ini.

PHP5 / Ubuntu 14.04 / Debian

Le programme d'installation cron.d pour php5 ne nettoie pas Magento ./var/session (ou autre chose que le dossier de session par défaut (/ var / lib / php5 pour Ubuntu et / var / lib / php5 / sessions ou / tmp / pour la plupart des autres) Linux dists).

Mais vous pouvez toujours utiliser "sessionclean" et "maxlifetime" selon le cron par défaut du système php5 / Debian:

Exemple, vous pouvez essayer depuis la ligne de commande:

# sudo /usr/lib/php5/sessionclean /var/www/{yoursite}/var/session $(/usr/lib/php5/maxlifetime)

Il suffit donc de l’intégrer à une crontab système / racine ou à une crontab d’utilisateur disposant des droits de lecture / écriture pour les fichiers de session:

$ sudo crontab -e

Ajoutez ceci si vous voulez qu'il ressemble au système php cron:

20,40 * * * * [ -x /usr/lib/php5/maxlifetime ] && [ -x /usr/lib/php5/sessionclean ] && [ -d /var/www/*/var/session ] && /usr/lib/php5/sessionclean /var/www/{yoursite}/var/session $(/usr/lib/php5/maxlifetime)

ou - puisque nous savons que ces fichiers / répertoires existent:

20,40 * * * * /usr/lib/php5/sessionclean /var/www/*/var/session $(/usr/lib/php5/maxlifetime)

Maintenant, j'ai un nombre gérable de sessions et il est maintenu propre via la collecte de place par défaut / durée de vie via les paramètres php.ini (cli).

(Vous pouvez laisser le caractère générique ci-dessus ou le remplacer par sitename.)

EDIT (PHP7 / Ubuntu 16.xx / Debian):

Le script 'sessionclean' a été modifié et le script maxlifetime a été supprimé. Pour le travail système / php cron, il s’agit désormais d’un seul script. Vous ne pouvez plus vraiment l'utiliser car les appels de fichiers sont maintenant statiques dans le script.

L'ancien script php5 sessionclean peut toujours fonctionner pour vous si le système ne nettoie pas. Ce que vous pouvez faire, c'est récupérer l'ancien paquet Debian php5 et en extraire sessionclean. Ou vous pouvez simplement copier ceci dans votre zone de scripts (en donnant les droits / var / www / (site) appropriés):

#!/bin/sh

# first find all used files and touch them (hope it's not massive amount of files)
[ -x /usr/bin/lsof ] && /usr/bin/lsof -w -l +d "${1}" | awk -- '{ if (NR > 1) { print $9; } }' | xargs -i touch -c {}

# find all files older then maxlifetime
find "${1}" -depth -mindepth 1 -maxdepth 1 -ignore_readdir_race -type f -cmin "+${2}" -delete

Je recommande également de le renommer afin qu'il ne soit pas confondu avec le nouveau cronjob php 'sessionclean'. Vous pouvez ensuite brancher votre propre numéro "maxlifetime" comme ceci:

     20,40 * * * * /home/-username-/scripts/MySessionClean /var/www/*/var/session 61

(61 étant l'exemple de l'âge (en minutes) et 'MySessionClean' étant le script renommé php5 téléchargé ou copié depuis ci-dessus).

De cette manière, nous évitons entièrement les appels php.ini / env.

(EDIT 13DEC2016: Mise à jour de la liaison Debian ARCHIVE REPO)


3

J'ai effacé la base de données régulièrement de tous ces anciens fichiers de session. Le travail manuel était irritant jusqu’à ce que j’ai installé Magento Optimizer, ce qui me permet de faire tout ce travail de routine. De plus, mon cache est actualisé en permanence et je ne le fais pas manuellement après avoir modifié des produits et des blocs statiques. Oh, oui, les rapports d'erreur et les chariots abandonnés sont également nettoyés.


3

De tous les commentaires ci-dessus, je pense que c'est la solution facile et j'espère que c'est mieux que de longs scripts et l'installation d'une extension tierce pour gérer les anciens fichiers de session et conserver les nouveaux fichiers de session.

  1. Créez un nom de fichier "clean_session.sh" dans votre magentodossier.
  2. Collez ces lignes.

#!/bin/bash
# delete session files older than 14 days
find /home/DOMAIN/public_html/var/session -name 'sess_*' -type f -mtime +14 -exec rm {} \;

  1. Ensuite, vous pouvez planifier cronjob chaque semaine pour effectuer le nettoyage.

1 1 * * 6 /bin/sh /home/DOMAIN/public_html/clean_session.sh

  1. N'oubliez pas de rendre le fichier exécutable en tant que

chmod u+x clean_session.sh

  1. Et vous pouvez aussi le lancer comme

sh clean_session.sh


3

Dans mon cas, j’exécute ce script placé dans le magento/var/répertoire des fichiers de session de suppression datant de plus d’une semaine ( -mtime +7):

#!/bin/sh
# Place this script in magento/var/ directory

for n in `seq 0 9`
  do
    for u in `seq 0 9`
    do
      for m in `seq 0 9`
        do
          name="sess_"$n$u$m*
          echo $name
          find session/ -name $name -type f -mtime +7 -delete
          echo $name ok
      done
      for m in {a..z}
        do
          name="sess_"$n$u$m*
          echo $name
          find session/ -name $name -type f -mtime +7 -delete
          echo $name ok
      done
    done
      for u in {a..z}
      do
        for m in `seq 0 9`
          do
            name="sess_"$n$u$m*
            echo $name
            find session/ -name $name -type f -mtime +7 -delete
            echo $name ok
        done
        for m in {a..z}
          do
            name="sess_"$n$u$m*
            echo $name
            find session/ -name $name -type f -mtime +7 -delete
            echo $name ok
        done
    done
done

for n in {a..z}
  do
    for u in `seq 0 9`
      do
        for m in `seq 0 9`
          do
            name="sess_"$n$u$m*
            echo $name
            find session/ -name $name -type f -mtime +7 -delete
            echo $name ok
        done
        for m in {a..z}
          do
            name="sess_"$n$u$m*
            echo $name
            find session/ -name $name -type f -mtime +7 -delete
            echo $name ok
        done
    done
    for u in {a..z}
      do
        for m in `seq 0 9`
          do
            name="sess_"$n$u$m*
            echo $name
            find session/ -name $name -type f -mtime +7 -delete
            echo $name ok
        done
        for m in {a..z}
          do
            name="sess_"$n$u$m*
            echo $name
            find session/ -name $name -type f -mtime +7 -delete
            echo $name ok
        done
    done
done

C'est mon premier script bash (révision 2) et je pense qu'il peut être optimisé sous plusieurs aspects. Je suis ouvert à toute suggestion d'optimisation.

Ce script peut être récupéré à l' adresse suivante : https://gist.github.com/Nolwennig/a75dc2f8628be2864bb2


0

J'ai créé un script qui vide le répertoire var / session. Vous pouvez l'ajouter à un travail cron à exécuter une fois par jour, ce qui devrait suffire et l'ajuster si nécessaire. Vous remarquerez que lorsque votre répertoire de session est rempli, il est impossible de supprimer des fichiers via cpanel ou ssh, ce script fera l'affaire, il suffit de le placer dans le répertoire racine de magento.

<?php
function adjustSessionFiles($dir, $pattern = "*")
{
    $files = glob($dir . "/$pattern");
    foreach ($files as $file) {
        if (is_dir($file) and !in_array($file, array('..', '.')))  {
            adjustSessionFiles($file, $pattern);
        }else if(is_file($file) and ($file != __FILE__)) {
            unlink($file);
        }
    }
}
$dir = __DIR__ . DIRECTORY_SEPARATOR . 'var' . DIRECTORY_SEPARATOR . 'session';
adjustSessionFiles($dir);

Le problème avec ce script est qu'il supprime toutes les sessions, pas seulement les anciennes. Ainsi, personne ne peut être connecté plus d'une journée (si vous utilisez cette opération quotidiennement), et tous les paniers seront vides après cette opération (aucun panier ne tiendra plus d'une journée).
simonthesorcerer
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.