Wykonywanie skryptu PHP w tle

Dzisiaj borykałem się z pewnym problemem. Musiałem zrobić formularz w którym wpisujemy treść maila i wysyłamy go do min. 500 osób. Problem polegał na tym, że przy takiej ilości maili skrypt ładował się bardzo długo, aż występował błąd 504 Gateway Time-out. Więc pomyślałem o tym by Cron zajmował się wysyłką, ja bym tylko zapisywał do bazy danych nową treść, a cron co półgodziny będzie sprawdzał czy jest jakiś nowy mail do wysłania. Ale nie bardzo chciałem robić tabelę w bazie danych dla jednego pola.

Zacząłem szukać informacji. Co się okazało, jest możliwość stworzenia skryptu który działa na zasadzie „fire-and-forget” (z ang. odpal i zapomnij). Czyli mój skrypt działa teraz w ten sposób:

  1. Wpisujemy treść maila.
  2. Klikamy wyślij
  3. Strona się przeładowuje, uruchamia docelowy skrypt i wyświetla komunikat „Rozpoczęto wysyłanie wiadomości”.
  4. Skrypt zaczął się wykonywać w tle, więc spokojnie można wyłączyć zakładkę, przejść na inną stronę lub zamknąć przeglądarkę, a serwer dalej będzie wykonywał to co miał wykonać.

Idealne dla mnie rozwiązanie. Jak tego dokonać? W bardzo łatwy sposób. Nie będę tu oczywiście pisał całego skryptu bo to nie ma sensu. Wystarczy stworzyć dwa pliki php i w jednym z nich użyć funkcji – exec(), aby uruchomić drugi skrypt, co się w nich znajduje to już zależy od waszej pomysłowości.

Funkcja exec() odpowiada za wywołanie zewnętrznego programu / skryptu. PHP posiada kilka dodatkowych funkcji podobnych, różnią się one głównie otrzymywanym wynikiem – shell_exec(), system().

Aby wywołać na swojej stronie zewnętrzny skrypt PHP należy wywołać funkcję exec z odpowiednim parametrem:

  • /sendEmails.php – ścieżka do pliku
  • parametr1, parametr2 – przekazywane parametry do skryptu. Odczytujemy je za pomocą tablicy $argv

Aby odczytać parametry należy skorzystać z tablicy $argv. Pierwszy element w tablicy to ścieżka do naszego pliku, każdy kolejny element to parametr który przekazaliśmy ($argv[1] -> ‚parametr1’).

Powyższa funkcja powoduje jednak że skrypt oczekuje na wynik  uruchomionego programu. Aby tego uniknąć wystarczy dodać do komendy dodatkowe parametry.

Te dodatkowe parametry > /dev/null 2>/dev/null & powodują, że zewnętrzny program nie będzie wyrzucał wyników, przez co nasz skrypt nie będzie na nie oczekiwał i program będzie działał w tle.

Operacja ta (wywołanie w tle, sama funkcja exec dziala bez zarzutu), niestety działa tylko na serwerze opartym na Linuxie, nie jestem w stanie na chwilę obecną osiągnąć wyżej zamierzonego celu na systemach z rodziny Windows. Jest to związane z architekturą systemu. Jak tylko uda mi się dojść do tego jak uruchomić tą lub podobną funkcję która uruchomi skrypt w tle na systemie Windows, zaktualizuję wpis. Na chwilę obecną nie dysponuję tak dużą ilością czasu, aby rozwiązywać problem, który nie dotyczy mojej pracy, za co was czytelników serdecznie przepraszam.

Oczywiście jeśli ktoś z was zna rozwiązanie problemu na Windowsie, może się nim podzielić w komentarzach. Na pewno je przetestuję.