มีวิธีใช้ shell_exec โดยไม่ต้องรอให้คำสั่งเสร็จสมบูรณ์หรือไม่?


95

ฉันมีงานที่ต้องดำเนินการอย่างเข้มข้นซึ่งฉันต้องการทำงานอยู่เบื้องหลัง

ผู้ใช้คลิกบนเพจสคริปต์ PHP จะทำงานและสุดท้ายขึ้นอยู่กับเงื่อนไขบางประการหากจำเป็นก็จะต้องเรียกใช้เชลล์สคริปต์เช่น:

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

ปัจจุบันผมใช้shell_exec , แต่นี้ต้องใช้สคริปต์เพื่อรอการส่งออก มีวิธีใดบ้างที่จะเรียกใช้คำสั่งที่ฉันต้องการโดยไม่ต้องรอให้เสร็จสมบูรณ์


หมายเหตุ: กระบวนการต้องเริ่มทันทีดังนั้น cron จึงไม่ใช่ตัวเลือก
ToughPal

2
หมายเหตุสั้น ๆ : ตรวจสอบให้แน่ใจว่าทุกคนไม่สามารถเข้าถึงหน้านี้ได้ (เครื่องมือค้นหา / ผู้ใช้ที่หลอกลวง) และหากคุณอยู่ในสภาพแวดล้อมที่ใช้ร่วมกันเวลาดำเนินการของสคริปต์ทั้งหมดของคุณ (โดยเฉพาะ php!) อาจมี จำกัด ไม่ว่าในกรณีใดคุณอาจต้องการดู set_time_limit / php.ini
merkuro

คำตอบ:


150

วิธีการเพิ่ม.

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

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

โปรดทราบว่าสิ่งนี้ยังกำจัด stdio และ stderr


2
ไม่ไม่มีผลข้างเคียง หากบางครั้งคุณตัดสินใจว่าต้องการเอาต์พุต stdio หรือ stderr ของกระบวนการของคุณให้พิจารณาstackoverflow.com/questions/45953/…
jitter

1
คำถาม: นั่นเป็นเพียงการทิ้งเอาต์พุตใช่ไหม? PHP ยังคงรอให้กระบวนการเสร็จสิ้นก่อนที่จะดำเนินการต่อหรือไม่ก็เริ่มทำงานและลืม
Alan Storm

5
ใช่ทิ้งหมด ใช่ไฟและลืม
กระวนกระวายใจ

3
หมายเหตุ: > /dev/null 2>&1 &ดังที่เห็นในคำตอบอื่น ๆ เป็นรูปแบบสั้น ๆ ที่> /dev/null 2>/dev/null &ให้ไว้ที่นี่ โดยพื้นฐานแล้วจะบอกว่า "เปลี่ยนเส้นทาง STDERR (2) ไปที่เดียวกับ STDOUT (& 1)"
rymo

3
ฉันมักจะได้รับ PID ของการรันสคริปต์โดยการเพิ่ม echo $! >> /tmp/pid.txt ในตอนท้ายของคำสั่ง exec แต่โดยการเปลี่ยนเส้นทาง output & error ไปที่ / dev / null จะไม่มีไฟล์ pid อีกต่อไป: คุณสามารถรับ PID ของสคริปต์ที่ exec เปิดใช้งานโดย exec ได้หรือไม่?
hugsbrugs

28

สิ่งนี้จะดำเนินการคำสั่งและตัดการเชื่อมต่อจากกระบวนการทำงาน แน่นอนมันสามารถเป็นคำสั่งใดก็ได้ที่คุณต้องการ แต่สำหรับการทดสอบคุณสามารถสร้างไฟล์ php ด้วยคำสั่ง sleep (20) ได้

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

มันดีกว่านี้หรือ shell_exec?
realtebo

สวัสดีฉันสามารถเรียกใช้ฟังก์ชันโดยใช้ shell_exec นี้ได้หรือไม่ ("nohup / usr / bin / php -f example.com/notifications/sendnotifications_async > / dev / null 2> & 1 &");
Waseem Bashir

1
ทำไมทั้งสอง nohupและ&?
bugmenot123

11

คุณยังสามารถส่งผลลัพธ์ของคุณกลับไปยังไคลเอนต์ได้ทันทีและดำเนินการประมวลผลโค้ด PHP ของคุณในภายหลัง

นี่เป็นวิธีที่ฉันใช้สำหรับการโทร Ajax ที่รอคอยมานานซึ่งจะไม่มีผลใด ๆ กับฝั่งไคลเอ็นต์:

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.

คุณสามารถดูคำอธิบายโดยละเอียดได้ที่นี่: http://oytun.co/response-now-process-later


1
โอปส์ ... ฉันกำลังปลุกคำถามซอมบี้ที่นี่ฉันไม่ได้ตระหนัก แต่ข้อมูลเล็กน้อยนี้อาจเป็นประโยชน์ต่อผู้อื่น
Oytun

3
สิ่งนี้ไม่เกี่ยวข้องกับ shell_exec
bugmenot123

8

ใน Windows 2003 หากต้องการเรียกใช้สคริปต์อื่นโดยไม่ต้องรอฉันใช้สิ่งนี้:

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

สิ่งนี้ใช้ได้เฉพาะหลังจากให้สิทธิ์ในการเปลี่ยนแปลงcmd.exe- เพิ่ม Read and Execute for IUSR_YOURMACHINE(ฉันตั้งค่าเขียนเป็นปฏิเสธด้วย)


7

แน่นอนว่าwindowsคุณสามารถใช้:

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

บันทึก:

หากคุณได้รับCOMข้อผิดพลาดให้เพิ่มส่วนขยายลงในของคุณphp.iniและรีสตาร์ทapache:

[COM_DOT_NET]
extension=php_com_dotnet.dll

ฉันไม่รู้ แต่มันได้ผลสำหรับฉัน ใครก็ได้ช่วยอธิบายว่า wscript.shell คืออะไรและทำหน้าที่อะไร
GeekWithGlasses

คุณช่วยอธิบายได้ไหมว่าทำไมบรรทัดนี้ถึงไม่ให้ผลลัพธ์ใด ๆ `$ oExec = $ WshShell-> เรียกใช้ ('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 ตรวจสอบบันทึกผี
Pedro Lobito

6

ใช้popenคำสั่งของ PHP เช่น:

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

สิ่งนี้จะสร้างกระบวนการลูกและสคริปต์จะแยกออกในพื้นหลังโดยไม่ต้องรอเอาต์พุต


4
กำลังรอให้กระบวนการย่อยสิ้นสุดลง อย่างน้อยก็ใน Win
Max Chernopolsky

พื้นหลังที่นี่สามารถทำได้ด้วยความช่วยเหลือของคำสั่ง "start" ของ Windows ที่นำหน้า exe ที่คุณต้องการเรียกใช้มันจะไม่ทำงานหากคุณละเว้นและฉันจะไม่คาดหวังว่ามันจะทำงานบน OS อื่น ... ได้ผลสำหรับฉันขอบคุณ! :-)
Antony

1

หากไม่อยู่ในหน้าเว็บขอแนะนำให้สร้างสัญญาณบางประเภท (อาจวางไฟล์ลงในไดเรกทอรี) และให้งาน cron รับงานที่ต้องทำ มิฉะนั้นเรามีแนวโน้มที่จะเข้าสู่อาณาเขตของการใช้pcntl_fork()และexec()จากภายในกระบวนการ Apache และนั่นเป็นเพียงโมโจที่ไม่ดี


1
คุณบอกว่ามันเป็นโมโจที่ไม่ดี ช่วยอธิบายให้ละเอียดหน่อยได้ไหม
Mayank

1

วิธีนี้จะใช้งานได้ แต่คุณจะต้องระวังอย่าให้เซิร์ฟเวอร์ของคุณมากเกินไปเพราะมันจะสร้างกระบวนการใหม่ทุกครั้งที่คุณเรียกใช้ฟังก์ชันนี้ซึ่งจะทำงานในพื้นหลัง หากมีการโทรพร้อมกันเพียงครั้งเดียวในเวลาเดียวกันวิธีแก้ปัญหานี้จะทำงานได้

ถ้าไม่เช่นนั้นฉันขอแนะนำให้เรียกใช้คิวข้อความเช่น beanstalkd / gearman / amazon sqs

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.