Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Wykonanie skryptu partiami
Forum PHP.pl > Forum > PHP
Albinos
Witam, chciałbym usłyszeć wasze rady i podpowiedzi w sprawie wykonania skryptu partiami.
Mam sobie skrypt w którym jest pętla, która najpierw łączy się z bazą mysql, pobiera nazwę użytkownika na podstawie nicku łaczy się ze stroną np www.strona.pl/nick, pobiera wymagane dane przez curl, generuje z nich obrazek i kod html oraz aktualizuje te dane w tej samej bazie dla danego użytkownika.
Dla jednego użytkownika trwa to poniżej 5 sekund. Daję też przerwę 5 sekund między osobami(sleep(5) na koncu pętli) żeby serwer tam za bardzo się nie grzał wink.gif .Ale mając w bazie powiedzmy 100 trwa to (łatwo policzyć) (5+5)*100=10000sekund, no a to wszystko chcę uruchamiać przez cron a zazwyczaj hostingi oferują timeout 300sekund.

I teraz sedno. Jak mogę zrobić żeby skrypt dzielił całość na części? Żeby to działało np tak.
Uruchamia się skrypt. Loguje się do bazy, na strone przez curl i rusza pętla.
Pętla pobiera pierwszego użtkownika, pobiera dane generuje co tam ma generować oraz odpoczywa 5 sekund.
I tak do użytkownika o id 10.
Teraz się przerywa skrypt i uruchamia ponownie ale zaczyna już od użytkownika o id 11
i tak po 10 do końca.
Na końcu musi ustawić się jakoś na początku ale już żeby się nie uruchamiało.
Docelowo chcę robić taką aktualizację 2-3 razy dziennie czyli co 12-8godzin.
Pozdrawiam
in5ane
Proponuję rozwiązanie, żebyś utworzył sobie w bazie jakieś dodatkowe pole, w którym będziesz oznaczał sobie, czy już użytkownik został pobrany, czy nie. Możesz sobie ustawiać jako wysłane 1, a Ci nie wysłani niech mają 0. I uruchamiaj skrypt, co kilka minut z crona. Na końcu uruchom skrypt, który zmieni wszystkim użytkownikom status wysyłki z 1 na 0, żeby przy następnej operacji mogło dziać się to samo na nowo.
Albinos
Ale wtedy nie da rady o stałą ilość w partii? Powiedzmy że ustawię crona co 2 minuty no to przez te 2 minuty będą się jakieś tam aktualizować i potem cron odpali ponownie czyli pierwszy przebieg się przerwie? Dobrze myślę? I zacznie od tych co mają pole zero, ale na końcu jak ustawi zera dla wszytskich to zacznie się od nowa ale ja chcę powiedzmy takie 2 przebiegi na dobę
dżozef
no to twórz tymczasowy plik podczas gdy skrypt działa, a po zakończeniu go usuwaj. przy uruchomieniu skryptu sprawdzaj czy istnieje, a jak tak - daj opóźnienie, jeśli nadal istnieje - przerwij (żeby się nie zapętlić).
Albinos
a czy jeśli dam w skrypcie refresh to cron potraktuje to jako nowe wywołanie skryptu czy te same? bo jeśli te same to i tak przekroczy timeout i nic mi to nie da

Ok zrobiłem tak:
dodałem kolumnę updated, jeśli user jest zaktualizowany jest 1 jeśli nie 0.
Plik zerowanie.php, zeruje wszytskie pola updated i przekierowuje do pliku petla.php
w tym pliku jest pętla która wykonuje się dla uzytkownka jesli pole updated jest 0, dodałem licznik i po 5 obrotach petli przerywam ją i odświeżam stronę po 10s (header(refresh: 10))
Wszystko działa cacy jeśli robię to przez przeglądarkę ale przez cron już zatrzymuje się na zerowaniu pól updated i nie idzie przez header do petla.php
Czy tak to jest z cron?
Czyli jak nie reaguje na header to w petli też się nie odświeży?
Korzystam z zewnętrznego serwisu do cron bo na swoim serwerze nie mam, a czy jakbym miał to by działało?
Mże jakieś rozwązania macie na ten problem?
freemp3
Funkcja header nie zadziała Ci w cron. Odpalenie skryptu przy jego pomocy jest równoznaczne z wpisaniem polecenia z palca w konsoli. To że wyślesz nagłowki nic nie da bo konsola ich nie odbierze i nie obsłuży wink.gif
Możesz zrobić to w inny sposób. Skoro chcesz to aktualizować dwa razy na dobę powiedzmy między północą i 12 oraz drugi raz między 12 a północą.
Kolumnę updated ustawiasz jako typ DATETIME i zapisujesz w niej kiedy był zrobiony ostatni update użytkownika. Aby wiedzieć czy skrypt jest wykonywany pierwszy raz dla użytkownika czy drugi należy sprawdzić aktualną godzinę przy pomocy funkcji date:
Kod
$hour = date('H')

Jeśli godzina jest między między 0 a 11 (włącznie) to mamy pierwsze, jeśli między 12 a 23 (włącznie) to drugie. Ustalenie tego jest konieczne do określenia warunku w zapytaniu do bazy, którym będziemy wyciągać użytkowników:
Kod
$date = date('Y-m-d');
if($hour >= 0 && $hour <= 11)
  $date .= '00:00:00';
else
  $date .= '12:00:00';
$sql = 'SELECT * FROM users WHERE updated < ' . $date . 'ORDER BY updated'; // sortujemy według tych, którzy najdłużej nie byli aktualizowani

Przy aktualizacji użytkownika w bazie danych w kolumnie updated podajemy wartość 'NOW()'. W tedy będziemy mieli zapisaną dokładną datę i godzinę, w której użytkownik został zaktualizowany

Co do samego uruchamiania skryptu to tak jak sugerowali poprzednicy uruchamiasz cron-a co określony odstęp czasu. Aby skrypty nie kolidowały tworzysz plik tymczasowy np: .updating.lock, a żeby było jeszcze bezpieczniej w nim umieszczasz aktualny czas:
Kod
file_put_contents('.updating.lock', time())

Po każdym przejściu pętli także należy zaktualizować czas znajdujący się w pliku. Dlaczego umieszczać czas w pliku? Odpowiedź jest prosta. Jeśli skrypt z jakiegoś powodu się wysypie to plik zostanie na stałe, a kolejne uruchamiane skrypty będą "myślały", że pierwszy cały czas działa, dlatego podczas uruchamiania skryptu oprócz sprawdzania czy plik istnieje można sprawdzić jaki był ostatni czas zapisu. Jeśli był wiekszy niż np 10 minut, to znaczy, że wcześniejszy skrypt się wysypał i obecny może kontynuować aktualizację.
Kod
if(file_exists('.updating.lock'))
{
  $time = (int)file_get_contents('.updating.lock');
  if(($time + (60 * 10)) > time()) // poprzedni skrypt działa więc wychodzimy
    exit();
}


To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.