Problem
Mam formularz, który po przesłaniu uruchomi podstawowy kod w celu przetworzenia przesłanych informacji i wstawienia go do bazy danych w celu wyświetlenia na stronie internetowej z powiadomieniami. Ponadto mam listę osób, które zapisały się, aby otrzymywać te powiadomienia pocztą e-mail i SMS-em. Ta lista jest jak na razie banalna (tylko przesuwa około 150), jednak wystarczy, aby przejście przez całą tabelę subskrybentów i wysłanie ponad 150 e-maili trwało ponad minutę. (E-maile są wysyłane indywidualnie, zgodnie z żądaniem administratorów naszego serwera poczty e-mail z powodu zasad masowej poczty e-mail).
W tym czasie osoba, która opublikowała alert, będzie siedzieć na ostatniej stronie formularza przez prawie minutę bez żadnego pozytywnego potwierdzenia, że jej powiadomienie zostało wysłane. Prowadzi to do innych potencjalnych problemów, z których wszystkie mają możliwe rozwiązania, które moim zdaniem są mniej niż idealne.
Po pierwsze, plakat może pomyśleć, że serwer ma opóźnienia i ponownie kliknąć przycisk „Prześlij”, powodując, że skrypt uruchamia się od nowa lub uruchamia się dwukrotnie. Mogę rozwiązać ten problem za pomocą JavaScript, aby wyłączyć przycisk i zamienić tekst na coś w rodzaju „Przetwarzanie ...”, jednak jest to mniej niż idealne, ponieważ użytkownik nadal będzie utknął na stronie przez czas wykonywania skryptu. (Ponadto, jeśli JavaScript jest wyłączony, ten problem nadal istnieje).
Po drugie, plakat może przedwcześnie zamknąć kartę lub przeglądarkę po przesłaniu formularza. Skrypt będzie działał na serwerze, dopóki nie podejmie próby ponownego zapisu w przeglądarce, jednak jeśli użytkownik następnie przejdzie do dowolnej strony w naszej domenie (podczas gdy skrypt jest nadal uruchomiony), przeglądarka zawiesza się, ładując stronę do czasu zakończenia działania skryptu . (Dzieje się tak tylko wtedy, gdy zamknięta jest karta lub okno przeglądarki, a nie cała aplikacja przeglądarki). Jednak jest to mniej niż idealne.
(Możliwe) Rozwiązanie
Postanowiłem, że chcę wydzielić część „e-mail” skryptu do osobnego pliku, do którego mogę zadzwonić po wysłaniu powiadomienia. Początkowo myślałem o umieszczeniu tego na stronie potwierdzenia po pomyślnym wysłaniu powiadomienia. Jednak użytkownik nie będzie wiedział, że ten skrypt działa i żadne anomalie nie będą dla niego widoczne; Ten skrypt nie może zawieść.
Ale co, jeśli mogę uruchomić ten skrypt jako proces w tle? Tak więc moje pytanie brzmi: jak mogę uruchomić skrypt PHP, aby był uruchamiany jako usługa w tle i działał całkowicie niezależnie od tego, co użytkownik zrobił na poziomie formularza?
EDYCJA: Nie można tego zrobić. Musi zostać uruchomiony natychmiast po przesłaniu formularza. To są powiadomienia o wysokim priorytecie. Ponadto administratorzy systemu obsługujący nasze serwery nie zezwalają cronom na uruchamianie ich częściej niż 5 minut.
źródło
exec()
ale nigdy tego nie próbowałem.ajax
i wstawiamsleep()
z interwałem czasowym wewnątrz pętli (używam foreach w moim przypadku), aby uruchomić proces w tle. Działa doskonale na moim serwerze. Nie jestem pewien co do pozostałych. Dodam równieżignore_user_abort()
iset_time_limit()
(z obliczonym czasem zakończenia) przed pętlą, aby upewnić się, że skrypt nie zostanie zatrzymany przez serwer, z którego korzystam, nawet według mojego testu, skrypt wykonujący zadanie bezignore_user_abort()
iset_time_limit()
.gearman
PHP do obsługi zadań w tle. Idealnie nadaje się do skalowania, jeśli natrafisz na duże przetwarzanie i duże obciążenia. Powinieneś się temu przyjrzeć.Odpowiedzi:
Poeksperymentowałem
exec
ishell_exec
odkryłem rozwiązanie, które działało idealnie! Decyduję się użyć,shell_exec
aby móc rejestrować każdy proces powiadamiania, który ma miejsce (lub nie). (shell_exec
zwraca jako ciąg i było to łatwiejsze niż użycieexec
, przypisanie wyniku do zmiennej, a następnie otwarcie pliku do zapisu).Używam następującego wiersza, aby wywołać skrypt e-mail:
Ważne jest, aby zwrócić
&
uwagę na znak na końcu polecenia (jak wskazał @netcoder). To polecenie UNIX uruchamia proces w tle.Dodatkowe zmienne ujęte w pojedyncze cudzysłowy po ścieżce do skryptu są ustawiane jako
$_SERVER['argv']
zmienne, które mogę wywołać w moim skrypcie.Następnie skrypt poczty e-mail wyprowadza do mojego pliku dziennika za pomocą
>>
i wyświetli coś takiego:źródło
$post_id
po ścieżce skryptu php?$post_id
; Wolałbym rzucać go bezpośrednio na numer:(int) $post_id
. (Wzywając twoją uwagę, aby zdecydować, co jest lepsze.)Na serwerach Linux / Unix możesz wykonać zadanie w tle za pomocą proc_open :
&
Będąc ważnym nieco tutaj. Skrypt będzie kontynuowany, nawet jeśli oryginalny skrypt się zakończył.źródło
proc_close
po zakończeniu zadania.proc_close
powoduje zawieszenie się skryptu na około 15 do 25 sekund. Musiałbym prowadzić dziennik przy użyciu informacji o potoku, więc muszę otworzyć plik do zapisu, zamknąć go, a następnie zamknąć połączenie proc. Więc niestety to rozwiązanie u mnie nie działa.proc_close
, o to chodzi! I tak, możesz przesłać potokiem do pliku z rozszerzeniemproc_open
. Zobacz zaktualizowaną odpowiedź.Ze wszystkich odpowiedzi żadna z nich nie brała pod uwagę śmiesznie łatwej funkcji fastcgi_finish_request , która po wywołaniu przesyła wszystkie pozostałe dane wyjściowe do przeglądarki i zamyka sesję Fastcgi i połączenie HTTP, pozwalając skryptowi działać w tle.
Przykład:
źródło
PHP to
exec("php script.php")
potrafi.Z instrukcji :
Więc jeśli przekierujesz dane wyjściowe do pliku dziennika (co i tak jest dobrym pomysłem), twój skrypt wywołujący nie zawiesi się, a skrypt poczty e-mail będzie działać w bg.
źródło
A dlaczego nie wykonać żądania HTTP w skrypcie i zignorować odpowiedzi?
http://php.net/manual/en/function.httprequest-send.php
Jeśli wykonasz żądanie w skrypcie, musisz zadzwonić do serwera WWW, uruchomi go w tle i możesz (w swoim głównym skrypcie) wyświetlić komunikat informujący użytkownika, że skrypt jest uruchomiony.
źródło
Co powiesz na to?
Ten drugi skrypt PHP powinien działać jako cron.
źródło
Jak wiem, nie da się tego zrobić w prosty sposób (zobacz fork exec itp. (Nie działa pod windows)), być może możesz odwrócić podejście, użyć tła przeglądarki, wysyłając formularz w Ajax, więc jeśli post nadal praca, nie musisz czekać.
Może to pomóc, nawet jeśli będziesz musiał długo się zastanawiać.
Jeśli chodzi o wysyłanie poczty, zawsze sugeruje się użycie bufora, może to być lokalny i szybki serwer smtp, który akceptuje twoje żądania i buforuje je do prawdziwego MTA lub umieszcza wszystko w DB, niż użycie crona, który buforuje kolejkę.
Cron może znajdować się na innym komputerze, wywołując bufor jako zewnętrzny adres URL:
źródło
Zadanie cron w tle wydaje się dobrym pomysłem na to.
Będziesz potrzebował dostępu ssh do maszyny, aby uruchomić skrypt jako cron.
$ php scriptname.php
aby go uruchomić.źródło
Jeśli możesz uzyskać dostęp do serwera przez ssh i możesz uruchamiać własne skrypty, możesz stworzyć prosty serwer FIFO za pomocą php (chociaż będziesz musiał ponownie skompilować php z
posix
obsługąfork
).Serwer można naprawdę napisać w dowolnym języku, prawdopodobnie można to łatwo zrobić w Pythonie.
Lub najprostszym rozwiązaniem byłoby wysłanie HttpRequest i nie odczytanie zwracanych danych, ale serwer mógłby zniszczyć skrypt przed zakończeniem przetwarzania.
Przykładowy serwer:
Przykładowy klient:
źródło
Prostszym sposobem uruchomienia skryptu PHP w tle jest
Skrypt będzie działał w tle, a strona szybciej dotrze do strony akcji.
źródło
Zakładając, że pracujesz na platformie * nix, użyj
cron
iphp
pliku wykonywalnego.EDYTOWAĆ:
Jest już sporo pytań dotyczących „uruchamiania php bez crona” na SO. Tu jest jeden:
Planuj skrypty bez używania CRON
To powiedziawszy, powyższa odpowiedź exec () brzmi bardzo obiecująco :)
źródło
Jeśli korzystasz z systemu Windows, badań
proc_open
lubpopen
...Ale jeśli jesteśmy na tym samym serwerze „Linux”, na którym działa cpanel, to jest to właściwe podejście:
Nie używaj
fork()
lubcurl
jeśli wątpisz, że sobie z nimi poradzisz, to tak, jak nadużywanie serweraNa koniec, w
script.php
pliku, który jest wywołany powyżej, zanotuj to, upewnij się, że napisałeś:źródło
dla pracownika pracującego w tle myślę, że powinieneś wypróbować tę technikę, pomoże ona wywołać dowolną liczbę stron, wszystkie strony będą działać jednocześnie niezależnie, bez czekania na każdą odpowiedź strony jako asynchroniczną.
form_action_page.php
testpage.php
PS: jeśli chcesz wysłać parametry adresu URL jako pętlę, postępuj zgodnie z tą odpowiedzią: https://stackoverflow.com/a/41225209/6295712
źródło
W moim przypadku mam 3 parametry, jeden z nich to string (mensaje):
W moim Process.php mam ten kod:
źródło
To działa dla mnie. tyr this
źródło
serialize()
funkcję. na przykład mamindex.php
z formularzem i wysyłam wartość przez ajax do index2.php Chcę wykonać wysyłanie danych w index2.php w tle, co sugerujesz? dziękiUżyj Amphp do wykonywania zadań równolegle i asynchronicznie.
Zainstaluj bibliotekę
Przykład kodu
W swoim przypadku możesz zrobić coś takiego jak poniżej
źródło