Wie soll ich mit Sitzungsdateien umgehen, die zu zahlreich werden?

43

Ich fungiere als Systemadministrator für einige Server, die Magento-Sites enthalten, und gelegentlich füllen sie sich mit Sitzungsdateien.

Mir wurde gesagt, dass die Verwaltung dieser Dateien in Magento nicht möglich ist, und ich gehe davon aus, dass ihre temporäre Verwendung bedeutet, dass sie nicht einfach ausgeschaltet werden können, aber es ist seltsam, dass Magento keine Möglichkeit hat, diese Dateien zu entfernen Dateien?

Meine Lösung ist ein nächtlicher Crontab, der so etwas ausführt, sich find /path/to/magento/sessions/ -name "sess*" -type f -deleteaber, gelinde gesagt, unelegant anfühlt.

Wie geht man am besten damit um?

Toby
quelle

Antworten:

37

Abgesehen vom Löschen von Sitzungsdateien mit findeiner benutzerdefinierten Änderungszeit, wie von anderen erwähnt, können Sie auch:

  • Speichern Sie die Sitzungen in Ihrer Datenbank . Natürlich wird dies Ihre Datenbank belasten und es ist nicht der schnellste Weg, aber Sie können auf diese Weise mehr Sitzungen abwickeln und Sitzungen zwischen mehreren Front-End-Servern gemeinsam nutzen. Sie können die Einstellung app/etc/local.xmldurch Umschalten ändern

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

    zu

    <session_save><![CDATA[db]]></session_save>
  • Verwenden Sie memcached als Sitzungsspeicher. Magento unterstützt dies auch standardmäßig. Schauen Sie sich app/etc/local.xml.additionaldie Konfiguration an. Ich habe es nie in der Produktion verwendet, aber ich habe gehört, dass dies ein bisschen knifflig sein kann.

  • Behandeln Sie die Sitzungen in Redis mit der brillanten Erweiterung Cm_RedisSession von Colin Mollenhours . Das Einrichten von Redis sollte nicht zu lange dauern, kann auch zum Zwischenspeichern verwendet werden (siehe Cm_Cache_Backend_Redis ) und kombiniert einen RAM-Cache mit Persistenz auf der Festplatte (im Gegensatz zu zwischengespeicherten, RAM-Festplatten oder dergleichen), was immer der Fall ist, wenn Ihr Server es ist abstürzt.

Matthias Zeis
quelle
1
Das Speichern der Sitzungen in der Datenbank ist auch sicherer. Wenn Ihre .htaccess-Datei nicht vorhanden ist (weil der var-Ordner gelöscht wurde), kann von außen nicht auf Ihre Sitzungsdateien zugegriffen werden.
Erfan
8
Das Speichern der Sitzungen in der Datenbank ist eine schlechte Idee. Es wurde nicht für diesen Zweck entwickelt und MySQL dient als sehr schlechtes Werkzeug für die Sitzungsspeicherung. Sperren ist ein zentrales Problem - ganz zu schweigen von der integrierten Unterstützung für das Löschen.
Ben Lessani - Sonassi
28

Bei dateibasierten Sitzungen werden sie vom Cron für die Bereinigung von PHP-Sitzungen automatisch bereinigt. Daher werden die Dateien wahrscheinlich innerhalb von ~ 7200 Sekunden nach der Erstellung gelöscht. Selbst auf einer geschäftigen Site (30.000 Unikate pro Tag) befinden sich normalerweise nur 4.000 Sitzungsdateien in ./var/session - was selbst für einen Low-End-Linux-Server nichts ist.

Die Bereinigung hängt jedoch von der Cron-Arbeit ab, die normalerweise nicht im Verzeichnis ./var/session von Magento angezeigt wird. Sie sollten also ein neues System-Cron einrichten

/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

Die Standardbereinigungsdauer für Sitzungen beträgt 7200 Sekunden, was mehr als ausreichend sein sollte, obwohl Sie die oben genannten Werte entsprechend ändern können.

Bei Memcache-Sitzungen ist TCP / IP der einzige Overhead, der bei einer Bereitstellung auf einem Server langsamer als bei einer dateibasierten. Dann würden Sie stattdessen einen Unix-Socket verwenden, der diesen Overhead beseitigt und mehr Sicherheit bietet. Trotzdem werden Ihre Kundensitzungen in Bezug auf die Menge an RAM, die Sie zuweisen können, eingeschränkt. Die durchschnittliche Magento-Sitzung beträgt 4 KB - Sie können also 256 aktive Sitzungen pro MB, das Sie zuweisen, unterstützen. Stellen Sie daher sicher, dass Sie ein angemessenes Limit festlegen, um zu vermeiden, dass Kunden den Warenkorb / die Sitzung nach dem Zufallsprinzip verlieren. Beachten Sie auch, dass durch einen Neustart des Memcache-Daemons alle vorhandenen Sitzungen gelöscht werden (BAD!).

Mit Redis (nicht nativ, aber über eine Erweiterung verfügbar) erhalten Sie eine ähnliche Unterstützung wie mit Memcache, jedoch mit den zusätzlichen Vorteilen der Persistenz (falls Sie diese verwenden möchten). Mit der Erweiterung Cm_Redis können Sie auch die Sitzungskomprimierung nutzen. Wir haben festgestellt, dass diese Erweiterung sowohl bei CE- als auch bei EE-Bereitstellungen sehr gut funktioniert.

Die Standardeinstellung für das Ablaufen der Bereinigung mit DB ist mächtig 1 Woche. Bei der oben genannten Speichergröße (30.000 Einheiten pro Tag) wird eine DB-Tabellengröße für die core_cache_session von ca. 7 GB ermittelt, was sich positiv auswirkt Ihr Geschäft ist für fast alle sitzungsbasierten Vorgänge zum Stillstand gekommen.

Aufgrund unserer Erfahrung mit dem Hosting großer (230.000 eindeutige Besucher pro Tag) und kleiner (<1.000 eindeutige Besucher pro Tag) Geschäfte empfehlen wir Folgendes:

Einzelserver-Bereitstellung - Dateien

Multiserver-Bereitstellung - Redis (unter Verwendung einer separaten Datenbank aus dem Magento-Hauptcache)

Ich habe hier einige wirklich gründliche Antworten geschrieben: http://magebase.com/magento-tutorials/magento-session-storage-which-to-choose-and-why/comment-page-1/#comment-1980

Ben Lessani - Sonassi
quelle
2
Wenn der Bereinigungs-Cron Sitzungen löschen soll, warum schlägt dies fehl, und wie kann dieses Problem behoben werden, anstatt einen neuen Cron zu erstellen, der sich wie ein Workaround anfühlt?
Gans
12

Ich habe vor einiger Zeit eine verwandte Frage gestellt:

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

Was ich nie herausgefunden habe (ich habe diesen Job für einen neuen Job verlassen und das ursprüngliche Problem wurde zu einem anderen) ist, ob Magentos Sitzungen diese Einstellungen berücksichtigen oder ob sie ihre Sitzungsbehandlung mit Zend implementieren (und vermutlich mit einer Art von zend.ini) Konfigurationsdatei).

Die PHP-Einstellungen zu sehen:

session.gc_maxlifetime session.gc_probability session.gc_divisor

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

pspahn
quelle
Ich würde das gerne selbst wissen, aus meiner Erfahrung sieht es so aus, als würde Magento diese Einstellungen nicht einhalten (wenn man bedenkt, dass ich GBs wertvolle Sitzungsdateien habe, ist es sicher anzunehmen, dass irgendwann GC ausgelöst hätte). Aus Sicherheitsgründen habe ich das von Ben empfohlene Skript einfach als Cronjob eingerichtet.
Javier Villanueva
7

Normalerweise reicht ein Cron-Job aus, aber hier sind ein paar Dinge zu beachten:

1) Legen Sie fest, dass die Sitzung nicht länger als session.gc_maxlifetime( php -i | grep session.gc_maxlifetime) Sekunden dauert (dies richtet abgelaufene Sitzungen ein, die für die Garbage Collection durch die Datei php.ini oder .htaccess vorbereitet werden sollen).

2) Möglicherweise möchten Sie die Sitzungen in der Datenbank speichern. Weitere Informationen hierzu finden Sie hier (diese Option ist möglicherweise einfacher über das benutzerdefinierte Magento-Modul zu verwalten).

3) Eine andere Option zu prüfen ist Memcached Hexe kann auch die Server beschleunigen (obwohl nicht vollständig mit der Frage verbunden, ich denke, es ist nützlich zu wissen, über)

Weitere Informationen finden Sie in dieser Frage: https://stackoverflow.com/questions/4353875/how-long-do-the-magento-session-files-need-to-be-kept

pzirkind
quelle
2
Es ist nicht akzeptabel, einen Cronjob zu verwenden, um einfach alle Sitzungsdateien zu entfernen. Was passiert, wenn ein Benutzer 10 Minuten vor der Ausführung des Cron etwas in seinen Einkaufswagen legt? Ihr Wagen ist sauber gewischt! Wenn die Garbage Collection von PHP nicht funktioniert, muss das herausgefunden werden.
Davidalger
+1 @davidalger guter Punkt, ich war unter der (falschen) Annahme, dass nur abgelaufene Sessions über cronjob
pzirkind 23.01.13
1
@davidalger - PHPs eigene Garbage Collection funktioniert über cron. Es sind einfach findalle Dateien älter als sess.gc_maxlifetimeund sie werden entfernt. Das Löschen von Sessions über cron ist normal, sicher und akzeptabel.
Ben Lessani - Sonassi
1
Eigentlich nein, ist es nicht. Sitzungsspeicherbereinigung wird durchgeführt, wenn der Sitzungsstart während der Ausführung eines PHP-Skripts erfolgt. Wie häufig die Garbage Collection ausgeführt wird, hängt von den Werten von session.gc_probabilityund ab session.gc_divisor. Wenn verschiedene Skripte unterschiedliche Werte für session.gc_maxlifetimedenjenigen mit dem niedrigsten Wert haben, wird bestimmt, wie lange sich etwas in der Warteschlange befindet, da der Sitzungsspeicher global ist, und die Ausführung dieses Skripts bereinigt die anderen Sitzungsobjekte des Skripts.
Davidalger
5

In all unseren Setups haben wir eine maintenance.php-Datei, die sich ab und zu um die Bereinigung der Logs und des var-Verzeichnisses kümmert. Da die Sitzungen entweder in der Datenbank oder im Dateisystem gespeichert werden müssen, werden sie durch diese Wartungsdatei bereinigt. (Siehe Code unten).

Sie können den folgenden Befehl als Cron-Job ausführen, um die Protokolle zu bereinigen:

php maintenance.php clean=log

Der obige Befehl erzeugt die folgende Ausgabe:

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

Sie können den folgenden Befehl als Cron-Job ausführen, um den var-Ordner zu bereinigen:

php maintenance.php clean=var

Der obige Befehl erzeugt die folgende Ausgabe:

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

Der eigentliche Code (Vergessen Sie nicht, den Pfad zu Ihrer local.xml-Datei anzupassen):

<?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;
    }
}
Kenny
quelle
5

Für Magento CMS und ähnliches (die keine alten Sitzungen bereinigen) verwende ich nur Cron-Jobs, die auf den Einstellungen von php.ini basieren.

PHP5 / Ubuntu 14.04 / Debian

Das System cron.d setup für php5 bereinigt Magento ./var/session (oder irgendetwas anderes als den Standard-Sitzungsordner (/ var / lib / php5 für Ubuntu und / var / lib / php5 / sessions oder / tmp / für die meisten anderen Linux) nicht dists).

Sie können jedoch weiterhin "sessionclean" und "maxlifetime" gemäß der Standard-PHP5 / Debian-System-Cron verwenden:

Beispiel, das Sie über die Befehlszeile ausprobieren können:

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

Integrieren Sie dies einfach in eine System- / Root-Crontab oder eine Crontab eines Benutzers, der über Lese- / Schreibrechte für die Sitzungsdateien verfügt:

$ sudo crontab -e

Fügen Sie dies hinzu, wenn Sie möchten, dass es ähnlich wie System-PHP-Cron aussieht:

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)

oder - da wir wissen, dass diese Dateien / Verzeichnisse existieren:

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

Jetzt habe ich eine überschaubare Anzahl von Sitzungen und es wird über die standardmäßigen Garbage Collection / Lifetime-Einstellungen in der php.ini (cli) sauber gehalten.

(Sie können den Platzhalter oben belassen oder durch den Site-Namen ersetzen.)

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

Das 'sessionclean'-Skript wurde geändert und das maxlifetime-Skript wurde entfernt. Für den System / PHP-Cron-Job ist es jetzt ein Skript. Sie können dies nicht mehr wirklich verwenden, da die Dateiaufrufe jetzt für Skripte statisch sind.

Das ältere php5 sessionclean Skript kann immer noch für Sie arbeiten, wenn das System nicht aufräumt . Was Sie tun können, ist das ältere Debian-PHP5-Paket zu nehmen und daraus zu extrahieren sessionclean. Oder Sie kopieren dies einfach in Ihren Skriptbereich (geben Sie die richtigen / var / www / (Site) -Berechtigungen / Eigentumsrechte):

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

Ich empfehle es auch umzubenennen, damit es nicht mit dem neuen PHP 'sessionclean' Cronjob verwechselt wird. Sie können dann Ihre eigene "maxlifetime" -Nummer wie folgt eingeben:

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

(61 ist das Beispielalter (in Minuten) und 'MySessionClean' ist das umbenannte PHP5-Skript, das von oben heruntergeladen oder kopiert wurde).

Auf diese Weise vermeiden wir alle Aufrufe von php.ini / env.

(EDIT 13DEC2016: Aktualisierter DEBIAN ARCHIVE REPO LINK)

bshea
quelle
3

Ich habe die Datenbank regelmäßig von all diesen alten Sitzungsdateien gelöscht. Es war eine ärgerliche manuelle Arbeit, bis ich Magento Optimizer installiert habe , was all diese Routinearbeit für mich erledigt. Außerdem wird mein Cache ständig aktualisiert und nach dem Ändern von Produkten und statischen Blöcken nicht manuell. Oh ja, Fehlerberichte und verlassene Karren werden ebenfalls gesäubert.

James
quelle
3

Von allen obigen Kommentaren halte ich dies für die einfache Lösung und hoffe, dass es besser ist als lange Skripte und die Installation von Erweiterungen von Drittanbietern, um alte Sitzungsdateien zu verwalten und neue Sitzungsdateien zu behalten.

  1. Erstellen Sie einen Dateinamen "clean_session.sh" unter Ihrem magentoOrdner.
  2. Fügen Sie diese Zeilen ein.

#!/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. Dann können Sie wöchentlich einen Cronjob einplanen, um die Bereinigung durchzuführen.

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

  1. Vergessen Sie nicht, die Datei ausführbar zu machen als

chmod u+x clean_session.sh

  1. Und Sie können es auch als ausführen

sh clean_session.sh

Anil
quelle
3

In meinem Fall führe ich dieses Skript aus, das in einem magento/var/Verzeichnis zum Löschen von Sitzungsdateien abgelegt ist, das älter als eine Woche ist ( -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

Es ist mein erstes Bash-Skript (Revision 2) und ich denke, es kann in mehrfacher Hinsicht optimiert werden. Ich bin offen für Optimierungsvorschläge.

Dieses Skript kann abgerufen werden unter: https://gist.github.com/Nolwennig/a75dc2f8628be2864bb2

Nolwennig
quelle
0

Ich habe ein Skript erstellt, das das Verzeichnis var / session leert. Sie können es einem Cron-Job hinzufügen, um es einmal pro Tag auszuführen. Dies sollte ausreichen und nach Bedarf angepasst werden. Sie werden bemerken, dass es unmöglich ist, Dateien über cpanel oder ssh zu löschen, wenn das Sitzungsverzeichnis gefüllt ist. Dieses Skript erledigt den Trick, der nur im magento-Stammverzeichnis abgelegt wird.

<?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);
Lawrence Farbman
quelle
Das Problem mit diesem Skript ist, dass alle Sitzungen gelöscht werden, nicht nur die alten. Daher kann niemand länger als einen Tag angemeldet sein (wenn Sie dies täglich ausführen), und alle Karren sind nach dieser Ausführung leer (sodass kein Wagen länger als einen Tag hält).
Simonthesorcerer