ورود

توجه ! این یک نسخه آرشیو شده میباشد و در این حالت شما عکسی را مشاهده نمیکنید برای مشاهده کامل متن و عکسها بر روی لینک مقابل کلیک کنید : اجرا دستور تکراری



pejman_view
December 25th, 2013, 20:49
من برنامه نویس یک شرکت بازیهای آنلاین هستم
به یک مشکل برخوردم که به شرح زیر میباشد و حل نمیشود لطفا از دوستان میخوام سریع راهنمایی کنند
مشکل فنی بر خوردم دیتابیس بازی همانطور که می دانید بایستی هر 1 ثانیه آپدیت بشه برای اینکه جنگ ها انجام بشود و منابع آپدیت شود و هزاران کار دیگر

و همانطور که می دانید کرون هم کمتر از یک دقیقه نداره بنابراین ما حلقه هایی نیاز داریم که sleep بخورن و کار کرون جاب یک ثانیه ای بخورد. حالا مشکل من از اینجا شروع شده که بعضی از کاربرا می گن جنگ ها بعضی اوقات دو بار اتفاق می افتد و این مشکل تنها از یکبار بروز می کند که در کسری از ثانیه دو تا کلاس با هم فراخوانی شود. ما برای اینکه از این مشکل جلوگیری کنیم اومدیم تو دیتابیس دو یک فیلد تعریف کردیم که اگر 0 بود کرون جاب های دیگر بتوانند کار کنند و اگر یک بود نتوانند و بصورت شرط اول حلقه گذاشتیم. حالا با این توجه باز هم اتفاق می افتد می خواستم ببینم راه بهتری برای جلوگیری از چندبار اجرا شدن یک دستور هست یا خیر؟

hejazee
December 27th, 2013, 23:33
راه حلش اینه که شما یک کد بنویسید حالا یا PHP یا هر زبان دیگه و تنظیم کنید که این کد به صورت daemon در لینوکس اجرا شود. یعنی دیگر از کرون استفاده نکنید.
به عنوان نمونه کد زیر را بررسی کنید (به زبان شل اسکریپت)
فایلی به نام task.sh ایجاد کنید با محتویات زیر:

while :
do
sleep 1
some_command || break
done



البته باید some_command با دستوری که قرار است اجرا شود جایگزین شود.
سپس فایل را ذخیره کنید و به آن مجوز اجرا دهید:


chmod 750 task.sh

سپس آن را به صورت دیمون اجرا کنید:


nohup task.sh >log.txt &

و نتیجه این که دستور some_command هر ثانیه یک بار اجرا خواهد شد.
اما اگر می خواهید که زمانی که دستور اجرا می شود ابتدا چک کند که آیا همچنان در حال اجرا است یا خیر، و اگر در حال اجرا بود، دوباره اجرا نشود، باید از lock ها یا semaphore استفاده کنید که حتما با آن آشنایی دارید.
اگر کدی که نوشته اید کار نمی کند، کدتان را اینجا ارسال کنید تا بررسی کنیم.

موفق باشید.

adenaweb
December 27th, 2013, 23:37
هزینه طراحی یک اسکریپت با ایده خودمون چنده برای بازی آنلاین؟

hejazee
December 27th, 2013, 23:46
چند نکته راجع به کدی که نوشتم:
1 - برنامه ی فوق، بین هر بار اجرای دستور some_command یک ثانیه فاصله می اندازد. به این معنی که اگر اجرای دستور، خودش 0.25 ثانیه زمان ببرد، دستور، هر 1.25 ثانیه یک بار اجرا خواهد شد.
2 - خروجی دستور باید TRUE باشد.

نکته:
برای این که دستور حتما در هر ثانیه یک بار اجرا شود، می توانید کاری کنید که دستور، زمان نبرد و بلافاصله پس از اجرا، فورا return شود و در بک گراند ادامه پیدا کند
البته دقت کنید که اگر چنین کاری کنید، آن وقت اگر اجرای دستور بیش از 1 ثانیه طول بکشد، چند تا دستور همزمان اجرا خواهد شد.

اما راه حل:
برای این که دستور به محض اجرا، فورا return شود و در بک گراند ادامه پیدا کند، دستور some_command را به شکل زیر بنویسید:


nohup some_command >/dev/null &

و برای این که دو دستور همزمان اجرا نشوند، باید از lock استفاده کنید و برای این که اجرای یک دستور را به یک ثانیه محدود کنید، می توانید یک دیمون دیگر بنویسید که دستوراتی که بیش از یک ثانیه در حال اجرا هستند را kill کند و ... یا خیلی کارهای دیگر هم میشود کرد.

تذکر:
برای خاتمه دادن به اجرای دستوری که توسط nohup در بک گراند در حال اجرا است، ابتدا pid آن را به شکل زیر پیدا می کنید


ps aux |grep test.sh |awk '{print $2}'

سپس آن را با دستور kill -9 متوقف می کنید. دستور کلی به شکل زیر خواهد بود:


kill -9 `ps aux |grep test.sh |awk '{print $2}'`

البته ممکن است نیاز به کمی تغییر داشته باشد. اما ایده ی ملی همین است.

hejazee
December 27th, 2013, 23:51
ترفند برای پیدا کردن pid یک پروسه (رفع مشکلی که در قبلی بود)


ps aux |grep "[t]est.sh" |awk '{print $2}'

حرف اول نام دستور را داخل [] محصور کردم و کل نام را در "" قرار دادم.