Website alle 5 Sekunden neu laden, ohne die Website offen zu lassen


loddarmattheus

Erfahrenes Mitglied
#1
Hallo Jungs,
ich wusste nicht, wie ich es anders beschreiben sollte, aber im Prinzip stimmt es so. Wir haben ein PHP-Script laufen, welches alle 5 Sekunden neue Daten von einer externen API liest und die Daten in einer MySQL verarbeitet.
Serverseitig können wir nur Cronjobs im Minutentakt starten, was einfach zu lang ist. Jetzt haben wir in die Datei ticker_live.php oben im Header einen Refresh eingebaut, was auch gut funktioniert.

Code:
<html>

      <head>
        <meta http-equiv="refresh" content="5; URL=ticker_live.php">
      </head>

      <body>
    .......
Er ruft die auf dem Webserver liegende Datei ticker_live.php immer wieder neu auf, allerdings muss ich die Datei dazu im Browser immer geöffnet haben. Gibts es nicht eine Lösung, wo ich die Datei ticker_live.php nur einmal starte und die Datei dann sozusagen "durchläuft" bis ich die Datei stoppe (=lösche), ohne immer ein Browserfenster geöffnet zu haben?

VG Loddar
 

Sprint

Erfahrenes Mitglied
#2
Vom deinem Rechner aus geht das nicht, denn nur der Browser kann ja das Script anstoßen.

Das erste was mir dazu einfiel war ein Cronjob, der sich selbst aufruft. Daten holen, 5 Sek. sleep, sich selbst aufrufen. Ich hab sowas selbst noch nicht gebraucht, darum weiß ich nicht, ob du damit evtl. in das Zeitlimit läufst. Falls ja, beschränkst du die Anzahl der Durchläufe und startest den Cronjob nach ein paar Minuten neu.

Ansonsten sollte es noch mit serverseitigem JS funktionieren, aber da kennen sich andere besser aus.
 

ComFreek

Mod | @comfreek
Moderator
#3
Gibts es nicht eine Lösung, wo ich die Datei ticker_live.php nur einmal starte und die Datei dann sozusagen "durchläuft" bis ich die Datei stoppe (=lösche), ohne immer ein Browserfenster geöffnet zu haben?
Ja, das wäre in der Tat die bessere Lösung, selbst wenn du Cronjobs im 5-Sekundentakt erstellen könntest. Ich würde stark vermuten, dass das performanter ist, als alle 5 Sekunden einen neuen Prozess erstellen zu lassen (sehr aufwendig seitens des OS).

sleep() klingt genau nach dem, was du suchst. Ich hoffe, die Funktion führt intern kein "busy waiting" durch, sondern gibt die Kontrolle an das OS ab. Das müsstest du dann noch einmal kurz ergoogeln.
Allerdings kann dein Provider auch eine Begrenzung für die maximale Skriptausführungszeit festlegen.

Ich würde das Skript auch von außen schützen, sodass nur autorisierte Nutzer es starten dürfen. Zwecks Beendigung könntest du wegen des kurzen Intervalls von 5 Sekunden auch einfach nach jedem sleep() eine bestimmte Bedingung prüfen. Bei größeren Intervallen würde man vielleicht auf POSIX Signale umsteigen. (Bietet da PHP eine API für?)
 

Sprint

Erfahrenes Mitglied
#4
Ja, das wäre in der Tat die bessere Lösung, selbst wenn du Cronjobs im 5-Sekundentakt erstellen könntest. Ich würde stark vermuten, dass das performanter ist, als alle 5 Sekunden einen neuen Prozess erstellen zu lassen (sehr aufwendig seitens des OS).
So wie ich ihn verstanden hatte, soll das Browserfenster nach dem ersten Anstoß geschlossen werden. Ansonsten könnte der Browser auch über AJAX immer wieder ein Script starten. Natürlich müßte auch hier der Browser offen bleiben, aber wen stört das denn wirklich? Fenster minimieren und weg isses.
 

loddarmattheus

Erfahrenes Mitglied
#5
Hallo Jungs,
das mit dem Sleep() werde ich mir mal anschauen.

Denn - kleiner Zwischenstand - mit dem 5 sekündigen Refresh läuft es dann doch nicht so, da mein Provider das Script kurzerhand nach etwa einer Stunde gekillt hat. Offenbar muss ich da in irgendetwas reingelaufen sein, was der Server als Endlosschleife interpretiert hat.

Irgendwelche andere Ideen? Wie sähe denn eine AJAX Lösung ansatzweise aus?
 

ComFreek

Mod | @comfreek
Moderator
#6
Natürlich müßte auch hier der Browser offen bleiben, aber wen stört das denn wirklich? Fenster minimieren und weg isses.
Wenn der PC ausgeschaltet ist (etwa bei einem Update), verpasst man Zeitfenster. Genauso außerhalb der Arbeitszeiten.

Denn - kleiner Zwischenstand - mit dem 5 sekündigen Refresh läuft es dann doch nicht so, da mein Provider das Script kurzerhand nach etwa einer Stunde gekillt hat. Offenbar muss ich da in irgendetwas reingelaufen sein, was der Server als Endlosschleife interpretiert hat.
Lass das Skript nur 45 Minuten lang laufen (zur Sicherheit) und setz einen Cronjob alle 45 Minuten, der das Skript wieder startet.
Ich würde dir aber wirklich raten, das mit dem Provider abzuklären.
 

Technipion

Erfahrenes Mitglied
#7
Hallo loddarmattheus,
Wir haben ein PHP-Script laufen, welches alle 5 Sekunden neue Daten von einer externen API liest und die Daten in einer MySQL verarbeitet.
kannst du den Teil vielleicht nochmal etwas genauer erklären? Womöglich lässt sich ja dieser automatisierte Abruf eleganter gestalten...

Ansonsten gibt es auch immer die Möglichkeit - falls dir die Verwendung deines eigenen Browsers zu lästig ist oder es Probleme mit den Arbeitszeiten gibt - einen externen Webdienst zu nutzen, der in regelmäßigen Abständen deine PHP-Seite aufruft. Ist aber natürlich alles immer ziemlich rumgebastelt es so zu lösen. Cronjob wäre da schon deutlich sauberer. Bzw. vielleicht kann man ja wie oben gesagt den ganzen Abruf des API irgendwie schöner gestalten.

Gruß Technipion
 

loddarmattheus

Erfahrenes Mitglied
#8
Klar, gerne erkläre ich es etwas genauer. Und zwar fragen wir mit dem Script alle 5 Sekunden Kursdaten (in diesem Fall BTC_USD) von der API der Webseite Bitfinex ab.

Die Klasse:
Code:
class Bitfinex
{
    public function returnTicker($waehrung)
    {
        return $this->queryPublic($waehrung);       
    }    
    
private function queryPublic($command)
    {
        $uri = file_get_contents('https://api.bitfinex.com/v1/trades/'.$command);
       return json_decode($uri, true);
    
}
und hier die Datei ticker_live.php:

Code:
<html>
      <head>
        <meta http-equiv="refresh" content="5; URL=ticker_live.php">
      </head>
<body>

<?php

include("bitfinex_class2_live.php");
include("config_live.php"); //Datenbank-Zugriff

$foo = new Bitfinex;
$alle =    $foo->returnTicker('tBTCUSD');

                // Create connection
                $conn = new mysqli($host, $username, $password, $dbname);
                // Check connection
                if ($conn->connect_error) {
                    die("Connection failed: " . $conn->connect_error);
                }
    
                $sql = "INSERT INTO bitfinex_ticker (last_bid, last_bid_size, last_ask, last_ask_size, daily_change, last_price, daily_volume, daily_high, daily_low, timestamp) VALUES ('" . $alle[0] . "', '" . $alle[1] . "', '" . $alle[2] . "', '" . $alle[3] . "', '" . $alle[4] . "', '" . $alle[6] . "', '" . $alle[7] . "', '" . $alle[8] . "', '" . $alle[9] . "', '" . $timestamp . "')";
                $conn->query($sql);       
  ?>
       </body>
    </html>
Ich habe heute mal beim Provider angefragt, warum wir nach ca. 1 Stunde einen Timeout bekommen. Mal gucken, was die uns vorschlagen.
 

loddarmattheus

Erfahrenes Mitglied
#9
Habe soeben die Antwort des Providers erhalten. Da ich nur auf einem SharedServer "laufe", unterliegen sämtliche Scripte einer maximalen Ausführungszeit. Ich habe jetzt folgende Idee:

Mein Script wird mit einem (minütlichen) Cron angestoßen, lädt sich alle 5 Sekunden neu und nach einer Schleife von 12 Wiederholungen schließt es sich. Dann ist die Minute vorbei und der Cron öffnet die Datei dann wieder. Ginge das irgendwie?
 

Sprint

Erfahrenes Mitglied
#10
Natürlich geht das. Hatte ich ja in meinem ersten Post schon vorgeschlagen. Die Seite muß sich nur selbst aufrufen. Du mußt entweder eine Session einrichten, damit der Zähler erhalten bleibt oder du gibst ihr den Wert z.B. als GET Variable mit.
Mach aber nur 11 Durchläufe, da der 12. ja schon wieder zum neuen Job gehört. Ansonsten würde der letzte Durchgang wohl gegen die Wand laufen, was aber auch nur die Log Datei interessiert.
 

ComFreek

Mod | @comfreek
Moderator
#11
Mein Script wird mit einem (minütlichen) Cron angestoßen, lädt sich alle 5 Sekunden neu und nach einer Schleife von 12 Wiederholungen schließt es sich. Dann ist die Minute vorbei und der Cron öffnet die Datei dann wieder. Ginge das irgendwie?
Ich habe oben bereits die Antwort geschrieben: sleep().

Das heißt aber trotzdem nicht, dass das nicht gegen die Bestimmungen deines Shared Hosting Betreibers verstößt. Ggf. sperrt er dann unangekündigt deine Seite.
Gibt es keine Möglichkeiten, die Kursdaten auch für die Vergangenheit z. B. für den ganzen letzten Tag zu erhalten? Dann bräuchtest du dein Skript nur einmal pro Tag laufen lassen.
 

loddarmattheus

Erfahrenes Mitglied
#12
Hi Jungs,

das mit dem Sleep scheint wenigstens lokal ganz gut zu funktionieren. Doch ich habe jetzt ein Riesenproblem, welches ich nicht lösen kann: Wie kann ich die php Datei denn nach Ablauf des 11en Sleep automatisch wieder schließen?

VG
 

Sprint

Erfahrenes Mitglied
#13
Gar nicht. Du prüfst über ein if, ob die 11 erreicht ist. Wenn ja, läßt du das Script einfach auslaufen, wenn nein, geht er ins nächste sleep. Der Server wirft es dann schon raus.