// run for each job
foreach ($jobs as $job) {
$pid = pcntl_fork();
if (! $pid) {
$descriptorspec = array(
0 => array("pipe", "r"),
1 => array("pipe", "w"),
2 => array("pipe", "w")
);
$process = proc_open($job['cmd'], $descriptorspec, $pipes);
if (is_resource($process)) {
echo $procout = stream_get_contents($pipes[1]);
echo $procerror = stream_get_contents($pipes[2]);
fclose($pipes[1]);
fclose($pipes[2]);
$return_value = proc_close($process);
}
break;
}
}
سلام.
این کد بالا رو نگاه کنید، این کد قسمت اجرا شدن اسکریپت های در صف انتظاراجرای یک کلاس cronjob هستش.
که چند تا سوال داشتم در موردش:
1- کلا این کدها روندش چیه؟ خودم در واقع کلیتش رو میدونم که به ترتیب همه اسکریپت های در صف انتظار رو پشت سر هم اجرا میکنه، ولی چون به اون تابع های proc_open و ... تسلط ندارم نمیدونم این کد داره چه کار میکنه از اول تا آخرش!
توابع استفاده شده توش کارشون چیه؟
2-این کدها توی ویندوز هم کار میکنن یا نه؟
3- این کدها توی هاستینگ های معمولی هم اجرا میشن؟ چون فکر میکنم اون تابع proc_open از توابع خطرناک هستش که توی هاستینگ ها میبندنش.
4- من اگر بودم هر کدوم از اسکریپت هایی که میخواستم اجرا بشن رو require_once میکردم، این روش من بهتره یا این کدها؟
5- واسه اینکه حدس میزنم ممکنه این روش توی هاستینگ های اشتراکی مشکل داشته باشه، پیشنهاد میکنید اول یک چک بکنم که اگر تابع proc_open موجود بود همین روش اجرا بشه اگر نبود از روش require_once?
نمیدونم چرا اینهمه دردسر دارین میکشین واسه انجام کاری که توی خود هاستها (حتی اشتراکی) راههای بهتری برای انجامش هست! قبل از اینکه از این سناریوهای پر دردسر استفاده کنید که اکثراً هم توی هاست اشتراکی جواب نمیدن و احتمالاً مشکلات Portability هم بین پلتفرمهای مختلف (ویندوز و لینوکس و...) دارن، کاری که میخواین انجام بدین رو به فارسی و بیان ساده بگین تا دوستان نظرشون رو بگن. شاید راههای ساده تری هم وجود داشته باشه.
1- دستور proc_open یه پردازش جدید ایجاد میکنه. درواقع مثل اینکه یه ترمینال جدید باز کنید و دستور جدیدی رو اجرا کنید.
2- تست نکردم ولی اجرا شدنش بستگی به دستوراتی داره که توی اندیس cmd متغیر job$ قرار داره.
3- 99.99٪ هاستهای اشتراکی proc_open رو میبندن.
4- امتیاز این روش نسبت به require اینه که هرکدوم، Processهای جداگانه دارن که درصورت نیاز میشه بصورت جداگانه اونها رو ببندین و ازطرفی میشه همزمان پردازشها رو اجرا کرد ولی توی require کردن، ترتیبی انجام میشه و همه دستورات با یک پردازش واحد انجام میشن.
5- راهی که من توصیه میکنم اینه که برحسب سیستمی که قراره روی اون کار کنید عمل کنید. اگه سرور مجازی یا اختصاصی دارین میتونید از proc_open استفاده کنید و یا دستورات رو توی دیتابیس بگذارین و هربار چند تا رو انتخاب و اجرا کنید. استفاده از shell_exec هم میتونه گزینه مناسبی باشه.
(14-04-1394، 10:44 ب.ظ)ADMIN نوشته: [ -> ]نمیدونم چرا اینهمه دردسر دارین میکشین واسه انجام کاری که توی خود هاستها (حتی اشتراکی) راههای بهتری برای انجامش هست! قبل از اینکه از این سناریوهای پر دردسر استفاده کنید که اکثراً هم توی هاست اشتراکی جواب نمیدن و احتمالاً مشکلات Portability هم بین پلتفرمهای مختلف (ویندوز و لینوکس و...) دارن، کاری که میخواین انجام بدین رو به فارسی و بیان ساده بگین تا دوستان نظرشون رو بگن. شاید راههای ساده تری هم وجود داشته باشه.
من به این دلیل این روش رو دارم انجام میدم چون نمیتونم 20- 30 تا url اسکریپت رو برم از طریق کنترل پنل هاستینگ واسه کرون جاب add کنم و حتی ممکنه هر روز هم به تعداد این کرون جاب ها اضافه بشه، درنتیجه میام یک کلاس مدیریت cronjob مینویسم که همه اسکریپت هایی که باید اجرا بشن بعلاوه زمان و interval جداگانه هرکدوم رو توی دیتابیس ذخیره میکنم و فقط همین یک کلاس رو از طریق کنترل پنل هاستینگ جزو cron job ها add میکنمش، و همچنین با این روش قابلیت های دیگه ای به این کلاس میتونم اضاضه کنم مثلا از طریق بخش admin اسکریپت، به راحتی یک cron رو disable یا enable کنم یا یک مورد جدید اضافه کنم یا بازه های زمانی interval اجرای اسکریپت ها رو تغییر بدم به راحتی و ....
(14-04-1394، 10:49 ب.ظ)ADMIN نوشته: [ -> ]4- امتیاز این روش نسبت به require اینه که هرکدوم، Processهای جداگانه دارن که درصورت نیاز میشه بصورت جداگانه اونها رو ببندین و ازطرفی میشه همزمان پردازشها رو اجرا کرد ولی توی require کردن، ترتیبی انجام میشه و همه دستورات با یک پردازش واحد انجام میشن.
1- آره سرور اختصاصی دارم، منظورتون اینه که با روش proc_open وقتی تمام اسکریپت های توی حلقه foreach میخوان اجرا بشن، در کسری از ثانیه و در واقع در همون مدت اتمام حلقه foreach (کدهای بالا) تمام اسکریپت ها به صورت همزمان شروع به کار میکنن در process های مختلف؟ ولی روش require_once اگر اتمام اسکریپت اول حلقه Foreach دو دقیقه طول بکشه، اسکریپت بعدی با دو دقیقه تاخیر تازه شروع میشه، درسته؟
2- این روش proc_open از لحاظ مصرف cpu فکر میکنم خیلی بهینه تر باشه، درسته؟ چون در process های مختلف اجرا میشن و وقتی سرور چندهسته ای باشه خیلی روش بهتری هستش نسبت به require کردن.
پ.ن: دوستان دیگه هم توی بحث ها شرکت کنن لطفا :| @rezakho و سایر دوستان ...
خب اگه یه زمانی نیاز شد یه کران جاب با پردازش طولانی اجرا کنید تکلیف چیست؟ میدونید چه اتفاقی میفته؟
پس اگه نمیخواید از کران جابه خوده پنل استفاده کنید و کنترل سرورتون هم دسته خودتونه، درباره پردازش های پنهان (background process) تحقیق کنید و عملیات ها رو به این صورت پردازش کنید تا وقفه ای در اجرای سایته شما ایجاد نشه در غیر این صورت یه راه حل دیگ هم هست که به نظره خودم زیاد استاندارد نیست.
(15-04-1394، 01:44 ق.ظ)n0o0b_sina نوشته: [ -> ]خب اگه یه زمانی نیاز شد یه کران جاب با پردازش طولانی اجرا کنید تکلیف چیست؟ میدونید چه اتفاقی میفته؟
همین سوالی که توی پست قبلی از آقای شهرکی پرسیدم که هنوز جواب ندادن حول همین موضوع بود که اگر روش proc_open همه اسکریپت ها رو همزمان شروع کنه میشه گفت پردازش هام خیلی طولانی نمیشه و مشکلی نیست دیگه، ولی اگر قرار باشه require_once بشه و هر کدوم توی صف اون یکی بمونه زیاد جالب نیست، الیته مشکل رو با دادن یک max_execution_time منطقی حل میکنم که همش به مشکل نخوره، جاهایی که زمان انجام کار واسه مهمه شاید بعدا تصمیم گرفتم از پردازش asynchronous استفاده کنم تا اجرای یک بخش کار معطل بخش دیگه نباشه...
(15-04-1394، 01:44 ق.ظ)n0o0b_sina نوشته: [ -> ]پس اگه نمیخواید از کران جابه خوده پنل استفاده کنید و کنترل سرورتون هم دسته خودتونه، درباره پردازش های پنهان (background process) تحقیق کنید و عملیات ها رو به این صورت پردازش کنید تا وقفه ای در اجرای سایته شما ایجاد نشه در غیر این صورت یه راه حل دیگ هم هست که به نظره خودم زیاد استاندارد نیست.
منظورتون از پردازش پنهان دقیقا چیه؟ همون پردازش asynchronous یا موازی منظورتونه؟ چون اینی که شما گفتید رو تحقیق کردم مثل اینکه کاربردش اینه که در ظاهر اسکریپت شما انگار کارش تموم شده ولی در پشت پرده هنوز ادامه داره! یعنی مثلا شما چند ثانیه sleep میدی یک اسکریپت رو و وقتی اجرا میکنی سریع تموم میشه اسکریپت ولی پشت پرده هنوز داره اون ثانیه های sleep رو طی میکنه! خب این قضیه واسه من مهم نیست چون وقتی با cron کار میخوام بکنم همش پرده اس و نیازی نیست یکجور دیگه ای اسکریپت اجرا بشه چون من اصلا بهش کار ندارم خود cron انجامش میده.
اون روش دیگه ای که میگید چی بود؟ :دی
اگه با روشهایی مثل shell_exec و proc_open کار کنید و پردازشها در پس زمینه اجرا بشن، به شما شماره process_id اونها داده میشه که بعداً میتونید با کمک دستور kill و پارامترهای cont- و stop- و 9- پردازشهای موردنظرتون رو مدیریت کنید. مثلاً توی دیتابیس شماره پردازش و دستورش رو بگذارین و هروقت خواستین متوقف کنید، ادامه بدین یا کلاً ببندینش.
(15-04-1394، 02:40 ق.ظ)php نوشته: [ -> ]همین سوالی که توی پست قبلی از آقای شهرکی پرسیدم که هنوز جواب ندادن حول همین موضوع بود که اگر روش proc_open همه اسکریپت ها رو همزمان شروع کنه میشه گفت پردازش هام خیلی طولانی نمیشه و مشکلی نیست دیگه، ولی اگر قرار باشه require_once بشه و هر کدوم توی صف اون یکی بمونه زیاد جالب نیست، الیته مشکل رو با دادن یک max_execution_time منطقی حل میکنم که همش به مشکل نخوره، جاهایی که زمان انجام کار واسه مهمه شاید بعدا تصمیم گرفتم از پردازش asynchronous استفاده کنم تا اجرای یک بخش کار معطل بخش دیگه نباشه...
منظورتون از پردازش پنهان دقیقا چیه؟ همون پردازش asynchronous یا موازی منظورتونه؟ چون اینی که شما گفتید رو تحقیق کردم مثل اینکه کاربردش اینه که در ظاهر اسکریپت شما انگار کارش تموم شده ولی در پشت پرده هنوز ادامه داره! یعنی مثلا شما چند ثانیه sleep میدی یک اسکریپت رو و وقتی اجرا میکنی سریع تموم میشه اسکریپت ولی پشت پرده هنوز داره اون ثانیه های sleep رو طی میکنه! خب این قضیه واسه من مهم نیست چون وقتی با cron کار میخوام بکنم همش پرده اس و نیازی نیست یکجور دیگه ای اسکریپت اجرا بشه چون من اصلا بهش کار ندارم خود cron انجامش میده.
اون روش دیگه ای که میگید چی بود؟ :دی
آره دقیقا :دی اون یکی دیگ زیاد مهم نیست من فکر کردم نمیخواید از کران استفاده کنید و مثله وردپرس هر بار که کار بر اومد وبسایت میخواید چک کنید.
من چندهفته اس درگیر همین کد لعنتی پست اولم! هرکاریش میکنم توی سرور(اختصاصی) کار نمیکنه!! مثلا ماژول pcntl رو فعال کردم ولی بازم کار نمیکنه! نمیدونم مشکلش چیه!
میخوام یک کد دیگه اضافه کنم به کد بالا که اگر pcntl یا proc_oepn یا stream_get_contents فعال نبودن(function_exist ) یا که توی throw exception اینا بذارم که اگر این روش اول جواب نداد از یک روش دیگه برم! سوالم اینه که چجوری این کار رو دقیقا انجام بدم(که اگر موجود نبودن)
و سوال دوم اینکه راه جایگزین کد بالا چیه؟! (اجرای همزمان چندین فابل php ) اینم اضافه کنم که shell_exec و shell در سرور فعاله.