Komutun tamamlanmasını beklemeden shell_exec kullanmanın bir yolu var mı?


95

Arka planda yürütmek istediğim süreç yoğun bir görevim var.

Kullanıcı bir sayfaya tıklar, PHP betiği çalışır ve son olarak, bazı koşullara bağlı olarak, gerekirse, bir kabuk betiği, örneğin çalıştırması gerekir:

shell_exec('php measurePerformance.php 47 844 email@yahoo.com');

Şu anda shell_exec kullanıyorum , ancak bu komut dosyasının bir çıktı için beklemesini gerektiriyor. İstediğim komutu çalıştırmak için herhangi bir yolu var mı olmadan tam beklerse o?


NOT: İşlemin hemen başlaması gerekir, bu nedenle bir cron bir seçenek değildir.
ToughPal

2
Kısa bir not: Sayfaya herkes (arama motorları / dolandırıcı kullanıcılar) tarafından erişilemeyeceğinden emin olun ve eğer paylaşılan bir ortamdaysanız, tüm komut dosyalarınızın (özellikle php!) Çalıştırılma süresi muhtemelen sınırlıdır. Her durumda set_time_limit / php.ini'ye bir göz atmak isteyebilirsiniz.
merkuro

Yanıtlar:


150

Eklemeye ne dersiniz.

"> /dev/null 2>/dev/null &"

shell_exec('php measurePerformance.php 47 844 email@yahoo.com > /dev/null 2>/dev/null &');

Bunun stdio ve stderr'den de kurtulduğunu unutmayın.


2
Hayır. Yan etki yok. Bir ara, işleminizin stdio veya stderr çıktısını istediğinize karar verirseniz, stackoverflow.com/questions/45953/…
jitter

1
Soru: Bu sadece çıktıyı atmak, değil mi? PHP, yürütmeye devam etmeden önce işlemin bitmesini hala bekler mi, yoksa çalışır ve unutur mu?
Alan Storm

5
Evet atar. Evet ateş et ve unut
jitter

3
Not: > /dev/null 2>&1 &Diğer yanıtlarda görüldüğü gibi, > /dev/null 2>/dev/null &burada verilenin kısa bir şeklidir . Bu temelde "STDERR (2) 'yi STDOUT (& 1) ile aynı yere yönlendir" diyor.
rymo

3
Genellikle echo $ ekleyerek çalışan komut dosyasının PID'sini alırım! >> /tmp/pid.txt exec komutunun sonunda ancak çıktı ve hatayı / dev / null'a yeniden yönlendirerek artık pid dosyası yok: herhangi biriniz çıktı beklemeden exec tarafından başlatılan komut dosyasının PID'sini alabilir mi?
hugsbrugs

28

Bu, bir komutu yürütecek ve çalışan işlemle bağlantıyı kesecektir. Tabii ki, istediğiniz herhangi bir komut olabilir. Ancak bir test için, bir uyku (20) komutu ile bir php dosyası oluşturabilirsiniz.

exec("nohup /usr/bin/php -f sleep.php > /dev/null 2>&1 &");

bu daha mı iyi yoksa shell_exec mi?
realtebo

merhaba, bu shell_exec ("nohup / usr / bin / php -f example.com/notifications/sendnotifications_async > / dev / null 2> & 1 &") kullanarak işlevi çalıştırabilir miyim ;
Waseem Bashir

1
Neden hem hem nohup de &?
bugmenot123

11

Çıktınızı anında istemciye geri verebilir ve daha sonra PHP kodunuzu işlemeye devam edebilirsiniz.

İstemci tarafında herhangi bir etkisi olmayacak uzun süredir bekleyen Ajax çağrıları için kullandığım yöntem bu:

ob_end_clean();
ignore_user_abort();
ob_start();
header("Connection: close");
echo json_encode($out);
header("Content-Length: " . ob_get_length());
ob_end_flush();
flush();
// execute your command here. client will not wait for response, it already has one above.

Ayrıntılı açıklamayı burada bulabilirsiniz: http://oytun.co/response-now-process-later


1
Ops ... Burada bir zombi sorusu uyandırıyordum, fark etmedim. Ancak bu bilgi biraz başkaları için faydalı olabilir.
Oytun

3
Bunun shell_exec ile ilgisi yok
bugmenot123

8

Windows 2003'te beklemeden başka bir komut dosyasını çağırmak için şunu kullandım:

$commandString = "start /b c:\\php\\php.EXE C:\\Inetpub\\wwwroot\\mysite.com\\phpforktest.php --passmsg=$testmsg"; 
pclose(popen($commandString, 'r'));

Bu, yalnızca değiştirme izinlerini verdikten SONRA çalışır cmd.exe- için Okuma ve Yürütme ekleyin IUSR_YOURMACHINE(ayrıca Yazmayı Reddet olarak ayarladım).


7

Elbette, windowskullanabilirsiniz:

$WshShell = new COM("WScript.Shell");
$oExec = $WshShell->Run("C:/path/to/php-win.exe -f C:/path/to/script.php", 0, false);

Not:

Bir COMhata alırsanız , uzantıyı hesabınıza ekleyin php.inive yeniden başlatın apache:

[COM_DOT_NET]
extension=php_com_dotnet.dll

Hiçbir fikrim yok ama benim için çalıştı. Lütfen herhangi biri wscript.shell'in ne olduğunu ve ne işe yaradığını açıklayabilir.
GeekWithGlasses

Bu satırın neden herhangi bir çıktı vermediğini açıklar mısınız? `$ oExec = $ WshShell-> Çalıştır ('C: \ Users \ Shreyash \ Desktop \ phantomjs-2.1.1-windows \ bin \ phantomjs.exe -f C: \ xampp \ htdocs \ composer \ test_0.js' ', 0 , false); ``
GeekWithGlasses

Test_0.js'de bir hata olabilir, phantom günlüğünü kontrol edin.
Pedro Lobito

6

PHP'nin popenkomutunu kullanın , örneğin:

pclose(popen("start c:\wamp\bin\php.exe c:\wamp\www\script.php","r"));

Bu, bir alt süreç yaratacak ve komut dosyası, çıktı beklemeden arka planda çalışacaktır.


4
Alt sürecin bitmesini bekler. En azından Kazanma
Max Chernopolsky

Buradaki arka plan, çalıştırmak istediğiniz exe'yi ön ekleyen Windows "başlat" komutunun yardımıyla elde edilir, atlarsanız çalışmaz ve başka bir işletim sisteminde çalışmasını beklemem ... ama YAPAR benim için çalışıyor, teşekkürler! :-)
Antony

1

Bir web sayfasının dışındaysa, bir tür sinyal oluşturmanızı (belki bir dizine bir dosya bırakmanızı) ve yapılması gereken işi bir cron işi almanızı öneririm. Aksi takdirde, Apache sürecini kullanma alanına pcntl_fork()ve exec()içinden girebiliriz ve bu sadece kötü bir mojo.


1
bunun kötü bir mojo olduğunu söyledin. detaylandırır mısın lütfen
Mayank

1

Bu işe yarayacak ancak sunucunuzu aşırı yüklememeye dikkat etmeniz gerekecek çünkü arka planda çalışacak olan bu işlevi her çağırdığınızda yeni bir işlem oluşturacaktır. Aynı anda yalnızca bir eşzamanlı arama yaparsanız, bu geçici çözüm işi yapar.

Değilse, örneğin beanstalkd / gearman / amazon sqs gibi bir mesaj kuyruğu çalıştırmanızı tavsiye ederim.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.