Come devo gestire i file di sessione che diventano troppo numerosi?


43

Mi sto comportando come amministratore di sistema per un paio di server che contengono siti Magento e occasionalmente si riempiono di file di sessione.

Mi è stato detto che la gestione di questi file non è qualcosa che può essere fatto all'interno di Magento e presumo che il loro uso temporaneo significhi che non possono essere semplicemente disattivati, ma sembra strano che Magento non abbia modo di gestire la rimozione di questi File?

La mia soluzione è un crontab notturno che esegue qualcosa del genere, find /path/to/magento/sessions/ -name "sess*" -type f -deletema a dir poco sembra inelegante.

Qual è il modo migliore per gestirli?

Risposte:


37

Oltre all'eliminazione dei file di sessione con l' findutilizzo di un tempo di modifica personalizzato come indicato da altri, puoi anche:

  • Salva le sessioni nel tuo database . Naturalmente questo caricherà il tuo database e non è il modo più veloce, ma puoi gestire molte più sessioni in quel modo e puoi condividere sessioni tra più server frontend. È possibile modificare l'impostazione app/etc/local.xmlcambiando

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

    a

    <session_save><![CDATA[db]]></session_save>
  • Usa memcached come memoria della sessione. Magento lo supporta anche per impostazione predefinita. Dai un'occhiata alla app/etc/local.xml.additionalconfigurazione. Non l'ho mai usato in produzione ma ho sentito che potrebbe essere un po 'complicato.

  • Gestisci le sessioni in Redis utilizzando l'estensione brillante Cm_RedisSession di Colin Mollenhours . L'impostazione di Redis non dovrebbe richiedere troppo tempo, può anche essere utilizzata per la memorizzazione nella cache (vedi Cm_Cache_Backend_Redis ) e combina una cache RAM con persistenza su disco (al contrario di memcached, dischi RAM o simili) che è sempre nel caso in cui il tuo server sia schiantarsi.


1
Anche il salvataggio delle sessioni nel database è più sicuro. Se il tuo file .htaccess non è presente (perché qualcuno ha eliminato la cartella var), i file della sessione non saranno accessibili dall'esterno.
Erfan,

8
Il salvataggio delle sessioni nel database è una cattiva idea. Non è progettato a tale scopo e MySQL funge da strumento molto scarso per l'archiviazione della sessione, il blocco è un problema chiave, per non parlare del supporto integrato per l'eliminazione.
Ben Lessani - Sonassi,

28

Con le sessioni basate su file, verranno eliminate automaticamente dal cron di pulizia della sessione PHP, quindi è probabile che i file vengano eliminati entro ~ 7200 secondi dalla creazione. Quindi, anche su un sito affollato (30k uniques al giorno), di solito ci sono solo circa 4.000 file di sessione in ./var/session - il che non è nulla nemmeno per un server Linux di fascia bassa.

Tuttavia, la pulizia in realtà si basa sul funzionamento di cron, che normalmente non si trova nella directory ./var/session di Magento. Quindi dovresti impostare un nuovo cron di sistema

/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

Il periodo di pulizia predefinito per le sessioni è 7200 secondi, che dovrebbe essere più che adeguato, anche se è possibile modificare quanto sopra per adattarlo.

Con le sessioni Memcache, TCP / IP è l'unico overhead, che per una distribuzione su server singolo lo renderebbe più lento rispetto ai file. Quindi, invece, useresti un socket unix, che rimuove quel sovraccarico e offre una migliore sicurezza. Ma ancora, le sessioni dei tuoi clienti verranno troncate / limitate sulla quantità di RAM che puoi allocare. La sessione media di Magento è 4Kb, quindi sarai in grado di supportare 256 sessioni attive, per MB che assegni. Quindi assicurati di impostare un limite appropriato per evitare che i clienti perdano casualmente carrello / sessione. Inoltre, tieni presente che il riavvio di un demone Memcache cancellerà tutte le sessioni esistenti (BAD!).

Con Redis (non nativo, ma disponibile tramite un'estensione), ottieni un livello di supporto simile a quello di Memcache, ma con i vantaggi aggiuntivi della persistenza (se desideri usarlo). Con l'estensione Cm_Redis, sarai anche in grado di sfruttare la compressione della sessione. Abbiamo scoperto che questa estensione funziona molto bene su implementazioni sia CE che EE.

Con DB, l'impostazione predefinita di scadenza della prugna è una potente settimana, quindi con la dimensione del negozio sopra riportata come esempio (30k uniques al giorno), vedrai una dimensione della tabella DB per core_cache_session di circa 7 GB - che macinerà il tuo negozio si ferma completamente, per quasi tutte le operazioni basate sulla sessione.

Dall'esperienza di ospitare negozi di grandi dimensioni (230k visitatori unici al giorno) e piccoli (<1k visitatori unici al giorno), la nostra raccomandazione è:

Distribuzione su server singolo - file

Distribuzione multi-server - Redis (utilizzando un database separato dalla cache principale di Magento)

Ho scritto alcune risposte davvero approfondite qui http://magebase.com/magento-tutorials/magento-session-storage-which-to-choose-and-why/comment-page-1/#comment-1980


2
Se il cron di pulizia suppone di cancellare le sessioni, perché non riesce e come può essere risolto il problema invece di creare un nuovo cron che sembra un aggiramento?
Oca,

12

Ho fatto una domanda correlata qualche tempo fa:

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

Quello che non ho mai scoperto (ho lasciato quel lavoro per uno nuovo e il problema originale è diventato quello di qualcun altro) è se le sessioni di Magento onoreranno queste impostazioni o se implementano la loro gestione delle sessioni usando Zend (e presumibilmente una sorta di zend.ini file di configurazione).

Le impostazioni php da guardare:

session.gc_maxlifetime session.gc_probability session.gc_divisor

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


Mi piacerebbe saperlo io stesso, dalla mia esperienza sembra che Magento non rispetti queste impostazioni (considerando che ho ottenuto i file di sessione del valore di GB, sarebbe sicuro supporre che ad un certo punto GC si sarebbe attivato). Quindi ho appena impostato lo script consigliato da Ben come cron job per sicurezza.
Javier Villanueva,

7

Di solito è sufficiente un cron job, ma ecco alcune cose da tenere a mente:

1) Impostare la sessione in modo che non duri più di session.gc_maxlifetime( php -i | grep session.gc_maxlifetime) secondi (questo imposterà le sessioni scadute da preparare per la garbage collection da parte di php.ini o .htaccess)

2) Potresti voler archiviare le sessioni nel database vedi qui per maggiori informazioni su come farlo (questa opzione potrebbe essere più facile da gestire tramite il modulo magento personalizzato)

3) Un'altra opzione da considerare è che Strega Memcached può anche velocizzare i server (anche se non completamente connesso alla domanda, penso che sia utile sapere)

Vedi questa domanda per maggiori informazioni: https://stackoverflow.com/questions/4353875/how-long-do-the-magento-session-files-need-to-be-kept


2
L'uso di un cronjob per rimuovere semplicemente tutti i file di sessione è inaccettabile. Cosa succede quando un utente aggiunge materiale al proprio carrello 10 minuti prima dell'esecuzione del cron? Il loro carrello è stato pulito! Se la garbage collection di PHP non funziona, questo deve essere capito.
davidalger,

+1 @davidalger buon punto, ero nell'ipotesi (sbagliata) che solo le sessioni scadute fossero state cancellate tramite
cronjob

1
@davidalger - La garbage collection di PHP funziona tramite cron. È semplicemente findtutti i file più vecchi di sess.gc_maxlifetimee li rimuove. L'eliminazione delle sessioni tramite cron è un comportamento normale, sicuro e accettabile.
Ben Lessani - Sonassi,

1
In realtà no, non lo è. La garbage collection della sessione viene eseguita all'avvio della sessione durante l'esecuzione di script PHP. La frequenza con cui viene eseguita la garbage collection dipende dai valori di session.gc_probabilitye session.gc_divisor. Se script diversi hanno valori diversi per session.gc_maxlifetimequello con il valore più basso determinerà per quanto tempo rimarranno bloccati gli oggetti poiché l'archiviazione della sessione è globale e l'esecuzione di tale script ripulirà gli altri oggetti sessioni degli script.
davidalger,

5

Su tutte le nostre configurazioni abbiamo un file maintenance.php che si occupa della pulizia dei registri e della directory var di tanto in tanto. Poiché le sessioni devono essere salvate nel database o nel file system, questo file di manutenzione li pulirà entrambi. (Vedi codice sotto).

È possibile eseguire il comando seguente come cron job per ripulire i registri:

php maintenance.php clean=log

Il comando sopra produrrà il seguente output:

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

È possibile eseguire il comando seguente come cron job per ripulire la cartella var:

php maintenance.php clean=var

Il comando sopra produrrà il seguente output:

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

Il codice effettivo (non dimenticare di modificare il percorso del file 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

Per Magento CMS e simili (che non stanno ripulendo le vecchie sessioni), utilizzo semplicemente cron job basati sulle impostazioni di php.ini.

PHP5 / Ubuntu 14.04 / Debian

La configurazione del sistema cron.d per php5 non pulisce Magento ./var/session (o qualsiasi altra cosa oltre alla cartella di sessione predefinita (/ var / lib / php5 per Ubuntu e / var / lib / php5 / sessioni o / tmp / per la maggior parte degli altri Linux dists).

Ma puoi ancora usare "sessionclean" e "maxlifetime" secondo il cron predefinito del sistema php5 / Debian:

Esempio che puoi provare dalla riga di comando:

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

Quindi incorporalo in un crontab di sistema / root o in un crontab di un utente che ha i permessi di lettura / scrittura per i file di sessione:

$ sudo crontab -e

Aggiungi questo se vuoi che assomigli al sistema 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)

oppure - poiché sappiamo che esistono quei file / directory:

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

Ora ho un numero gestibile di sessioni ed è tenuto pulito tramite Garbage Collection / Durata predefinita tramite le impostazioni di php.ini (cli).

(È possibile lasciare il carattere jolly sopra o sostituirlo con sitename.)

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

Lo script 'sessionclean' è stato modificato e lo script maxlifetime è stato rimosso. Per il lavoro cron system / php ora è uno script. Non è più possibile utilizzarlo poiché le chiamate ai file ora sono statiche per lo script.

Il vecchio script sessionclean php5 può ancora funzionare per te se il sistema non sta pulendo. Quello che puoi fare è prendere il vecchio pacchetto Debian php5 ed estrarlo sessioncleanda esso. Oppure puoi semplicemente copiarlo nella tua area degli script (dando le autorizzazioni / proprietà proprie / var / www / (site)):

#!/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

Consiglio anche di rinominarlo, quindi non è confuso con il nuovo cronjob php 'sessionclean'. È quindi possibile collegare il proprio numero "maxlifetime" in questo modo:

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

(61 è l'età di esempio (in minuti) e 'MySessionClean' è lo script php5 rinominato scaricato o copiato dall'alto).

In questo modo evitiamo completamente le chiamate php.ini / env.

(EDIT 13DEC2016: aggiornato l'archivio DEBIAN ARCHIVE REPO)


3

Ho cancellato il DB regolarmente da tutti questi vecchi file di sessione. È stato un lavoro manuale irritante fino a quando non ho installato Magento Optimizer che mi fa funzionare tutto questo di routine. Inoltre, la mia cache viene aggiornata costantemente e non lo faccio manualmente dopo aver cambiato prodotti e blocchi statici. Oh, sì, anche i rapporti sugli errori e i carrelli abbandonati vengono puliti.


3

Di tutti i commenti sopra, penso che questa sia la soluzione semplice e spero sia meglio degli script lunghi e dell'installazione di estensioni di terze parti per gestire i file delle vecchie sessioni e conservare i nuovi file di sessione.

  1. Crea un nome di file "clean_session.sh" nella tua magentocartella.
  2. Incolla queste righe.

#!/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. Quindi puoi pianificare cronjob settimanalmente per eseguire la pulizia.

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

  1. Non dimenticare di rendere il file eseguibile come

chmod u+x clean_session.sh

  1. E puoi anche eseguirlo come

sh clean_session.sh


3

Per il mio caso, eseguo questo script inserito nella magento/var/directory per eliminare i file di sessione più -mtime +7vecchi di una settimana ( ):

#!/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

È il mio primo script bash (revisione 2) e penso che possa essere ottimizzato in diversi aspetti. Sono aperto per qualsiasi suggerimento di ottimizzazione.

Questo script può essere recuperato su: https://gist.github.com/Nolwennig/a75dc2f8628be2864bb2


0

Ho creato uno script che svuota la directory var / session. È possibile aggiungerlo a un processo cron per eseguirlo una volta al giorno, che dovrebbe essere sufficiente e regolare secondo necessità. Noterai che quando la directory della sessione viene riempita, è impossibile eliminare i file tramite cpanel o ssh, questo script farà il trucco semplicemente inserendolo nella directory principale di 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);

Il problema con questo script è che elimina tutte le sessioni, non solo quelle precedenti. Quindi nessuno può accedere per più di un giorno (se lo esegui quotidianamente) e tutti i carrelli saranno vuoti dopo che è stato eseguito (quindi nessun carrello rimarrà più di un giorno).
simonthesorcerer
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.