2010-11-02 14 views
8

Ich habe ein PHP-Skript als Cron-Job ausgeführt, die eine Reihe von einfachen Aufgaben, die für jeden Benutzer in der Datenbank Schleifen und dauert etwa 30 Minuten abgeschlossen. Dieser Prozess beginnt jede Stunde und muss so schnell und effizient wie möglich sein. Das Problem, das ich habe, ist wie bei jedem Server-Skript, die Ausführungszeit variiert und ich muss die besten Cron-Zeiteinstellungen herausfinden.Cron-Job für PHP-Skript, das sehr lange Ausführungszeit benötigt

Wenn ich Cron jede Minute ausführen, muss ich die letzte Schleife des Skripts 20 Sekunden vor dem Ende der Minute stoppen, um sicherzustellen, dass die aktuelle Schleife in der Zeit beendet wird. Im Laufe der Stunde summiert sich dadurch viel Zeit.

Ich frage mich, ob es eine schlechte Idee ist, einfach das php-Ausführungszeitlimit zu entfernen und das Skript einmal pro Stunde laufen zu lassen und es bis zum Ende laufen zu lassen .... ist das eine schlechte Idee?

+1

Ist Ihr Cron-Job eine Website mit PHP oder PHP über die Befehlszeile aufrufen? Ich verstehe den zweiten Absatz nicht vollständig - warum stoppen Sie die Verarbeitung und starten jede Minute neu? –

+0

Ich denke, Sie können hier einige produktivere Antworten erhalten, wenn Sie erklären, was der Job zu tun hat. Es könnte einen effizienteren Weg geben, dies zu tun. – ocodo

Antwort

5

Angenommen, Sie möchten die Arbeit so schnell wie möglich erledigen, verwenden Sie nicht Cron. Cron ist gut für Dinge, die zu bestimmten Zeiten passieren müssen. Es wird oft missbraucht, um einen Hintergrundprozess zu simulieren, der im Idealfall die Arbeit verarbeitet, sobald die Arbeit erscheint. Sie sollten wahrscheinlich einen Daemon schreiben, der kontinuierlich läuft. (Hinweis: Sie können auch ein System mit Nachrichten-/Arbeitswarteschlangen betrachten, es gibt auch Bibliotheken, die dies ermöglichen)

Sie können einen Daemon von Grund auf mit dem pcntl functions schreiben (da es Ihnen egal ist) mehrere Arbeitsprozesse ist es super-easy ein Prozess im Hintergrund laufen zu bekommen.) oder zu betrügen und nur ein Skript, das für immer läuft und führen sie es über screen, oder eine feste Bibliothek Code nutzen wie PEAR System:Daemon oder nanoserv

Sobald die Für alles, was dich wirklich interessiert, ist eine Schleife, die für immer läuft. Sie sollten darauf achten, dass das Skript keinen Speicher verliert oder zu viele Ressourcen verbraucht.

Im Allgemeinen können Sie so etwas wie tun:

<?PHP 
// some setup code 
while(true){ 
    $todo = figureOutIfIHaveWorkToDo(); 
    foreach($todo as $something){ 
     //do stuff with $something 
     //remember to clean up resources so you don't leak memory! 
     usleep(/*some integer*/); 
    } 
    usleep(/* some other integer */); 
} 

Und es wird ziemlich gut funktionieren.

0

Ich habe die PHP-Befehlszeilenschnittstelle für ähnliche lange laufende Aufgaben in der Vergangenheit verwendet. Wahrscheinlich möchten Sie das Ausführungszeitlimit für eine Anfrage nicht entfernen.

0

Klingt wie eine gute Idee, wenn es wenig Chance gibt, dass es mehr als eine Stunde dauern wird. Beachten Sie jedoch, dass der falsche Bug eine sehr gute Möglichkeit sein kann, länger als erwartet zu dauern.

Um alle möglichen unangenehmen Probleme zu vermeiden, sollten Sie eine Schutzdatei mit der Prozess-ID des Skripts haben. Beim Start sollten Sie überprüfen, ob die Datei nicht existiert oder ob die Prozess-ID in der Datei nicht existiert (durch einen kid (pid, 0) -Aufruf). Wenn diese Bedingungen erfüllt sind, erstellen Sie eine neue Datei mit der PID des Skripts und löschen Sie die Datei, wenn Sie fertig sind.

Dies ist der gleiche Trick, den viele Dämonen verwenden, um sicherzustellen, dass sie nicht bereits läuft. Wenn der Daemon plötzlich beendet wurde, wird die Datei weiterhin existieren, aber die PID des Prozesses wird wahrscheinlich nicht ausgeführt.

1

Das Zeitlimit auf 0 zu setzen und es zu tun ist ziemlich typisch für PHP basierte Cronjobs (nach meiner Erfahrung), aber das ist auch der Punkt, wenn Sie sich einige wichtige Fragen stellen sollten, wie "Soll ich diesen Job in einer kompilierten Sprache umschreiben? " und "Verwende ich alle meine Tools (Datenbank usw.) zu ihrer maximalen Effizienz?"

Das heißt, vielleicht besser als das Zeitlimit vollständig zu entfernen wäre, es auf die Obergrenze zu setzen, die Sie eigentlich wollen. Wenn das 48 Minuten bedeutet, dann set_time_limit(48 * 60);

0

Je nachdem, was Ihr Skript tut, kann es zu Problemen führen, wenn Sie das Zeitlimit entfernen. Wenn Sie z. B. einen externen Server abfragen, der während der Ausführung des Jobs nicht reagiert, und dass Ihr cron 2 Stunden statt 30 Minuten benötigt, können Sie einen Stack von PHP-Prozessen erhalten, die hochgefahren werden, selbst wenn die vorherigen Ports vorhanden sind Bin noch nicht fertig. Dies kann zu Systeminstabilität und Abstürzen führen.

Sie haben wahrscheinlich zwei Möglichkeiten:

  • Achten Sie darauf, dass keine andere Instanz des Skripts zuvor ausgeführt wird, sonst exit() beim Start.
  • Überlegen Sie, Ihren Cronjob in einen Daemon zu ändern.
1

Ich denke wirklich, dass Sie die Zeit nicht auf 0 setzen sollten, das ist nur auf der Suche nach Ärger. Setzen Sie ihn höchstens auf 59 * 60 Sekunden, aber wenn Sie ihn auf 0 setzen, kann dies zu Sicherheitsproblemen führen. Bleibt ein Skript hängen, wird es fast immer hängen bleiben, bis der Server-Host die Ausführung stoppt. Es wird als schlechte Praxis angesehen, dies zu tun.

0

Muss es stündlich wie ein Uhrwerk laufen?

Wenn Sie den Job nicht teilen (Sie haben erwähnt, dass es mehr als eine einfache Aufgabe war) jede Aufgabe jede Stunde erledigen?

Oder teilen Sie es pro Benutzer, tun A-M auf Stunde, dann N-Z die nächste?

2

Anstelle max_execution_time können Sie auch set_time_limit() verwenden, um den Zähler für jede Schleife zurückzusetzen. Dies stellt sicher, dass Ihr Skript nie in der Zeit läuft, es sei denn, es gibt etwas Ernstes innerhalb der aktuellen Schleife (und dauert länger als die max_execution_time).

Im Grunde sollte dies dazu führen, dass Ihr Skript so lange ausgeführt wird, wie es benötigt wird, während es zwischen zwei set_time_limit()-Anrufen einen 30-Sekunden-Timeout gibt.

+0

Dies ist ein guter Rat. Ich bin mir nicht sicher, warum Sie nicht genug Stimmen haben. – dinwal

Verwandte Themen