Có cách nào để sử dụng shell_exec mà không cần đợi lệnh hoàn thành không?


95

Tôi có một công việc chuyên sâu về quy trình mà tôi muốn chạy trong nền.

Người dùng nhấp vào một trang, tập lệnh PHP chạy và cuối cùng, dựa trên một số điều kiện, nếu được yêu cầu, thì nó phải chạy một tập lệnh shell, EG:

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

Hiện tại tôi sử dụng shell_exec , nhưng điều này yêu cầu tập lệnh phải đợi đầu ra. Có cách nào để thực hiện lệnh tôi muốn mà không cần đợi nó hoàn thành không?


LƯU Ý: Quá trình phải bắt đầu ngay lập tức vì vậy cron không phải là một tùy chọn.
ToughPal

2
Chỉ cần lưu ý nhanh: Đảm bảo rằng trang này sẽ không thể truy cập được bởi tất cả mọi người (công cụ tìm kiếm / người dùng gian lận) và nếu bạn đang ở trên môi trường chia sẻ, thời gian thực thi của tất cả các tập lệnh của bạn (đặc biệt là php!) Có thể bị giới hạn. Trong mọi trường hợp, bạn có thể muốn xem set_time_limit / php.ini.
merkuro

Câu trả lời:


150

Làm thế nào về việc thêm.

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

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

Lưu ý rằng điều này cũng loại bỏ stdio và stderr.


2
Không. Không có tác dụng phụ. Nếu bạn đôi khi quyết định bạn muốn stdio hoặc đầu ra stderr của quá trình bạn xem xét stackoverflow.com/questions/45953/...
jitter

1
Câu hỏi: Đó chỉ là loại bỏ đầu ra, phải không? PHP vẫn đợi quá trình kết thúc trước khi tiếp tục thực thi, hay nó kích hoạt và quên?
Alan Storm

5
Có loại bỏ. Có bắn và quên
jitter

3
Lưu ý: > /dev/null 2>&1 &như đã thấy trong các câu trả lời khác là dạng ngắn gọn > /dev/null 2>/dev/null &được đưa ra ở đây. Về cơ bản, điều này đang nói "chuyển hướng STDERR (2) đến cùng một nơi với STDOUT (& 1)".
rymo

3
Tôi thường nhận được PID của tập lệnh đang chạy bằng cách thêm echo $! >> /tmp/pid.txt ở cuối lệnh execute nhưng bằng cách chuyển hướng đầu ra & lỗi đến / dev / null, không còn tệp pid: có ai trong số bạn có thể nhận PID của tập lệnh do tệp thực thi khởi chạy trong khi không đợi đầu ra không?
hugsbrugs

28

Thao tác này sẽ thực hiện một lệnh và ngắt kết nối khỏi quá trình đang chạy. Tất nhiên, nó có thể là bất kỳ lệnh nào bạn muốn. Nhưng để kiểm tra, bạn có thể tạo tệp php bằng lệnh sleep (20).

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

nó tốt hơn cái này hay shell_exec?
realtebo

xin chào, tôi có thể chạy hàm này bằng shell_exec này không ("nohup / usr / bin / php -f example.com/notifications/sendnotifications_async > / dev / null 2> & 1 &");
Waseem Bashir

Tại sao cả hai nohup&?
bugmenot123

11

Bạn cũng có thể trả lại đầu ra cho máy khách ngay lập tức và tiếp tục xử lý mã PHP của bạn sau đó.

Đây là phương pháp tôi đang sử dụng cho các cuộc gọi Ajax đã chờ đợi lâu mà sẽ không có bất kỳ ảnh hưởng nào đến phía máy khách:

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.

Bạn có thể tìm thấy lời giải thích chi tiết tại đây: http://oytun.co/response-now-process-later


1
Ops ... Tôi đang đánh thức một câu hỏi về zombie ở đây, tôi không nhận ra. Nhưng chút thông tin này có thể có lợi cho những người khác.
Oytun

3
Này có để làm với shell_exec
bugmenot123

8

Trên Windows 2003, để gọi một tập lệnh khác mà không cần chờ đợi, tôi đã sử dụng điều này:

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

Điều này chỉ hoạt động SAU KHI cấp quyền thay đổi cmd.exe- thêm Đọc và Thực thi cho IUSR_YOURMACHINE(Tôi cũng đặt ghi thành Từ chối).


7

Chắc chắn, windowsbạn có thể sử dụng:

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

Ghi chú:

Nếu bạn gặp COMlỗi, hãy thêm tiện ích mở rộng vào của bạn php.inivà khởi động lại apache:

[COM_DOT_NET]
extension=php_com_dotnet.dll

Tôi không biết nhưng nó đã làm việc cho tôi. Xin bất cứ ai giải thích wscript.shell là gì và nó làm gì.
GeekWithGlasses 25/08/17

bạn có thể vui lòng giải thích tại sao dòng này không đưa ra bất kỳ đầu ra nào không? `$ oExec = $ WshShell-> Run ('C: \ Users \ Shreyash \ Desktop \ phantomjs-2.1.1-windows \ bin \ phantomjs.exe -f C: \ xampp \ htdocs \ composer \ test_0.js', 0 , false); `
GeekWithGlasses

Bạn có thể gặp lỗi trên test_0.js, hãy kiểm tra nhật ký ảo.
CONvid 19

6

Sử dụng popenlệnh của PHP , ví dụ:

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

Điều này sẽ tạo ra một tiến trình con và tập lệnh sẽ thực thi ở chế độ nền mà không cần đợi kết xuất.


4
Nó đợi quá trình con kết thúc. Ít nhất trên Win
Max Chernopolsky

Nền ở đây đạt được với sự trợ giúp của lệnh "start" của Windows có tiền tố exe mà bạn muốn chạy, nó sẽ không hoạt động nếu bạn bỏ qua nó và tôi sẽ không mong đợi nó hoạt động trên một hệ điều hành khác ... nhưng nó CÓ làm việc cho tôi, cảm ơn! :-)
Antony

1

Nếu nó nằm ngoài một trang web, tôi khuyên bạn nên tạo ra một tín hiệu nào đó (có thể là thả một tệp vào một thư mục) và nhờ một công việc cron thực hiện công việc cần phải hoàn thành. Nếu không, chúng ta có khả năng xâm nhập vào lãnh thổ của việc sử dụng pcntl_fork()exec()từ bên trong một quy trình Apache, và đó chỉ là trò xấu.


1
bạn nói đó là một mojo tồi. bạn có thể vui lòng giải thích?
Mayank

1

Điều đó sẽ hoạt động nhưng bạn sẽ phải cẩn thận để không làm quá tải máy chủ của mình vì nó sẽ tạo ra một quy trình mới mỗi khi bạn gọi hàm này sẽ chạy trong nền. Nếu chỉ có một cuộc gọi đồng thời tại cùng một thời điểm thì giải pháp này sẽ thực hiện công việc.

Nếu không thì tôi khuyên bạn nên chạy một hàng đợi tin nhắn như sqs beantalkd / gearman / amazon chẳng hạn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.