SELFPHP: Version 5.8.2 Befehlsreferenz - Tutorial – Kochbuch – Forum für PHP Einsteiger und professionelle Entwickler

SELFPHP


Professional CronJob-Service

Suche



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



:: Buchempfehlung ::

PHP 5.3 & MySQL 5.1

PHP 5.3 & MySQL 5.1 zur Buchempfehlung
 

:: Anbieterverzeichnis ::

Globale Branchen

Informieren Sie sich über ausgewählte Unternehmen im Anbieterverzeichnis von SELFPHP  

 

:: Newsletter ::

Abonnieren Sie hier den kostenlosen SELFPHP Newsletter!

Vorname: 
Name:
E-Mail:
 
 

Zurück   PHP Forum > SELFPHP > PHP für Fortgeschrittene und Experten

PHP für Fortgeschrittene und Experten Fortgeschrittene und Experten können hier über ihre Probleme und Bedenken talken

Antwort
 
Themen-Optionen Ansicht
  #1  
Alt 15.04.2004, 09:16:16
c4 c4 ist offline
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_onlinetime()); 
    } 

    
// 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($fhLOCK_EX)) { 
        
fwrite($fh$content); 
       
flock($fhLOCK_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
__________________
sic!
--> http://dbCF.de/
Mit Zitat antworten
  #2  
Alt 20.04.2004, 16:08:36
c4 c4 ist offline
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?
__________________
sic!
--> http://dbCF.de/
Mit Zitat antworten
  #3  
Alt 20.04.2004, 18:01:04
Benutzerbild von meikel (†)
meikel (†) meikel (†) ist offline
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
Mit Zitat antworten
  #4  
Alt 20.04.2004, 18:29:51
c4 c4 ist offline
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.
__________________
sic!
--> http://dbCF.de/
Mit Zitat antworten
  #5  
Alt 20.04.2004, 23:38:15
Benutzerbild von meikel (†)
meikel (†) meikel (†) ist offline
SELFPHP Guru
 
Registriert seit: Dec 2003
Ort: Erfurt
Alter: 75
Beiträge: 4.001
Zitat:
Original geschrieben von _c_4_
[B]--> http://www.php.net/clearstatcache Ich nutze keine der gelisteten Funktionen. file_exists() ist ja wie gesagt auskommentiert.
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($fhLOCK_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.
Mit Zitat antworten
  #6  
Alt 21.04.2004, 18:49:07
c4 c4 ist offline
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.
__________________
sic!
--> http://dbCF.de/
Mit Zitat antworten
  #7  
Alt 22.04.2004, 13:08:27
Benutzerbild von meikel (†)
meikel (†) meikel (†) ist offline
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.
Mit Zitat antworten
Antwort


Aktive Benutzer in diesem Thema: 1 (Registrierte Benutzer: 0, Gäste: 1)
 
Themen-Optionen
Ansicht

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.

BB-Code ist an.
Smileys sind aus.
[IMG] Code ist aus.
HTML-Code ist aus.

Gehe zu


Alle Zeitangaben in WEZ +2. Es ist jetzt 16:15:59 Uhr.


Powered by vBulletin® Version 3.8.3 (Deutsch)
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.


© 2001-2024 E-Mail SELFPHP OHG, info@selfphp.deImpressumKontakt