Session geht sporadisch verloren
Lukas.
- php
Hallo,
ich arbeite in meinem System (php) mit Sessions, hierzu wird in jedem Script eine Datei eingebunden, die folgende Zeilen enthält
ini_set ('session.save_path', $s_pfad);
ini_set('session.gc_maxlifetime',3800);
session_start();
Der Pfad für die Session ist über eine zuvor ebenfalls eingebunden Datei bekannt.
Bei Bedarf schreibe ich in das S_Session-Array ein oder lese aus.
Das funktioniert auch weitestgehend sehr gut. Leider gehen dennoch ab und an Sessions verloren, was dazu führt, das ich den User zwangsweise auslogge. Er hatte aber noch nicht die Zeitschwelle für den destroy der Session erreicht.
Ich bin momentan etwas überfragt, wo ich bei der Fehlersuche ansetzen sollte.
Habt Ihr dazu ein paar Tips, um den Fehler zumindest schonmal eingrenzen zu können?
Gruß, Lukas
Es gibt da ein paar Skripte und systemweite cronjobs, welche Sessions löschen.
und
Da steht wohl noch max=1440 drin. Du willst 3800...
Es gibt da ein paar Skripte und systemweite cronjobs, welche Sessions löschen.
- /etc/cron.d/php5 oder
- /etc/cron.d/php
und
- /usr/lib/php5/maxlifetime oder
- /usr/lib/php/maxlifetime
Da steht wohl noch max=1440 drin. Du willst 3800...
Aber größtenteils funktioniert es ja. Außerdem ist zuletzt ein User mitten während der Arbeit ausgeloggt worden, also von einem Klick zum nächsten.
Lukas
Aber größtenteils funktioniert es ja.
Jahaha! Das ist der Effekt - und das haben auch schon andere gehabt. Ansonsten einfach mal nachlesen, was darüber schon herausgefunden wurde.
Lesen:
Der verworfene Artikel: PHP Anwendung und Praxis-Loginsystem.pdf
Freilich kann man Dir noch einen Blick ins Error-Log empfehlen.
Und hast Du etwas wie: $_SESSION['last_action'] = date('U');
getan? Im Session-File muss man "ein wenig herumschreiben" - sonst wird es von obigen Mechanismus brutal gekillt.
Hi,
Lesen:
Der verworfene Artikel: PHP Anwendung und Praxis-Loginsystem.pdf
Lese ich mir gleich mal durch.
Freilich kann man Dir noch einen Blick ins Error-Log empfehlen.
Inwiefern?
Und hast Du etwas wie:
$_SESSION['last_action'] = date('U');
getan? Im Session-File muss man "ein wenig herumschreiben" - sonst wird es von obigen Mechanismus brutal gekillt.
Ja, so etwas habe ich. Allerdings etwas anders, mein Prozess läuft wie folgt:
User klickt -> Session wird gestartet -> Werte werden (nahezu bei jedem Klick) gelesen und neu gesetzt -> Die Zeitspanne zum Logout wird über Datenbankeinträge errechnet
Lukas
User klickt -> Session wird gestartet
Und hierbei nur gelesen.
-> Werte werden (nahezu bei jedem Klick) gelesen und neu gesetzt
Überzeuge Dich davon, dass da auch wirklich was geschrieben wird, ob sich das Datum auch ändert. Etwas wie ein stat $SESSION_FILE
| (Klick) | stat $SESSION_FILE
sollte Klarheit schaffen.
-> Die Zeitspanne zum Logout wird über Datenbankeinträge errechnet
Klar! Wenn man richtig viel Aufwand zweifelhafter Nötigkeit treiben kann sollte man das UN-BE-DINGT tun.
Hi,
Überzeuge Dich davon, dass da auch wirklich was geschrieben wird, ob sich das Datum auch ändert. Etwas wie ein
stat $SESSION_FILE
| (Klick) |stat $SESSION_FILE
sollte Klarheit schaffen.
Habe ich gerade gemacht. Da scheint alles klar zu gehen.
-> Die Zeitspanne zum Logout wird über Datenbankeinträge errechnet
Klar! Wenn man richtig viel Aufwand zweifelhafter Nötigkeit treiben kann sollte man das UN-BE-DINGT tun.
Nein, das liegt daran, dass ich ohnehin einen kompletten Log erstelle. Da ist das Ausrechnen der Zeitspanne nur so eine Art "Abfallprodukt".
Lukas
Aber den Pfad ändere ich doch bereits.
Lukas
Aber den Pfad ändere ich doch bereits.
Schön. Dann zeige sämtlichen relevanten Code und informiere uns über sämtliche relevanten Umstände. Schau auch nach, ob in Formularen, Links oder Weiterleitungen ggf. eine Änderung der URL vorkommt:
So gilt z.B.:
true == ('http://example.com' !== 'http://www.example.com')
Aber den Pfad ändere ich doch bereits.
Schön. Dann zeige sämtlichen relevanten Code und informiere uns über sämtliche relevanten Umstände. Schau auch nach, ob in Formularen, Links oder Weiterleitungen ggf. eine Änderung der URL vorkommt:
Es ist ein Websystem mit ca. 100 php-Dateien, die alle ggf. relevanten Code enthalten, wie soll ich das machen?
So gilt z.B.:
true == ('http://example.com' !== 'http://www.example.com')
Habe ich auch schon drüber nachgedacht, ob so etwas die Ursache sein könnte. Meine Nachforschungen haben ergeben, dass das zumindest eher unwahrscheinlich ist.
Frage: Ist sicher, dass die Ursache darin zu finden ist, dass die entsprechende Datei zur Session gelöscht wurde?
Lukas
Frage: Ist sicher, dass die Ursache darin zu finden ist, dass die entsprechende Datei zur Session gelöscht wurde?
Diese Frage kannst Du beantworten. Nicht indes ein Leser in einem Forum, der weder Deinen Code kennt noch irgendetwas über Dein System weiß.
~> grep 'maxlifetime' /var/log/syslog
als hoffentlich berechtigter $USER sagt Dir (wahrscheinlich, weil auch das verbiegbar ist), ob überhaupt Sessions via Cronjobs gekillt werden.
Tach!
ini_set ('session.save_path', $s_pfad); ini_set('session.gc_maxlifetime',3800); session_start();
Der Pfad für die Session ist über eine zuvor ebenfalls eingebunden Datei bekannt.
Üblicherweise läuft der Garbage Collector beim Aufruf von session_start() los und arbeitet dann mit einer gewissen Wahrscheinlichkeit (also nicht bei jedem Aufruf) alle Session-Dateien im session.save_path ab. Wer die Dateien angelegt hat, ist nicht von Belang, und das ist immer ein Problem, wenn der session.save_path von mehreren Anwendungen mit unterschiedlichen Zeit-Konfigurationen gemeinsam genutzt wird. Eine zweite Ursache können Aufräumarbeiten des Betriebssystems sein. Manche Distributionen setzen extra noch eine eigene Aufräumroutine im Zuge der PHP-Installation auf. Wenn man abseits dieser Mechanismen seine Sessions ablegt, dürfte damit kein serverseitiges Problem auftreten. Das heißt, separates Verzeichnis außerhalb vom /tmp nehmen, und wenn regelmäßig session_start() stattfindet, sollte es auch kein Problem mit Leichen geben.
Die Ursache kann aber auch clientseitig zu finden sein, nämlich dann, wenn der Client die Session-ID verliert, beispielsweise durch Cookie-Löschen oder abgelaufener session.cookie_lifetime.
Insgesamt wird die Ursache wohl eher schwierig zu finden sein. Du könntest ein detailliertes Logging aufsetzen (selbst schreiben), und damit erstmal herausfinden, ob der Client ohne Session-ID kam oder ob die ID dieselbe wie vorher war, nur keine Session_Datei mehr existiert, oder ob vielleicht ihr Inhalt dem einer abgelaufenen Session entspricht, oder was auch immer.
Am Client kann man in die Entwicklertools und da in den Netzwerkverkehr schauen. Aber der Zug ist meist abgefahren, wenn man die erst hinterher öffnet und der Fehler nicht durch Wiederholung nachstellbar ist.
Und natürlich alle zeitgesteuerten Aktionen auf dem System kontrollieren. Vielleicht gibt es ein Cron-Log im /var/log. Da könnte vielleicht ein zeitlich passender Eintrag drin sein, wenn das die Ursache war.
dedlfix.
Hi dedlfix,
dank für Deine ausführliche Antwort.
Insgesamt wird die Ursache wohl eher schwierig zu finden sein. Du könntest ein detailliertes Logging aufsetzen (selbst schreiben), und damit erstmal herausfinden, ob der Client ohne Session-ID kam oder ob die ID dieselbe wie vorher war, nur keine Session_Datei mehr existiert, oder ob vielleicht ihr Inhalt dem einer abgelaufenen Session entspricht, oder was auch immer.
Ich glaube, genau darauf wird es hinauslaufen. Da der Fehler täglich vorkommt (leider nicht reproduzierbar), kommt man hierüber sicher am weitesten.
Lukas
Hallo und guten Abend Lukas,
ich arbeite in meinem System (php) mit Sessions, hierzu wird in jedem Script eine Datei eingebunden, die folgende Zeilen enthält
Das bedeutet also, dass es untertschiedliche Scripte gibt, die die "Session-Dateien" einbinden? bitte zeigen, wie die genau heißen, komplett mit Pfad!
ini_set ('session.save_path', $s_pfad); ini_set('session.gc_maxlifetime',3800); session_start();
Der Pfad für die Session ist über eine zuvor ebenfalls eingebunden Datei bekannt.
Und wie lautet der immer? Hast Du den schon mal zur Laufzeit in eine Logdatei geschrieben, deren Name dann bitte absolut zur Document-Root oder zur Filesystem_Root angegeben wird!
Und genau hier vermute ich deinen (prophanen) Fehler. Der ist leider wesentlich und daher nur mit dem Herzen sichtbar ;-P
Grüße
TS
ini_set ('session.save_path', $s_pfad); ini_set('session.gc_maxlifetime',3800); session_start();
Der Pfad für die Session ist über eine zuvor ebenfalls eingebunden Datei bekannt.
Und wie lautet der immer? Hast Du den schon mal zur Laufzeit in eine Logdatei geschrieben, deren Name dann bitte absolut zur Document-Root oder zur Filesystem_Root angegeben wird!
Kann ich auch mal machen. Aber ich verspreche mir davon wenig, weil die Variable $s_pfad nur ein einziges Mal in der Konfigdatei eingelesen wird, darin absolut zum Documentroot angegeben ist und sich daher niemals ändern sollte.
Und genau hier vermute ich deinen (prophanen) Fehler. Der ist leider wesentlich und daher nur mit dem Herzen sichtbar ;-P
Macht es deiner Ansicht nach Sinn, den Pfad trotzdem mal mitzuloggen?
Lukas
Tach!
Macht es deiner Ansicht nach Sinn, den Pfad trotzdem mal mitzuloggen?
Du wirst dich da vermutlich in mehreren Schritten rantasten müssen. Welche Werte du benötigst, wird sich aus den Erkenntnissen ergeben, die du beim Suchen des Fehlers gewinnst.
dedlfix.
Hallo dedlfix,
Du wirst dich da vermutlich in mehreren Schritten rantasten müssen. Welche Werte du benötigst, wird sich aus den Erkenntnissen ergeben, die du beim Suchen des Fehlers gewinnst.
Ja, sehe ich genauso. Ähnlich wie beim Reparieren eines Autos, dessen Motor nicht läuft. Dreht der Anlasser? Wenn nein, dann in diese Richtung weiter, wenn ja, dann weiter in Richtung Kraftstoff und Zündung. Usw.
Das war auch eigentlich meine Intention dieses Threads. Ein Schema zu finden, was es durch entsprechende zu ermittelnde Logdaten dann auszuwerten gilt, um den Fehler mehr und mehr einzuengen.
Lukas
Tach!
Das war auch eigentlich meine Intention dieses Threads. Ein Schema zu finden, was es durch entsprechende zu ermittelnde Logdaten dann auszuwerten gilt, um den Fehler mehr und mehr einzuengen.
Es wird schwierig für Außenstehende sein, dafür eine komplette Schritt-für-Schritt-Abarbeitungsanleitung zu geben. Die zu bekommen war vermutlich nicht dein Anliegen. Aber auch grobe Anleitungen scheitern an der Vorhersagbarkeit. Die nächsten Schritte kann man recht gut aus den Erfahrungen der vorhergehenden ableiten. Aber in der Theorie gehts dann im Schneeballsystem weiter. Das artet schnell in ein ungünstiges Aufwand-Nutzen-Verhältnis aus. Wir können dich bei deiner Fehlersuche begleiten, aber das wird nur auf die Tippeltappeltour gehen. Sprich, an den Stellen, an denen du nicht weiterkommst, können wir einen Schubs geben. Aber auch da sind uns Grenzen gesetzt, weil wir dein System nicht vor uns haben. Manchmal sieht man aus dem Augenwinkel etwas, das einem nicht eingefallen wäre, wenn man eine Strategie am Schreibtisch hätte ausarbeiten sollen, trotz aller Erfahrung.
dedlfix.
Hi dedlfix,
also gut "tippeltappeln wir" :-)
Das Blöde ist, ich warte gerade auf das Zuschlagen des Fehlers, aber er hält sich bedeckt. Ist halt, wie gesagt, ein sporadischer...
Aber ohne ihn komme ich gar nicht ins Tippeln, geschweige denn ins tappeln ;-)
Gruß, Lukas
Das hindert niemanden daran, über ein paar Dinge nachzudenken.
Ist die Session eventuell an eine IP gebunden? Könnte diese (aus Server-Sicht) gewechselt haben?
Das hindert niemanden daran, über ein paar Dinge nachzudenken.
Ist die Session eventuell an eine IP gebunden? Könnte diese (aus Server-Sicht) gewechselt haben?
Ist alles der Fall, habe ich aber bereits geprüft. IP-Wechsel liegt nicht vor.
Lukas
ini_set ('session.save_path', $s_pfad); ini_set('session.gc_maxlifetime',3800);
Geheimtipp (Bessere Lösung:)
# .htaccess, alternativ Server/Verzeichniskonfiguration
php_value session.save_path /Dein/Pfad
php_value session.gc_maxlifetime 3800
ini_set ('session.save_path', $s_pfad); ini_set('session.gc_maxlifetime',3800);
Geheimtipp (Bessere Lösung:)
# .htaccess, alternativ Server/Verzeichniskonfiguration php_value session.save_path /Dein/Pfad php_value session.gc_maxlifetime 3800
Das gefällt mir sehr gut! Denn, und hier auch schnell ein Lob an TS, es scheint nach neuesten Logeinträgen zum gegenwärtigen Zeitpunkt tatsächlich die wahrscheinlichste Lösung zu sein, dass der Pfad zur Session verloren geht.
Lukas
Geheimtipp (Bessere Lösung:)
# .htaccess, alternativ Server/Verzeichniskonfiguration php_value session.save_path /Dein/Pfad php_value session.gc_maxlifetime 3800
Habe ich gerade mal geändert. Dazu ist mir dann etwas aufgefallen. Es scheint so, als würde jetzt der Server minütlich ohne Hinzutun eines Users die Sessiondateien selbstständig aktualisieren. Ist das so? Und auch gewollt?
Lukas
Hallo,
# .htaccess, alternativ Server/Verzeichniskonfiguration php_value session.save_path /Dein/Pfad php_value session.gc_maxlifetime 3800
Habe ich gerade mal geändert.
Dazu ist mir dann etwas aufgefallen.
Es scheint so, als würde jetzt der Server minütlich ohne Hinzutun eines Users die Sessiondateien selbstständig aktualisieren.
es scheint so? Was meinst du damit?
Ist das so? Und auch gewollt?
Meines Wissens dürfte es keinen Unterschied machen, ob eine PHP-Einstellung in der php.ini oder in der Serverkonfiguration vorgenommen wird, oder sogar im Script selbst mit ini_set(). Außer natürlich bei Direktiven, die sich schon vor Script-Start auswirken, etwa die Auswertereihenfolge von GET, POST, Cookies, Environment. Solche mit ini_set() verändern zu wollen, ist natürlich Quark.
Aber eine ganz andere Frage: Wieso setzt du die Zeit ausgerechnet auf 3800? Eine Stunde, drei Minuten und zwanzig Sekunden? Ich hätte 3600 als halbwegs runden Wert genommen (eine Stunde), oder meinetwegen 4000. Aber 3800?
So long,
Martin
Tach!
Aber eine ganz andere Frage: Wieso setzt du die Zeit ausgerechnet auf 3800? Eine Stunde, drei Minuten und zwanzig Sekunden? Ich hätte 3600 als halbwegs runden Wert genommen (eine Stunde), oder meinetwegen 4000. Aber 3800?
Im Grunde ist das egal, ob der Wert nun auf Nullen oder krumm endet und ob er exakten Minuten entspricht oder nicht. In der Praxis ist es selten entscheidend, wann eine Session exakt ihren Timeout bekommt. Er muss nur ungefähr so groß sein, damit er einigermaßen komfortabel ist.
dedlfix.
Hallo und guten Tag,
Aber eine ganz andere Frage: Wieso setzt du die Zeit ausgerechnet auf 3800? Eine Stunde, drei Minuten und zwanzig Sekunden? Ich hätte 3600 als halbwegs runden Wert genommen (eine Stunde), oder meinetwegen 4000. Aber 3800?
Im Grunde ist das egal, ob der Wert nun auf Nullen oder krumm endet und ob er exakten Minuten entspricht oder nicht. In der Praxis ist es selten entscheidend, wann eine Session exakt ihren Timeout bekommt. Er muss nur ungefähr so groß sein, damit er einigermaßen komfortabel ist.
Und bitte nicht immer das Session-Management mit dem Login-Management verwechseln. Nun habe ich allerdings solange schon nicht mehr dazu rumgenölt, dass Ihr das schon wieder vergessen habt? Wird Zeit, dass ich mich wieder um Euch kümmere und meinen Senf dazugebe ;-P
Die Lebdensdauer der Session sollte immer ausreichend lang sein. GGf. kann man bei einem "Logout" gezielt Daten aus der Session herauslöschen. Es ist aber keinesfalls zwingend erforderlich, die Sessiondatei komplett zu löschen. Sollte der User nach zwei Minuten ein "Relogin" vornehmen, möchte er vielleicht gerne weiterarbeiten. Alternativ kann man die Aufsetzpunkte aus der Session natürlich auch in die Datenhaltung (Datenbank) verlegen, wohin sie in ordentlichen Systemen auch gehören.
Aber merke: Sessionmanagement <> Rechtemangement
Grüße
TS
Hi Martin,
es scheint so? Was meinst du damit?
Ich war mir nicht sicher, weil ich nicht sicher wissen konnte, ob zufälligerweise die User im Minutentakt Seiten aufrufen. Inzwischen bin ich aber sicher, dass der Server das Ohne Hinzutun der User macht. Finde ich ungewöhnlich...
Aber eine ganz andere Frage: Wieso setzt du die Zeit ausgerechnet auf 3800? Eine Stunde, drei Minuten und zwanzig Sekunden? Ich hätte 3600 als halbwegs runden Wert genommen (eine Stunde), oder meinetwegen 4000. Aber 3800?
Och, das war einfach nur, weil ich über 3600 (mein Scripteigener Timeout) gehen wollte, damit sich da nichts "ins Gehege kommt". Und ich habe schlicht 200 Sekunden drauf getan. Fühlte sich für mich als "runder Wert" an.
Lukas
Martin
--
> Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.
> - Douglas Adams, The Hitchhiker's Guide To The Galaxy
Tach!
Ich war mir nicht sicher, weil ich nicht sicher wissen konnte, ob zufälligerweise die User im Minutentakt Seiten aufrufen. Inzwischen bin ich aber sicher, dass der Server das Ohne Hinzutun der User macht. Finde ich ungewöhnlich...
In der Tat. Da ist nicht zufälligerweise ein Ajax-Polling mit im Spiel?
dedlfix.
Hallo und guten Tag,
Ich war mir nicht sicher, weil ich nicht sicher wissen konnte, ob zufälligerweise die User im Minutentakt Seiten aufrufen. Inzwischen bin ich aber sicher, dass der Server das Ohne Hinzutun der User macht. Finde ich ungewöhnlich...
In der Tat. Da ist nicht zufälligerweise ein Ajax-Polling mit im Spiel?
Das würde ja, bezogen auf den betroffenen User, die Sessionlebensdauer mit jedem Poll nachtriggern, also benau das Gegenteil von "zur Löschung freigegeben" bewirken.
Grüße
TS
In der Tat. Da ist nicht zufälligerweise ein Ajax-Polling mit im Spiel?
Das würde ja, bezogen auf den betroffenen User, die Sessionlebensdauer mit jedem Poll nachtriggern, also benau das Gegenteil von "zur Löschung freigegeben" bewirken.
Was ok für mich ist. Weil, im Grunde will ich nur sicherstellen, dass die Session solange gültig ist (und von imr aus auch ein paar Minuten länger), als ich per Login/Logout Management brauche. Wenn Logout, zerstöre ich die Sessiondatei. Passiert das, während der User arbeitet, speichere ich alle relevanten Daten in die DB und er kann dann auch von jedem Client genau dort weiter arbeiten, wo er aufgehört hat. Hierbei gehen keine Daten verloren.
Lukas
Tach!
Ich war mir nicht sicher, weil ich nicht sicher wissen konnte, ob zufälligerweise die User im Minutentakt Seiten aufrufen. Inzwischen bin ich aber sicher, dass der Server das Ohne Hinzutun der User macht. Finde ich ungewöhnlich...
In der Tat. Da ist nicht zufälligerweise ein Ajax-Polling mit im Spiel?
Hi dedlfix,
arghs, doch, klar. Daran liegts wohl... danke.
Lukas
Hallo und guten Tag Martin,
Dazu ist mir dann etwas aufgefallen.
Es scheint so, als würde jetzt der Server minütlich ohne Hinzutun eines Users die Sessiondateien selbstständig aktualisieren.
es scheint so? Was meinst du damit?
Ist das so? Und auch gewollt?
Meines Wissens dürfte es keinen Unterschied machen, ob eine PHP-Einstellung in der php.ini oder in der Serverkonfiguration vorgenommen wird, oder sogar im Script selbst mit ini_set().
nee, nee, nee
Einstellungen in der *.ini beeinflussen den Cron-Job. Einstellungen in der .htaccess oder im Script wirken sich aber nur auf die klassische Weise auf den Garbage Collector aus.
Grüße
TS
Hallo und guten Tag,
# .htaccess, alternativ Server/Verzeichniskonfiguration php_value session.save_path /Dein/Pfad php_value session.gc_maxlifetime 3800
Habe ich gerade mal geändert. Dazu ist mir dann etwas aufgefallen. Es scheint so, als würde jetzt der Server minütlich ohne Hinzutun eines Users die Sessiondateien selbstständig aktualisieren. Ist das so? Und auch gewollt?
das hängt von deinem System ab, auf dem PHP läuft. Auf Debian-Systemen wird das Session-Aufräumen von einem Cron-Job erledigt. Der ist dann i.d.R. nur noch abhängig von session.gc_maxlifetime, bzw einer adäquaten Einstellung dafür in einer PHP-Config-Datei des Servers.
Ich habe jetzt vergessen, wo genau das eingestellt wurde und ob man es trotzdem getrennt für jeden für Virt-Hosts konfigurieren konnte, ich vermute aber: JA. Das würde dann auch das von Dir beschriebene Verhalten erklären. Eine Eintragung im Virt-Host ist dem Server bekannt und kann berücksichtigt werden. Eine Einstellung per Script (oder .htaccess) ist dem Server immer nur zur Laufzeit bekannt.
Wenn Du die Einstellungen in der Hauptkonfiguration oder im Virt-Host vornimmst, würde ich auch
php_admin_value
benutzen. Das können die End-Programmierer dann nicht eigenmächtig ändern.
Grüße
TS