سؤال

أحاول إنشاء برنامج نصي PHP، لقد انتهيت من البرنامج النصي ولكن الأمر يستغرق حوالي 10 دقائق لإنهاء العملية التي تم تصميمه للقيام بها.هذه ليست مشكلة، ولكن أفترض أنه يجب علي إبقاء الصفحة محملة طوال هذا الوقت وهو أمر مزعج.هل يمكنني الحصول عليه حتى أبدأ العملية ثم أعود بعد 10 دقائق وأشاهد ملف السجل الذي تم إنشاؤه؟

هل كانت مفيدة؟

المحلول

حسنا، يمكنك استخدام " ignore_user_abort ( صحيح) "

وهكذا ستستمر النصي للعمل (إبقاء العين على مدة النصي، وربما إضافة "<لأ href =" http://de2.php.net/manual/en/function.set-time-limit.php " يختلط = "noreferrer"> set_time_limit (0) ")

ولكن تحذيرا هنا: أنت لن تكون قادرة على وقف برنامج نصي مع هذين الخطين:

ignore_user_abort(true); 
set_time_limit(0);

وإلا يمكنك الوصول مباشرة إلى الخادم وقتل عملية هناك! (كانت هناك، وفعلت حلقة لا نهاية لها، تطلق على نفسها مرارا وتكرارا، أدلى الخادم التوصل إلى وقف الصراخ، وحصلت على صاح ...)

نصائح أخرى

ويبدو وكأنه يجب أن يكون طابور وبرنامج نصي خارجية لمعالجة قائمة الانتظار.

وعلى سبيل المثال، يجب النصي PHP الخاص بك وضع إدخال في جدول قاعدة بيانات والعودة على الفور. ثم، كرون تشغيل كل دقيقة يتحقق قائمة الانتظار والشوك عملية لكل وظيفة.

والميزة هنا هي أنك لا قفل على اباتشي الخيط لمدة 10 دقيقة.

وكان لي الكثير من القضايا مع هذا النوع من العملية تحت النوافذ. كان وضعي مختلف قليلا في أنني لم نهتم استجابة "السيناريو" - أردت البرنامج النصي لبدء والسماح طلبات صفحة أخرى للذهاب من خلال بينما كان مشغولا يعملون بعيدا

.

لسبب ما. كان لي مشاكل معها إما شنقا طلبات أو انتهاء المهلة أخرى بعد حوالي 60 ثانية (على حد سواء اباتشي و PHP وضعت مهلة بعد حوالي 20 دقيقة). وتبين أيضا أن الأوقات فايرفوكس بعد 5 دقائق (افتراضيا) على أي حال حتى بعد أن النقطة التي لا يمكن معرفة ما يجري من خلال متصفح دون تغيير الإعدادات في فايرفوكس.

وانتهى بي الأمر باستخدام عملية مفتوحة وطرق وثيقة عملية لفتح فب في وضع المبادرة القطرية مثل ذلك:

وpclose(popen("start php myscript.php", "r"));

وهذا من شأنه (باستخدام البداية) فتح عملية فب ثم قتل في عملية بدء مغادرة فب الترشح لفترة طويلة ولكن ذلك يحتاج - مرة أخرى كنت بحاجة لقتل عملية لإغلاقها يدويا. لم يكن بحاجة لتعيين أي الرافضة الوقت وكنت قد ترك الصفحة الحالية الذي يطلق عليه مواصلة وإخراج بعض مزيد من التفاصيل.

والمسألة الوحيدة مع ذلك هو أنه إذا كنت في حاجة الى ارسال النصي أي بيانات، وكنت إما أن تفعل ذلك عن طريق مصدر آخر أو تمريرها على طول "سطر الأوامر" كمعلمات. وهي ليست آمنة جدا.

وعملت بشكل جيد ما كنا بحاجة على الرغم من ويضمن النصي دائما يبدأ والسماح للتشغيل دون أي انقطاع.

وهذا قد يكون من المساعدة، أيضا: غير متزامن قذيفة إكسيك في PHP

وأعتقد أن القيادة shell_exec هو ما كنت أبحث عنه.

ومع ذلك، فمن تعطيل في الوضع الآمن.

ووPHP المادة اليدوية عنه هنا هو: http://php.net/shell_exec

وهناك مقال حول هذا الموضوع هنا: <لأ href = "http://nsaunders.wordpress.com/2007/01/12/running-a-background-process-in-php/" يختلط = "نوفولو noreferrer "> http://nsaunders.wordpress.com/2007/01/12/running-a-background-process-in-php/

وهناك خيار آخر والتي يمكنك استخدامها، تشغيل CLI النصي ... وسوف تعمل في الخلفية ويمكنك حتى تشغيله كما cronjob إذا كنت تريد.

ومنها مثلا

> #!/usr/bin/php -q

<?php

//process logs

?>

ويمكن أن يكون هذا الإعداد بمثابة cronjob وسيتم تنفيذ مع عدم وجود قيود الوقت .... هذه الأمثلة هي ليونيكس نظام تشغيل يستند على الرغم من.

وFYI لدي النصي فب تشغيل مع حلقة لا نهائية التي لا بعض تجهيز وتم تشغيل لمدة 3 أشهر دون توقف الماضي.

هل يمكن استخدام ignore_user_abort() - وبهذه الطريقة سوف يستمر البرنامج النصي لتشغيله حتى لو قمت بإغلاق المتصفح الخاص بك أو الذهاب إلى صفحة أخرى.

فكر في ذلك جيرمان

Gearman هو إطار عمل عام لزراعة العمل إلى آلات أو عمليات متعددة.يسمح للتطبيقات بإكمال المهام بالتوازي ، وتحميل معالجة التوازن ، واتصال وظائف بين اللغات.يمكن استخدام الإطار في مجموعة متنوعة من التطبيقات ، بدءًا من مواقع الويب عالية الوفاء إلى نقل أحداث النسخ المتماثل لقاعدة البيانات.

يوفر هذا التمديد فصولًا لكتابة عملاء وعمال الترس.- دليل PHP المصدر

الموقع الرسمي ل جيرمان

بالإضافة إلى إجابة باستياندوين يمكنك الجمع ignore_user_abort(true); مع طلب الضفيرة.

طلب إجهاض مزيف لتحديد مستوى منخفض CURLOPT_TIMEOUT_MS واستمر في المعالجة بعد إغلاق الاتصال:

function async_curl($background_process=''){

    //-------------get curl contents----------------

    $ch = curl_init($background_process);
    curl_setopt_array($ch, array(
        CURLOPT_HEADER => 0,
        CURLOPT_RETURNTRANSFER =>true,
        CURLOPT_NOSIGNAL => 1, //to timeout immediately if the value is < 1000 ms
        CURLOPT_TIMEOUT_MS => 50, //The maximum number of mseconds to allow cURL functions to execute
        CURLOPT_VERBOSE => 1,
        CURLOPT_HEADER => 1
    ));
    $out = curl_exec($ch);

    //-------------parse curl contents----------------

    //$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
    //$header = substr($out, 0, $header_size);
    //$body = substr($out, $header_size);

    curl_close($ch);

    return true;
}

async_curl('http://example.com/background_process_1.php');

ملحوظة:

إذا كنت تريد أن تهتم Curl في أقل من ثانية واحدة ، فيمكنك استخدام Curlopt_timeout_ms ، على الرغم من وجود خطأ/"ميزة" على "أنظمة تشبه Unix" التي تسبب Libcurl إلى المهلة على الفور إذا كانت القيمة أقل من 1000 مللي ثانية مع الخطأ " خطأ حليقة (28):تم الوصول إلى المهلة".التفسير لهذا السلوك هو:

[...]

الحل هو تعطيل الإشارات باستخدام CURLOPT_NOSIGNAL

الايجابيات

  • لا حاجة لتبديل الطرق (متوافق مع نظام التشغيل Windows وLinux)
  • لا حاجة لتنفيذ معالجة الاتصال عبر الرؤوس والمخزن المؤقت (مستقل عن المتصفح وإصدار PHP)

سلبيات

  • تحتاج إلى تمديد الضفيرة

موارد

زوك.

أنا متأكد من أن هذا سيعمل:

<?php 

pclose(popen('php /path/to/file/server.php &'));
echo "Server started. [OK]"; 

?>

"&" مهم.يخبر الصدفة بعدم الانتظار حتى تنتهي العملية.

يمكنك أيضًا استخدام هذا الرمز في ملف php الخاص بك (كما قال "bastiandoeen")

ignore_user_abort(true); 
set_time_limit(0);

في أمر إيقاف الخادم الخاص بك:

<?php

$output;
exec('ps aux | grep -ie /path/to/file/server.php | awk \'{print $2}\' | xargs kill -9 ', $output);
    echo "Server stopped. [OK]";

?>

ومجرد دعوة StartBuffer () قبل أي الإخراج، وEndBuffer () عندما تريد العميل لإغلاق الاتصال. سيتم تنفيذ التعليمات البرمجية بعد استدعاء EndBuffer () على الخادم دون اتصال العميل.

    private function StartBuffer(){
        @ini_set('zlib.output_compression',0);
        @ini_set('implicit_flush',1);
        @ob_end_clean();
        @set_time_limit(0);
        @ob_implicit_flush(1);
        @ob_start();
    }

    private function EndBuffer(){
        $size = ob_get_length();
        header("Content-Length: $size");
        header('Connection: close');
        ob_flush();ob_implicit_flush(1);
    }

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top