CronJob-Service
bei SELFPHP mit ...
|
+ minütlichen Aufrufen
+ eigenem Crontab Eintrag
+ unbegrenzten CronJobs
+ Statistiken
+ Beispielaufrufen
+ Control-Bereich
Führen Sie mit den CronJobs von
SELFPHP zeitgesteuert Programme
auf Ihrem Server
aus. Weitere Infos
|
:: Anbieterverzeichnis ::
Globale Branchen
Informieren Sie sich über ausgewählte Unternehmen im Anbieterverzeichnis von SELFPHP
:: Newsletter ::
Abonnieren Sie hier den kostenlosen
SELFPHP Newsletter!
|
PHP für Fortgeschrittene und Experten Fortgeschrittene und Experten können hier über ihre Probleme und Bedenken talken |
15.04.2004, 09:16:16
|
SELFPHP Guru
|
|
Registriert seit: Jul 2002
Ort: Oberursel
Alter: 54
Beiträge: 4.748
|
|
Besucherzähler setzt sich selbsständig zurück
Moin,
so schön mein neuer Besucherzähler auch ist, so unlogisch ist das Problem: Irgendwann wird aus noch ungeklärter Ursache die Statistik gelöscht und alles geht von vorn los.
Das Skript:
PHP-Code:
<?php
// Funktion mit $counter=user_counter() aufrufen.
// Nach Ablauf des Skriptes stehen dann folgende Variablen zur Verfuegung:
// $counter['hits_today'] Hits am heutigen Tag
// $counter['hits_yesterday'] Hits vom Vortag
// $counter['visits_today'] Besucher am heutigen Tag
// $counter['visits_yesterday'] Besucher vom Vortag
// $counter['hits_total'] Gesamthits
// $counter['visits_total'] Gesamtbesucherzahl
// $counter['user_online'] Zahl der User, die online sind
// $counter['max_online'][0] Maximale Zahl gleichzeitiger Besucher
// $counter['max_online'][1] ...zu diesem Zeitpunkt. Fuer Formatierung siehe [url]http://php.net/date[/url]
function user_counter() {
// Pfad zur Datei, in der alles gespeichert werden soll
$datafile='./counter_db.php';
// Zeit in Sekunden, die ein Besucher als online gelten soll
$time_user_online=300;
// Zeit in Sekunden, die ein Besucher nicht als neuer Besucher gezaehlt werden soll
$time_visits=1800;
// Zeitstempel speichern
$timestamp=date('Ymd');
$timestamp_yesterday=date('Ymd', time()-86400);
// Falls 'Datenbank' noch nicht existiert, dann mit Standardwerten erstellen
// -->> Nach erstem Durchlauf auskommentieren! <<--
// /* vor if und
// */ hinter } (geschweifte Klammer)
if (!file_exists($datafile)) {
$fh=fopen($datafile, 'w');
$content='';
$content.="<?phpn";
$content.="$ips[]=array(0, 0, 0);n";
$content.="$counter['hits_total']=0;n";
$content.="$counter['visits_total']=0;n";
$content.="$counter['max_online']=array(0, 0);n";
$content.="?>";
fwrite($fh, $content);
fclose($fh);
}
// Diese Datei einbinden
include($datafile);
// Hits erhoehen - heutige und gesamt
if (!isset($hits[$timestamp])) {
$hits[$timestamp]=1;
}
else {
$hits[$timestamp]++;
}
$counter['hits_total']++;
// Visits setzen, wenn nicht vorhanden
if (!isset($visits[$timestamp])) {
$visits[$timestamp]=0;
}
// Zaehler fuer aktive Nutzer auf Seite
$user_online=0;
// IPs aussortieren und aktualisieren
$found_ip_v=$found_ip_o=0;
for ($i=0; $i<count($ips); $i++) {
// Alte IPs entfernen
// v - Visits, o - Online
if ($ips[$i][2]=='v' && time()-$time_visits>$ips[$i][1]) {
$ips[$i]=0;
continue;
}
elseif ($ips[$i][2]=='o' && time()-$time_user_online>$ips[$i][1]) {
$ips[$i]=0;
continue;
}
// Zeiten der aktuellen IP neu setzen
if ($ips[$i][0]==$_SERVER['REMOTE_ADDR'] && $ips[$i][2]=='v') {
$ips[$i][1]=time();
$found_ip_v=1;
}
// Zeiten der aktuellen IP neu setzen
elseif ($ips[$i][0]==$_SERVER['REMOTE_ADDR'] && $ips[$i][2]=='o') {
$ips[$i][1]=time();
$found_ip_o=1;
}
if ($ips[$i][2]=='o') {
// Zaehler fuer aktive Nutzer auf Seite erhoehen
$user_online++;
}
}
// IP hinzufuegen, wenn noch nicht in Liste
if ($found_ip_v==0) {
// Visits erhoehen
$visits[$timestamp]++;
$counter['visits_total']++;
// Zaehler fuer aktive Nutzer auf Seite erhoehen
$user_online++;
// IP hinzufuegen
$ips[]=array($_SERVER['REMOTE_ADDR'], time(), 'v');
$ips[]=array($_SERVER['REMOTE_ADDR'], time(), 'o');
}
elseif ($found_ip_o==0) {
// Zaehler fuer aktive Nutzer auf Seite erhoehen
$user_online++;
// IP hinzufuegen
$ips[]=array($_SERVER['REMOTE_ADDR'], time(), 'o');
}
if ($user_online>$counter['max_online'][0]) {
$counter['max_online']=array($user_online, time());
}
// Daten fuer neue 'Datenbank' sammeln
$content='';
$content.="<?phpn";
foreach ($hits as $k => $v) {
$content.="$hits['$k'] = $v;n";
}
foreach ($visits as $k => $v) {
$content.="$visits['$k'] = $v;n";
}
$content.="$counter['hits_today'] = {$hits[$timestamp]};n";
$content.="$counter['hits_yesterday'] = ".(isset($hits[$timestamp_yesterday]) ? $hits[$timestamp_yesterday] : 0).";n";
$content.="$counter['visits_today'] = {$visits[$timestamp]};n";
$content.="$counter['visits_yesterday'] = ".(isset($visits[$timestamp_yesterday]) ? $visits[$timestamp_yesterday] : 0).";n";
$content.="$counter['hits_total'] = {$counter['hits_total']};n";
$content.="$counter['visits_total'] = {$counter['visits_total']};n";
$content.="$counter['user_online'] = $user_online;n";
$content.="$counter['max_online'] = array({$counter['max_online'][0]}, {$counter['max_online'][1]});n";
foreach ($ips as $k => $v) {
if ($v!=0) {
$content.="$ips[] = array('$v[0]', $v[1], '$v[2]');n";
}
}
$content.="?>";
// 'Datenbank' speichern
$fh=fopen($datafile, 'w');
if (flock($fh, LOCK_EX)) {
fwrite($fh, $content);
flock($fh, LOCK_UN);
}
fclose($fh);
// Datei erneut einbinden, damit aktualisierte Werte uebergeben werden koennen
include($datafile);
return $counter;
}
?>
Auch zu finden unter http://dbCF.de/t-besucherzaehler/
Das Problem trat gestern nicht zum ersten Mal auf. Aber zum ersten Mal mit der Nutzung von flock() Vorher ist es auch schon ohne passiert.
Ich lasse mir jetzt immer eine Mail schicken, wenn die Gesamtzahl aller Besucher kleiner fünf ist. In der Hoffnung, dass ich rausfinde, bei welcher Seite das passiert ist. Bisher hat mir der Inhalt noch nicht geholfen.
Wie gesagt: Ich weiß nicht warum es passiert.
Könnte es an der Zahl (bis zu 20) gleichzeitiger Zugriffe liegen? Aber PHP sorgt doch eigentlich dafür, dass dann alles der Reihe nach abläuft, nicht oder?
Externe Variablen dürften auch kein Problem sein, ist es doch schließlich eine Funktion, die sich nur um ihr eigenes Zeug kümmert.
Hinweis: An dem
PHP-Code:
if (!file_exists($datafile))
wie im Skript zu sehen, liegt es nicht, das ist bei mir auskommentiert.
Ich weiß, dass das Skript auch von anderen genutzt wird - dafür ist es ja da. Ich habe allerdings noch keine Beschwerden zu dem Thema erhalten. Entweder sind die bloß zu faul oder es liegt an meinen anderen Skripten.
So, das war's erst einmal, was mir so einfällt. Würde mich freuen, wenn ihr mir helfen könnt.
Bye
Carsten
|
20.04.2004, 16:08:36
|
SELFPHP Guru
|
|
Registriert seit: Jul 2002
Ort: Oberursel
Alter: 54
Beiträge: 4.748
|
|
Das Problem besteht noch immer! Netterweise ist es jetzt mal bei mir aufgetreten. Der Grund: Die counter_db.php (die Datei, in der alles gespeichert wird) war leer. Komplett leer! Ich weiß nicht warum.
Ideen?
|
20.04.2004, 18:01:04
|
|
SELFPHP Guru
|
|
Registriert seit: Dec 2003
Ort: Erfurt
Alter: 75
Beiträge: 4.001
|
|
Zitat:
Original geschrieben von _c_4_
|
>Der Grund: Die counter_db.php (die Datei, in der alles gespeichert
>wird) war leer. Komplett leer!
Den Fehler mußt Du erkennen und abfangen.
>Ich weiß nicht warum. Ideen?
Der Fehler tritt auf, wenn Besucher B das File lesen möchte, was gerade von Besucher A geschrieben wird. Das Problem dabei ist, daß PHP, "um eine bessere Performance zu bieten", den Status der Datei speichert (cached).
-> http://www.php.net/clearstatcache
|
20.04.2004, 18:29:51
|
SELFPHP Guru
|
|
Registriert seit: Jul 2002
Ort: Oberursel
Alter: 54
Beiträge: 4.748
|
|
--> http://www.php.net/clearstatcache
Zitat:
When you use stat(), lstat(), or any of the other functions listed in the affected functions list (below), PHP caches the information those functions return
|
Ich nutze keine der gelisteten Funktionen. file_exists() ist ja wie gesagt auskommentiert.
> Den Fehler mußt Du erkennen und abfangen.
Wenn sie leer ist, dann ist es zu spät.
$content - die Variable, in der der Dateiinhalt gesammelt wird hat definitiv einen Inhalt:
Code:
$content='';
$content.="<?phpn";
Die erstellte Datei war aber absolut leer.
> Der Fehler tritt auf, wenn Besucher B das File lesen möchte, was gerade von Besucher A geschrieben wird.
> Das Problem dabei ist, daß PHP, "um eine bessere Performance zu bieten", den Status der Datei speichert
Ich dachte PHP sorgt dafür, dass das alles schön der Reihe nach abläuft?! Außerdem sollte flock($fh, LOCK_EX) dieses Problem zusätzlich umgehen.
|
20.04.2004, 23:38:15
|
|
SELFPHP Guru
|
|
Registriert seit: Dec 2003
Ort: Erfurt
Alter: 75
Beiträge: 4.001
|
|
Es betrifft genaugenommen alle Dateifunktionen, bei denen PHP den Status über das System ermitteln muß.
Zitat:
> Den Fehler mußt Du erkennen und abfangen.
Wenn sie leer ist, dann ist es zu spät.
|
[php] if (!file_exists($datafile)) {
$fh=fopen($datafile, 'w');[/php
Das geht so nicht. Es ist unwichtig, ob das File existiert - es muß zum Zeitpunkt les- und beschreibbar sein.
Das ist auch ungenau:
PHP-Code:
$fh=fopen($datafile, 'w');
if (flock($fh, LOCK_EX)) {
Bevor das Script schreiben will, muß es testen, ob es das genau zu dem gewünschten Zeitpunkt auch darf. Ein Webserver ist keine Mailbox mit nur einem einzigen Modem. Da können sich schon auf einem Schlag mal 50-100 User "rumtreiben".
Das ist ebenfalls ungenau:
PHP-Code:
include($datafile);
Was passiert, wenn während der Laufzeit das Script von einem anderen Task geändert wurde?
Du kannst das nur mittels eines semaphor Files klären, welches am Anfang der Funktion gesetzt wird und nach dem fclose wieder gelöscht wird. Existiert das File, schickst Du alle anderen so lange "in die Warteschleife", bis das File gelöscht wurde.
Besser wäre allerdings eine SQL DB (wenn man ohne solche unnötigen Statistiken absolut nicht leben kann).
Optimal ist allerdings der Verfzicht auf solche Darstellungen. Für Statistikzwecke kann man ja nachts mal das Logfile durchackern.
|
21.04.2004, 18:49:07
|
SELFPHP Guru
|
|
Registriert seit: Jul 2002
Ort: Oberursel
Alter: 54
Beiträge: 4.748
|
|
Zitat:
Du kannst das nur mittels eines semaphor Files klären, welches am Anfang der Funktion gesetzt wird und nach dem fclose wieder gelöscht wird. Existiert das File, schickst Du alle anderen so lange "in die Warteschleife", bis das File gelöscht wurde.
|
Wie soll ich eine Warteschleife realisieren? Eine Schleife, die bei Bedarf 10.000 Mal durchlaufen wird? Oder gibt's was eleganteres?
Zitat:
Besser wäre allerdings eine SQL DB.
|
Stimmt, ja. Das Skript ist weniger für mich, als viel mehr für den Rest der Welt, der das nutzen will. Es scheint massig PHP-, aber nicht PHP-mit-MySQL-Nutzer geben.
|
22.04.2004, 13:08:27
|
|
SELFPHP Guru
|
|
Registriert seit: Dec 2003
Ort: Erfurt
Alter: 75
Beiträge: 4.001
|
|
Zitat:
Original geschrieben von _c_4_
Wie soll ich eine Warteschleife realisieren? Eine Schleife, die bei Bedarf 10.000 Mal durchlaufen wird? Oder gibt's was eleganteres?
|
sleep ()
Du mußt aber immer testen lassen, ob nicht etwa User 4711 'nen Tick schneller war...
btw: das ganze Verfahren ist insgesamt so krötig, wenn man es 100%-ig sicher machen will, daß es schon keinen Spaß mehr macht. <ggg>
Ich hatte da irgend wann aufgegeben und den ganzen Summs durch
UPDATE statistik SET counter = counter + 1;
ersetzt. Da es nur ein Hit-Zähler werden sollte, hatte ich mir IP Auswertung komplett erspart.
|
Aktive Benutzer in diesem Thema: 1 (Registrierte Benutzer: 0, Gäste: 1)
|
|
Themen-Optionen |
|
Ansicht |
Linear-Darstellung
|
Forumregeln
|
Es ist Ihnen nicht erlaubt, neue Themen zu verfassen.
Es ist Ihnen nicht erlaubt, auf Beiträge zu antworten.
Es ist Ihnen nicht erlaubt, Anhänge hochzuladen.
Es ist Ihnen nicht erlaubt, Ihre Beiträge zu bearbeiten.
HTML-Code ist aus.
|
|
|
Alle Zeitangaben in WEZ +2. Es ist jetzt 16:15:59 Uhr.
|