Mam skrypt PHP, który musi wywoływać skrypt powłoki, ale nie dba o wynik. Skrypt powłoki wykonuje wiele wywołań SOAP i jest powolny do zakończenia, więc nie chcę spowalniać żądania PHP podczas oczekiwania na odpowiedź. W rzeczywistości żądanie PHP powinno być w stanie wyjść bez przerywania procesu powłoki.
Szukałem w różnych exec()
, shell_exec()
, pcntl_fork()
, itd funkcji, ale żaden z nich nie wydają się dokładnie to, co chcę zaoferować. (Lub, jeśli tak, to nie jest dla mnie jasne, jak.) Jakieś sugestie?
php
asynchronous
shell
AdamTheHutt
źródło
źródło
nice
iionice
zapobieganie przytłaczaniu skryptu powłoki przez twój system (np./usr/bin/ionice -c3 /usr/bin/nice -n19
)Odpowiedzi:
Jeśli „nie zależy na danych wyjściowych”, czy nie można wywołać exec do skryptu z
&
procesem w tle?EDYCJA - dołączając to, co @ AdamTheHut skomentował do tego postu, możesz dodać to do zaproszenia do
exec
:To przekieruje zarówno
stdio
(pierwszy>
), jak istderr
(2>
)/dev/null
i uruchomi w tle.Istnieją inne sposoby na zrobienie tego samego, ale jest to najłatwiejszy do odczytania.
Alternatywa dla powyższego podwójnego przekierowania:
źródło
&> /dev/null &
xdebug nie wygeneruje dzienników, jeśli go użyjesz. Sprawdź stackoverflow.com/questions/4883171/…/dev/null
lepszym rozwiązaniem jest używanie , ponieważ pisanie do zamkniętych FD powoduje błędy, podczas gdy próby czytania lub pisania/dev/null
po prostu w milczeniu nic nie robią.Kiedyś na do tego, jak to jest naprawdę zaczyna niezależnego procesu.
źródło
www-data
), nie ma uprawnień do używaniaat
i nie możesz go skonfigurować, możesz spróbować użyć<?php exec('sudo sh -c "echo \"command\" | at now" ');
Jeślicommand
zawiera cudzysłowy, zobacz escapeshellarg, aby zaoszczędzić ci bólu głowyecho "sudo command" | at now
i komentowaniawww-data
w/etc/at.deny
Do wszystkich użytkowników systemu Windows: Znalazłem dobry sposób na uruchomienie asynchronicznego skryptu PHP (w rzeczywistości działa z prawie wszystkim).
Opiera się na poleceniach popen () i pclose (). Działa dobrze zarówno w systemie Windows, jak i Unix.
Oryginalny kod z: http://php.net/manual/en/function.exec.php#86329
źródło
myscript.js
ale piszesznode myscript.js
. To znaczy: węzeł jest plikiem wykonywalnym, myscript.js jest skryptem do wykonania. Istnieje ogromna różnica między plikiem wykonywalnym a skryptem.php artisan
po prostu wstaw tutaj komentarz, więc nie trzeba śledzić, dlaczego nie będzie działać z poleceniamiW systemie Linux możesz wykonać następujące czynności:
Spowoduje to wykonanie polecenia w wierszu polecenia, a następnie po prostu zwróci PID, który możesz sprawdzić dla> 0, aby upewnić się, że zadziałał.
To pytanie jest podobne: czy PHP ma wątki?
źródło
action=generate var1_id=23 var2_id=35 gen_id=535
segment). Ponadto, ponieważ OP poprosił o uruchomienie skryptu powłoki, nie potrzebujesz części specyficznych dla PHP. Ostateczny kod to:$cmd = 'nohup nice -n 10 /path/to/script.sh > /path/to/log/file.log & printf "%u" $!';
nice
ale takżeionice
.&
uruchamia poprzedni kod w tle, a następnieprintf
służy do sformatowanego wyjścia$!
zmiennej zawierającej PIDProces php-execute-a-background ma kilka dobrych sugestii. Myślę, że mój jest całkiem dobry, ale jestem stronniczy :)
źródło
W systemie Linux można rozpocząć proces w nowym niezależnym wątku, dodając znak ampersand na końcu polecenia
W systemie Windows możesz użyć polecenia „start” DOS
źródło
start
polecenie w systemie Windows, nie działa asynchronicznie ... Czy możesz podać źródło, z którego otrzymałeś te informacje?/B
parametrem. Wyjaśniłem to tutaj: stackoverflow.com/a/34612967/1709903właściwy sposób (!) to zrobić
fork forks, setsid mówi bieżącemu procesowi, aby stał się nadrzędny (bez elementu nadrzędnego), wykonaj powiedz procesowi wywołującemu, aby został zastąpiony przez wywoływany aby rodzic mógł zrezygnować bez wpływu na dziecko.
źródło
Użyłem tego ...
(gdzie
PHP_PATH
const jest zdefiniowany jako podobnydefine('PHP_PATH', '/opt/bin/php5')
lub podobny)Przekazuje argumenty za pomocą wiersza polecenia. Aby przeczytać je w PHP, zobacz argv .
źródło
Jedyny sposób, który naprawdę dla mnie zadziałał, to:
źródło
shell_exec("/usr/local/sbin/command.sh 2>&1 >/dev/null | at now & disown")
i wszystko, co dostaję, to:sh: 1: disown: not found
Uważam również, że Symfony Process Component jest do tego przydatny.
Zobacz, jak to działa w repozytorium GitHub .
źródło
proc_*
funkcjach wewnętrznych.Możesz również uruchomić skrypt PHP jako demon lub cronjob :
#!/usr/bin/php -q
źródło
Użyj nazwanego fifo.
Następnie, gdy chcesz rozpocząć długo działające zadanie, po prostu napisz nowy wiersz (nieblokujący do pliku wyzwalacza).
Tak długo, jak twój wkład jest mniejszy niż
PIPE_BUF
i jest to pojedynczawrite()
operacja, możesz pisać argumenty do fifo i wyświetlać je jak$REPLY
w skrypcie.źródło
bez kolejki użycia możesz użyć
proc_open()
następującego:źródło