غير متزامن قذيفة exec في PHP
-
03-07-2019 - |
سؤال
لقد حصلت على السيناريو PHP الذي يحتاج إلى الاحتجاج شيل ولكن لا تهتم الإخراج.قذيفة النصي عددا من الصابون المكالمات بطيئة كاملة ، لذلك أنا لا أريد أن تبطئ PHP طلب في حين أنه ينتظر الرد.في الواقع, PHP الطلب يجب أن تكون قادرة على الخروج من دون إنهاء عملية قذيفة.
لقد بحثت في مختلف exec()
, shell_exec()
, pcntl_fork()
, ، وما إلى ذلك.وظائف, ولكن أيا منها لا يبدو أنها تقدم بالضبط ما أريد.(أو إذا فعلوا ذلك ، ليس من الواضح لي كيف.) أي اقتراحات ؟
المحلول
إذا كان "لا يهتمون الانتاج"، لا يمكن أن يسمى إكسيك إلى البرنامج النصي مع &
إلى خلفية هذه العملية؟
تعديل - يمكنك دمج ما علق @ AdamTheHut لهذا المنصب، ويمكنك إضافة هذه إلى دعوة إلى exec
:
" > /dev/null 2>/dev/null &"
وهذا سيتم توجيه كل من stdio
(>
أولا) وstderr
(2>
) ل/dev/null
وتعمل في الخلفية.
وهناك طرق أخرى للقيام بنفس الشيء، ولكن هذا هو أبسط لقراءة.
وبديل إلى ما سبق المزدوج إعادة توجيه:
" &> /dev/null &"
نصائح أخرى
اعتدت في لهذا, كما بدأت فعلا مستقلة العملية.
<?php
`echo "the command"|at now`;
?>
لجميع مستخدمي ويندوز: لقد وجدت وسيلة جيدة لتشغيل برنامج نصي PHP غير متزامن (في الواقع يعمل مع كل شيء تقريبا)
.وأنها تقوم على popen () وpclose () أوامر. ويعمل بشكل جيد على حد سواء على ويندوز ويونكس.
function execInBackground($cmd) {
if (substr(php_uname(), 0, 7) == "Windows"){
pclose(popen("start /B ". $cmd, "r"));
}
else {
exec($cmd . " > /dev/null &");
}
}
ورمز الأصلي من: http://php.net/manual/en/function.exec.php # 86329
في لينكس يمكنك القيام بما يلي:
$cmd = 'nohup nice -n 10 php -f php/file.php > log/file.log & printf "%u" $!';
$pid = shell_exec($cmd);
وهذا سيتم تنفيذ الأمر في الأمر برومبتي ثم يعود فقط PID، والتي يمكن أن تحقق لل> 0 للتأكد من أنه يعمل.
وهذا السؤال هو مماثل: هل PHP دينا خيوط
فب-تنفيذ واحد في خلفية عملية لديه بعض الاقتراحات الجيدة . أعتقد الألغام هو جيد جدا، ولكن أنا منحاز:)
في لينكس، يمكنك البدء في عملية في موضوع مستقل جديد بإلحاق العطف في نهاية الأمر
mycommand -someparam somevalue &
في Windows، يمكنك استخدام "بدء" القيادة DOS
start mycommand -someparam somevalue
الطريق الصحيح(!) للقيام بذلك
- شوكة()
- setsid()
- execve()
شوكة من شوك ، setsid قل العملية الحالية لتصبح على درجة الماجستير واحد (أي الأم) ، execve أخبر عملية الاستدعاء إلى محل يسمى واحد.حتى أن الأم يمكن أن تترك دون التأثير على الطفل.
$pid=pcntl_fork();
if($pid==0)
{
posix_setsid();
pcntl_exec($cmd,$args,$_ENV);
// child becomes the standalone detached process
}
// parent's stuff
exit();
وأنا استخدم هذا ...
/**
* Asynchronously execute/include a PHP file. Does not record the output of the file anywhere.
* Relies on the PHP_PATH config constant.
*
* @param string $filename file to execute
* @param string $options (optional) arguments to pass to file via the command line
*/
function asyncInclude($filename, $options = '') {
exec(PHP_PATH . " -f {$filename} {$options} >> /dev/null &");
}
و(حيث PHP_PATH
هو CONST محددة مثل define('PHP_PATH', '/opt/bin/php5')
أو ما شابه ذلك)
ويمر في الحجج عبر سطر الأوامر. لقراءتها في PHP، انظر ARGV .
والطريقة الوحيدة التي وجدت أن عملت حقا بالنسبة لي هو:
shell_exec('./myscript.php | at now & disown')
وكما أنني وجدت symfony لعملية مكون مفيدة لذلك.
use Symfony\Component\Process\Process;
$process = new Process('ls -lsa');
// ... run process in background
$process->start();
// ... do other things
// ... if you need to wait
$process->wait();
// ... do things after the process has finished
وانظر كيف يعمل في تقريرها جيثب الريبو .
استخدم يخرج أولا اسمه.
#!/bin/sh
mkfifo trigger
while true; do
read < trigger
long_running_task
done
وبعد ذلك كلما كنت تريد أن تبدأ مهمة طويلة قيد التشغيل، ببساطة كتابة سطر جديد (توصيل nonblocking إلى ملف الزناد.
وطالما الإدخال أصغر من PIPE_BUF
وانها عملية write()
واحدة، يمكنك كتابة الحجج في FIFO ويكون لهم كما تظهر $REPLY
في البرنامج النصي.
يمكنك أيضا تشغيل PHP النصي شيطان أو cronjob: #!/usr/bin/php -q
ودون انتظار الاستخدام، يمكنك استخدام proc_open()
مثل هذا :
$descriptorspec = array(
0 => array("pipe", "r"),
1 => array("pipe", "w"),
2 => array("pipe", "w") //here curaengine log all the info into stderror
);
$command = 'ping stackoverflow.com';
$process = proc_open($command, $descriptorspec, $pipes);