Apakah ada cara untuk menggunakan shell_exec tanpa menunggu perintah selesai?

95

Saya memiliki tugas proses intensif yang ingin saya jalankan di latar belakang.

Pengguna mengklik halaman, skrip PHP berjalan, dan akhirnya, berdasarkan beberapa kondisi, jika diperlukan, maka ia harus menjalankan skrip shell, EG:

shell_exec('php measurePerformance.php 47 844 [email protected]');

Saat ini saya menggunakan shell_exec , tetapi ini membutuhkan skrip untuk menunggu keluaran. Apakah ada cara untuk menjalankan perintah yang saya inginkan tanpa menunggu sampai selesai?

ToughPal
sumber
CATATAN: Prosesnya harus segera dimulai sehingga cron bukan merupakan pilihan.
ToughPal
2
Hanya catatan singkat: Pastikan halaman tidak akan dapat diakses oleh semua orang (mesin pencari / pengguna penipu) dan jika Anda berada di lingkungan bersama, waktu eksekusi semua skrip Anda (khususnya php!) Mungkin terbatas. Bagaimanapun Anda mungkin ingin melihat-lihat set_time_limit / php.ini.
merkuro
Kemungkinan duplikat php menjalankan proses latar belakang
Sean the Bean

Jawaban:

150

Bagaimana menambahkan.

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

shell_exec('php measurePerformance.php 47 844 [email protected] > /dev/null 2>/dev/null &');

Perhatikan ini juga menghilangkan stdio dan stderr.

naik opelet
sumber
2
Tidak. Tidak ada efek samping. Jika Anda kadang-kadang memutuskan ingin output stdio atau stderr dari proses Anda pertimbangkan stackoverflow.com/questions/45953/…
jitter
1
Pertanyaan: Itu hanya membuang hasilnya, bukan? Apakah PHP masih menunggu prosesnya selesai sebelum melanjutkan eksekusi, atau apakah itu menyala dan lupa?
Alan Storm
5
Ya buang. Ya, nyalakan dan lupakan
jitter
3
Catatan: > /dev/null 2>&1 &seperti yang terlihat pada jawaban lain adalah bentuk singkat yang > /dev/null 2>/dev/null &diberikan di sini. Ini pada dasarnya mengatakan "redirect STDERR (2) ke tempat yang sama dengan STDOUT (& 1)".
rymo
3
Saya biasanya mendapatkan PID dari menjalankan skrip dengan menambahkan echo $! >> /tmp/pid.txt di akhir perintah exec tetapi dengan mengarahkan output & error ke / dev / null, tidak ada lagi file pid: apakah ada di antara Anda yang bisa mendapatkan PID dari skrip yang diluncurkan oleh exec tanpa menunggu keluaran?
pelukan
28

Ini akan menjalankan perintah dan memutuskan sambungan dari proses yang sedang berjalan. Tentu saja, ini bisa berupa perintah apa pun yang Anda inginkan. Tapi untuk tes, Anda bisa membuat file php dengan perintah sleep (20).

exec("nohup /usr/bin/php -f sleep.php > /dev/null 2>&1 &");
Brent Baisley
sumber
lebih baik ini atau shell_exec?
realtebo
hai, dapatkah saya menjalankan fungsi menggunakan shell_exec ini ("nohup / usr / bin / php -f example.com/notifications/sendnotifications_async > / dev / null 2> & 1 &");
Waseem Bashir
Mengapa keduanya nohup dan &?
bugmenot123
11

Anda juga dapat memberikan output Anda kembali ke klien secara instan dan melanjutkan pemrosesan kode PHP Anda setelahnya.

Ini adalah metode yang saya gunakan untuk panggilan Ajax yang menunggu lama yang tidak akan berpengaruh pada sisi klien:

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.

Anda dapat menemukan penjelasan detailnya di sini: http://oytun.co/response-now-process-later

Oytun
sumber
1
Ops ... Saya sedang membangunkan pertanyaan zombie di sini, saya belum menyadarinya. Tetapi sedikit informasi ini dapat bermanfaat bagi orang lain.
Oytun
3
Ini tidak ada hubungannya dengan shell_exec
bugmenot123
8

Pada Windows 2003, untuk memanggil skrip lain tanpa menunggu, saya menggunakan ini:

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

Ini hanya berfungsi SETELAH memberikan izin yang diubah pada cmd.exe- tambahkan Baca dan Jalankan untuk IUSR_YOURMACHINE(Saya juga menyetel tulis ke Tolak).

Jason Plank
sumber
7

Tentu, untuk windowsAnda dapat menggunakan:

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

catatan:

Jika Anda mendapatkan COMkesalahan, tambahkan ekstensi ke Anda php.inidan mulai ulang apache:

[COM_DOT_NET]
extension=php_com_dotnet.dll
CONvid19
sumber
Saya tidak tahu tetapi itu berhasil untuk saya. Tolong ada yang menjelaskan apa itu wscript.shell dan apa fungsinya.
GeekWithGlasses
dapatkah Anda menjelaskan mengapa baris ini tidak memberikan keluaran apapun? `$ oExec = $ WshShell-> Jalankan ('C: \ Users \ Shreyash \ Desktop \ phantomjs-2.1.1-windows \ bin \ phantomjs.exe -f C: \ xampp \ htdocs \ composer \ test_0.js', 0 , false); `
GeekWithGlasses
Anda mungkin mengalami kesalahan pada test_0.js, periksa log phantom.
CONvid19
6

Gunakan popenperintah PHP , misalnya:

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

Ini akan membuat proses anak dan skrip akan dijalankan di latar belakang tanpa menunggu keluaran.

Jason Plank
sumber
4
Itu menunggu proses anak berakhir. Setidaknya pada Menang
Max Chernopolsky
Latar belakang di sini dicapai dengan bantuan perintah "start" Windows yang mengawali exe yang ingin Anda jalankan, itu tidak akan berfungsi jika Anda menghilangkannya, dan saya tidak akan mengharapkannya untuk bekerja pada OS lain ... tetapi TIDAK bekerja untuk saya, terima kasih! :-)
Antony
1

Jika keluar dari halaman web, saya sarankan untuk membuat sinyal (menjatuhkan file ke direktori, mungkin) dan meminta cron mengambil pekerjaan yang perlu dilakukan. Jika tidak, kita kemungkinan akan masuk ke wilayah penggunaan pcntl_fork()dan exec()dari dalam proses Apache, dan itu hanya masalah yang buruk.

kekacauan
sumber
1
Anda mengatakan itu adalah mojo yang buruk. bisakah kamu menjelaskannya?
Mayank
1

Itu akan berhasil tetapi Anda harus berhati-hati untuk tidak membebani server Anda karena itu akan membuat proses baru setiap kali Anda memanggil fungsi ini yang akan berjalan di latar belakang. Jika hanya satu panggilan bersamaan pada saat yang sama maka solusi ini akan melakukan pekerjaan itu.

Jika tidak maka saya akan menyarankan untuk menjalankan antrian pesan seperti misalnya beanstalkd / gearman / amazon sqs.

Alfred
sumber