2012-05-14 43 views
17

Có cách nào để hết thời gian một chức năng không? Tôi có 10 phút để thực hiện một công việc. Công việc bao gồm một vòng lặp for, đây là một ví dụ:Hết giờ một chức năng trong PHP

<?php 
foreach($arr as $key => $value){ 
    some_function($key, $value); //This function does SSH and SFTP stuff 
} 
?> 

$ arr có 15 yếu tố và some_function() đôi khi có thể mất hơn 1 phút. Trong thực tế một khi nó đã bị treo cổ trong 5 phút.

Có cách nào tôi có thể hết thời gian chờ cuộc gọi chức năng và tiếp tục với phần tử tiếp theo trong $ arr?

Cảm ơn bạn !!

+0

một số câu hỏi: là những gì nó, mà giới hạn bạn đến 10 phút? không quan trọng, nếu các công việc ssh/sftp được thực hiện hay không? và bạn có thể giải quyết hạn chế này bằng cách sử dụng một số loại hàng đợi không? – aurora

+0

Đây là tập lệnh crontab chạy 10 phút một lần. Nó đang kiểm tra trạng thái máy chủ và cập nhật cơ sở dữ liệu. Nếu tôi không nhận được phản hồi sau 1 phút, tôi sẽ thiết lập máy chủ chậm cho máy chủ đó ... – Mo3z

Trả lời

13

Điều đó tùy thuộc vào việc triển khai của bạn. 99% các chức năng trong PHP đang chặn. Có nghĩa là quá trình xử lý sẽ không tiếp tục cho đến khi chức năng hiện tại hoàn thành. Tuy nhiên, nếu hàm chứa một vòng lặp, bạn có thể thêm vào mã của riêng bạn để ngắt vòng lặp sau khi một điều kiện nhất định đã được đáp ứng.

Something như thế này:

foreach ($array as $value) { 
    perform_task($value); 
} 

function perform_task($value) { 
    $start_time = time(); 

    while(true) { 
    if ((time() - $start_time) > 300) { 
     return false; // timeout, function took longer than 300 seconds 
    } 
    // Other processing 
    } 
} 

Một ví dụ khác nơi làm gián đoạn quá trình xử lý là không thể:

foreach ($array as $value) { 
    perform_task($value); 
} 

function perform_task($value) { 
    // preg_replace is a blocking function 
    // There's no way to break out of it after a certain amount of time. 
    return preg_replace('/pattern/', 'replace', $value); 
} 
+0

Cảm ơn Mike nhưng tôi là some_function hoặc perform_task là một chức năng cốt lõi và tôi đang cố gắng tránh sửa đổi phương pháp cốt lõi. – Mo3z

+1

Đi tuyến đường: Tạo một kịch bản lệnh mới example.php và gọi tập lệnh đó trong some_function và xác định set_time_limit ... logic của some_function sẽ được thực thi trong example.php .. – Mo3z

+0

cùng một vấn đề ở đây, cùng một kỹ thuật. –

8

PHP là đơn ren ... bạn phải sử dụng khả năng của hệ điều hành của bạn đến ngã ba quá trình khác .

Cách duy nhất tôi biết cách thực hiện điều này là với lệnh exec để ngắt kết nối với một quy trình đầy đủ khác. Đặt những thứ bạn muốn theo thời gian trong một tập lệnh riêng biệt, gọi exec trên kịch bản, sau đó ngay lập tức ngủ trong 10 phút. Nếu lúc 10 phút thì tiến trình vẫn đang chạy giết nó. (bạn nên có PID của nó bằng cách làm cho lệnh chạy mã php mới trong nền, nhận nó thông qua dòng lệnh và trả lại nó từ lệnh exec).

+0

Không phải tất cả PHP không phải là luồng –

4

Trước khi bắt đầu vòng lặp, hãy đặt biến số ghi nhớ time(). Vào cuối mỗi lần lặp lại, kiểm tra xem hiện tại time() có lớn hơn 60 giây hay không. Nếu có, break. Ví dụ:

<?php 
$startTime=time(); 
foreach($arr as $key => $value){ 
    some_function($key, $value); //This function does SSH and SFTP stuff 
    if (time()-$startTime>60) break; //change 60 to the max time, in seconds. 
} 
?> 
+0

Cảm ơn David vì câu trả lời của bạn. Tôi không cần phải phá vỡ vòng lặp, tôi cần phải phá vỡ some_function nếu phải mất hơn một phút. – Mo3z

1

Hãy xem set_time_limit. Bây giờ chức năng chính nó không thực sự muốn bạn muốn vì nó chỉ đưa vào xem xét thời gian thực hiện, có nghĩa là 5 giây trong cuộc sống thực có thể vẫn chỉ là 0.2 giây thực hiện. Nhưng lý do để xem liên kết là cho các ý kiến. Có một vài giải pháp mà người dùng đã đăng.

5

Bạn có thể thử triển khai điều này bằng cách sử dụng 'curl'. Curl là - từ PHP - chủ yếu được sử dụng để làm công cụ HTTP/FTP, nhưng nó hỗ trợ nhiều giao thức hơn, bao gồm ssh/sftp. Tôi đã không bao giờ làm một cái gì đó ssh/sftp liên quan bằng cách sử dụng curl, vì vậy tôi không thể đưa ra bất kỳ lời khuyên bổ sung, nhưng bạn sẽ có thể tìm thêm thông tin ở đây trên stackoverflow hoặc ở một nơi khác.

Có tùy chọn "CURLOPT_TIMEOUT" bạn có thể sử dụng để định cấu hình thời gian chờ cho yêu cầu của mình (cũng có tùy chọn "CURLOPT_CONNECTTIMEOUT"). Bạn thậm chí có thể chỉ định thời gian chờ ở độ phân giải giây (CURLOPT_TIMEOUT_MS/CURLOPT_CONNECTTIMEOUT_MS).

Dù sao: đối với cronjob, tôi khuyên bạn nên sử dụng "tệp khóa" bổ sung mà tập lệnh của bạn viết khi bắt đầu và xóa, khi nó chạy xong. Bạn có thể kiểm tra tệp khóa này trong tập lệnh của mình để nếu cron kích hoạt tập lệnh của bạn trước khi kết thúc lần chạy, bạn chỉ có thể thoát khỏi tập lệnh mà không cần thực hiện thêm thao tác nào. Điều đó đảm bảo rằng, tập lệnh của bạn sẽ không được thực hiện nhiều lần song song.

Bạn có thể tìm thêm về các tùy chọn CURL và curl chính nó trong tài liệu PHP, quá:

Bạn phải chắc chắn, rằng libcurl cài đặt của bạn và/hoặc curl cho php hỗ trợ SSH/SFTP, mặc dù:

, vv

Hy vọng rằng sẽ giúp ...

7

gì bạn muốn là để sử dụng chức năng pcntl_alarm, mà sẽ kích hoạt một tín hiệu SIGALRM về thời gian chờ. Ví dụ:

// 10 minutes 
pcntl_alarm(600); 
pcntl_signal('SIGALRM', function() { print("I am done!\n"); exit(0); }); 

Xin vui lòng xem tại đây hướng dẫn PHP để biết thêm về vấn đề này: http://php.net/manual/en/function.pcntl-alarm.php

+2

Dưới đây là triển khai hoàn chỉnh: https://gist.github.com/avalanche123/3085581 –