ر این مقاله، چگونگی رفع خطای ۵۰۳ در وب سرور را آموزش میدهیم. کدهایی که با عدد ۵ شروع میشوند، بیانگر ایرادی از جانب سرور هستند. این کد هم به ما میگوید که سرور به دلایلی، امکان پاسخگویی به درخواست شما را ندارد.
اگر دوست دارید با انواع این کدها بیشتر آشنا شوید، مقاله خطاهای HTTP را بخوانید.
رایجترین دلیلی که باعث بروز خطای 503 میشود، Crash شدن PHP است. حالا جدا از دلایل منجر به این اتفاق، بیایید سراغ راهحل برویم.
قبل از هرکاری،طبق اعلام سایت رسمی مستندات لایت اسپید جهت تست، باید آن را (حداقل بهصورت موقت)، به آپاچی تغییر دهید. دو حالت پیش میآید:
خب اول یک راهنمای سریع برای عیبیابی خواهیم داشت:
در نهایت، شاید نیاز به پشتیبانی حرفهای داشته باشید؛ اما قبل از آن، بد نیست اقدامات زیر را انجام دهید. شاید خودتان توانستید بهراحتی مشکل را برطرف کنید!
اینها اقدامات دمدستیای بودند که ممکن است بتوانند مشکلتان را برطرف کنند؛ اما اگر موفق نشدید، اصلاً جای نگرانی نیست. با ما همراه باشید و سراغ Log Files بروید.
لاگ فایلهای زیادی هستند که برای رفع مشکل کردن ارور 503 کمکتان میکنند. در ادامه 4 مورد از این Log Files را با هم بررسی میکنیم. محل قرارگیری آنها را یاد میگیریم و میفهمیم که چه اطلاعاتی را در اختیارمان میگذارند.
اگر قصد عیبیابی از طریق این فایلها را دارید، بهتر است با همین ترتیبی که ما آنها را معرفی میکنیم پیش بروید.
فایل stderr.log، حاوی ارورهای رایجی است که هنگام اجرای PHP رخ میدهند. این فایل معمولاً در یکی از دو دایرکتوری /var/log/apache2/ یا /usr/local/lsws/logs/ پیدا میشود.
اتفاقاً بیشترین کاربرد این فایل، پیدا کردن دلیل ارور ۵۰۳ است!
برای مثال، نمونه زیر خروجیای است که از این لاگ دریافت خواهید کرد:
[STDERR] fork() failed, please increase process limit: Cannot allocate memory
در این مورد، Error Log توسط وبسرور ایجاد میشود. این فایل هم در یکی از سه دایرکتوری /var/log/apache2/ یا /usr/local/lsws/logs/ یا /var/log/httpd/error_log قرار دارد! Error Log وبسرور، علاوهبر اینکه مشخص میکند ایراد از وبسرور است یا نه، راهکارهای کارآمدی را هم در اختیارتان میگذارد.
مثال زیر، یک نمونه خروجی از ارور لاگ وب سرور است:
[INFO] [319934] [1.1.1.1:49873-1#APVH:lsapi] connection to [uds://tmp/lshttpd/APVH-php56.sock] on request #0, confirmed, 0, associated process: 0, running: 0, error: Too many open files!
اگر میخواهید تعداد خطاهای ۵۰۳ را متوجه شوید، یا میخواهید بفهمید از آخرین باری که مشکل را برطرف کردهاید، آیا مجدداً خطای ۵۰۳ رخ داده یا نه، باید از دستور زیر استفاده کنید:
grep oops /etc/apache2/logs/error_log
نکته: در بیشتر مواقع، دلیل بروز این خطا ارائه نمیشود. بلکه فقط زمان و دامنهای که درگیر بوده نمایش داده میشود.
این لاگ خطا، توسط سیستمعامل ایجاد میشود. برای پیدا کردن آن هم باید در یکی از ۲ دایرکتوری /var/log/messages یا /var/log/syslog دنبالش بگردید. اگر PHP به هر نحوی تحت تاثیر سیستمعامل قرار گرفته باشد، استفاده از این لاگ کمکتان میکند.
مثال زیر:
lfd[18304]: *User Processing* PID:18264 Kill:1 User:xxxxx VM:538(MB) EXE:/usr/local/lsws/fcgi-bin/lsphp-5.4.42 CMD:lsphp5
خروجی بالا، نشان میدهد که پروسه lsphp توسط فایروال lfd از بین رفته است. در واقع باید lsphp را از lfd حذف کنید.
این لاگ در php.ini تعریف میشود. میتوانید phpinfo.php را برای پیدا کردن php error_log جستوجو کنید. کنترلپنل سیپنل، بهصورت پیشفرض آن را در error_log قرار میدهد. PHP وقتی خطا، هشدار یا هرچیز مشابه دیگری را شناسایی کند، بسته به سطح لاگی که به آن دسترسی دارید، چنین لاگی را میسازد.
معمولاً این لاگ، داخل همان فولدری که PHP اجرا میشود، ساخته میشود.
مثال زیر، یک خروجی از PHP Error Log را نشان میدهد:
Fatal error: Call to undefined function my_function() in /home/mysite/public_html/test.php on line 2
معمولاً 3 نوع خطا در اپلیکیشن PHP که در حال استفاده از آن هستید رخ میدهد. بهترین راه برای مقابله با آنها، ارسال این لاگها برای توسعهدهنده اپلیکیشن مبتنیبر PHP است.
خب برویم سراغ عیبیابی دقیقتر!
در این بخش، چگونگی عیبیابی خطای ۵۰۳ را به دو صورت مقدماتی و پیشرفته بررسی خواهیم کرد.
حتما بخوانید: چگونگی حذف یک تصویر از نتایج گوگل
خود این بخش، به قسمتهای مختلف تقسیم میشود:
در محیط عمل، رایج است که اپلیکیشن مبتنیبر PHP را از نمایش خطا منع میکنند! این کار برای حفاظت از سرور، هنگام بروز خطا انجام میشود. البته اگر بخواهید دلیل بروز خطای ۵۰۳ را تشخیص دهید، این کار بهنوعی مانع عملیات می شود!
اگر خطای 503 برای یک سایت یا دامنه مشخص رخ داده است، کد زیر را درست بعد از <?php و در اسکریپت مشابه با خطای 503 وارد کنید:
<?php # The opening PHP tag
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
حالا وقتی قصد بازدید از صفحه وب را داشته باشید، احتمالاً با خطایی مشابه خطای زیر مواجه خواهید شد:
Fatal error: Call to undefined function my_function() in /home/mysite/public_html/test.php on line 2
معمولاً این خطا، هیچ ارتباطی با وبسرور ندارد. در واقع، یک ایراد از جانب کد است! توصیه ما این است که Stack Overflow را بررسی کنید. همچنین میتوانید با توسعهدهنده نرمافزار برای رفع مشکل تماس بگیرید.
نکته: بعد از اینکه خطا را شناسایی کردید، حتماً فایل را به مکان قبلیاش بازگردانید تا امنیت سرورتان حفظ شود.
این بخش (PHP info page)، اطلاعات بسیار زیادی را در رابطه با نصب PHP در اختیارمان میگذارد. این صفحه یک فایل کاملاً مقدماتی است که نباید خطای 503 را نشانمان دهد:
<?php
echo phpinfo();
?>
نکته: اگر در PHP info page با خطای 503 مواجه شدید، این بخش کمکتان نخواهد کرد!
نکته: اگر در PHP info page با خطای 503 مواجه شدید، این بخش کمکتان نخواهد کرد!
از جمله اطلاعاتی که PHP info page ارائه میکند، موارد زیر هستند:
تصویر بالا، یک صفحه PHP info page را نشان میدهد.
اگر به این تصویر دقت کنید، میبینید که OPCache فعال است، مقدار محدودیت مموری یا memory limit را خواهید دید، میتوانید بفهمید کدام افزونهها در حال کار هستند و …. تمام این اطلاعات، برای پیدا کردن دلیل خطای 503 بسیار مفید هستند.
همچنین این صفحه، میتواند برای مقایسه بین پیادهسازیهای PHP دو وبسرور آپاچی و لایت اسپید هم کارآمد باشد.
بسیاری از افزونههای مفید PHP هستند که منجر به بروز این خطا میشوند! مخصوصاً وقتی بهروزرسانی نشده باشند!
مثل موارد زیر:
توصیه اول اینکه دائماً این افزونهها را بهروزرسانی کنید؛ اما اگر از آخرین نسخه آنها استفاده میکنید و همچنان مشکل برقرار است، غیرفعالشان کنید! اگر مشکل برطرف شد که دلیل آن هم مشخص میشود.
اما اگر مشکل همچنان برقرار بود، تمام افزونههایی که بهصورت پیشفرض فعال نبودند را غیرفعال کنید. حالا مجدداً بررسی کنید. اگر خطا برطرف شده بود که هیچ، اگر نه همراهمان باقی بمانید.
این نوع کش، در واقع پروسه نگهداری از بایت کدها در حافظه اشتراکی است! به این ترتیب، دیگر نیازی است PHP یک پروسه مشابه را هربار بازخوانی کند؛ اما خب OPCache میتواند منجر به بروز مشکلاتی شود.
هنگامی که قصد پیدا کردن منشاء ایراد 503 را دارید، حتماً و حتماً OPcache را غیرفعال کنید.
موارد زیر، رایجترین افزونههای OPCache هستند:
دستور زیر، نمونه خطایی است که به OPCache ارتباط دارد:
[STDERR] zend_mm_heap corrupted
در برخی مواقع، PHP فایلها را روی سرور ذخیره میکند تا بتواند عملکرد درستی داشته باشد. اگر حافظهتان تکمیل باشد، مخصوصاً قسمتی از آن که از /tmp/ نگهداری میکند، میتواند دلیلی برای خطای ۵۰۳ باشد.
برای بررسی میزان استفاده از هاردتان، میتوانید دستور $ sudo df -h را اجرا کنید.
مثال زیر، یک نمونه از خروجی این دستور است:
$ sudo df -h
Filesystem Size Used Avail Use% Mounted on
devtmpfs 901M 0 901M 0% /dev
tmpfs 915M 96K 915M 1% /dev/shm
tmpfs 915M 89M 827M 10% /run
tmpfs 915M 0 915M 0% /sys/fs/cgroup
/dev/mapper/cl_centos 29G 4.2G 25G 15% /
/dev/vda1 976M 184M 726M 21% /boot
tmpfs 183M 0 183M 0% /run/user/0
اگر حافظهتان پُر است، فایلهای قدیمی را پاک کنید. ممکن است انجام این کار، مشکل خطای ۵۰۳ را حل کند.
وقتی PHP به محدودیت حافظهای که برایش تعیین شده میرسد، اصطلاحاً Crash میکند. 2 نوع مختلف از memory limit وجود دارد که PHP باید به آنها پایبند باشد:
دو نمونه زیر، برای مواقعی هستند که خطا مرتبط با ایرادات مموری است:
Fatal error: Allowed memory size of 33554432 bytes exhausted (tried to allocate 12864 bytes)
[STDERR] fork() failed, please increase process limit: Cannot allocate memory
اگر موافق باشید، هر دو نوع محدودیت در مموری را کمی دقیقتر بررسی کنیم.
اگر خطایی که دریافت میکنید مثل یکی از موارد بالا است، اولین قدم در عیبیابی، افزایش میزان محدودیت در مموری یا همان Memory limit است. میتوانید تنظیماتی که در ادامه آوردهایم را در php.ini اعمال کنید:
memory_limit = 100M
برای اینکه بفهمید مکان قرارگیری فایل php.ini و memory limit کنونی، میتوانید یک صفحه PHP info بسازید. دستور زیر کمکتان میکند:
<?php
echo phpinfo();
?>
در برخی مواقع، ممکن است خطوط مختلف اسکریپت به .htaccess ضمیمه شوند. این کار بهمنظور بازنویسی تنظیمات PHP انجام میشود. همچنین این کار باعث بازنویسی تمام تنظیمات درون فایل php.ini میشود.
مثال زیر، یک نمونه از ورودی memory limit در .htaccess را نشان میدهد:
php_value memory_limit xxxM
برای اضافه کردن، پاک کردن یا حتی اعمال تنظیمات روی این خط کد، باید وارد .htaccess شوید.
اگر از CLoudLinx و Lightweight Virtual Environment یا به اختصار LVE، استفاده میکنید، ممکن است به محدودیت تعیینشده توسط اکانت رسیده باشید.
تصویر بالا نشان میدهد که اکانتها به محدودیت رسیدهاند. بسته به محدودیتی که اکانت با آن مواجه شده است، باید آن را تنظیم کنید.
اگر محدودیت تعیینشده برای مموری را در php.ini افزایش دادهاید و تائید شده که به LVE limit نرسیدهاید، شاید لازم باشد LSPHP حافظه مجازیاش را افزایش دهد.
حتما بخوانید: آموزش نصب zabbix 2.0.x
با انجام اقدامات زیر، میتوانید این کار را انجام دهید:
اگر نهایت حد Execution Time به اندازهای نباشد که بتواند درخواستها طولانی را مدیریت کند، ممکن است با این خطا که مربوط به لاگ وبسرور است مواجه شوید: error: Connection reset by peer
همچنین داشتن مقدار ، این معنی را میرساند که فرایند هیچوقت درخواست را به اتمام نمیرساند. چنین خطاهایی معمولاً در stderr.log نشان داده میشوند. اگر این لاگ هم اطلاعات مفیدی ارائه نکرد، میتوانید میزان max execution time را افزایش دهید.
اگر نهایت حد Execution Time به اندازهای نباشد که بتواند درخواستها طولانی را مدیریت کند، ممکن است با این خطا که مربوط به لاگ وبسرور است مواجه شوید: error: Connection reset by peer
همچنین داشتن مقدار ، این معنی را میرساند که فرایند هیچوقت درخواست را به اتمام نمیرساند. چنین خطاهایی معمولاً در stderr.log نشان داده میشوند. اگر این لاگ هم اطلاعات مفیدی ارائه نکرد، میتوانید میزان max execution time را افزایش دهید.
ممکن است در لاگ stderr.log، چیزی مشابه پیام زیر ببینید:
[30117] Reached max children process limit: 10, extra: 3, current: 13, busy: 13, please increase LSAPI_CHILDREN.
PHP SuXEC Max Conn روی 10 تنظیم شده است، اما دامنه به 13 فرایند PHP نیاز دارد. برای افزایش LSAPI_CHILDREN، به LSWS WebAdmin > Server > General > PHP suEXEC Max Conn بروید و مقدار آن را افزایش دهید. مثلاً در این مورد، عدد 20 را درنظر بگیرید. LSWS و pkill lsphp را Restart کنید تا تنظیمات جدید اعمال شوند.
اگر خطا همچنان وجود داشت، میتوانید به افزایش مقدار PHP suEXEC Max Conn، تا زمانی که خطا از بین برود ادامه دهید.
اگر CSF/LFD را نصب دارید، ممکن است همینها منجر به خطای 503 شوند. این برنامهها میتوانند فرایند را قبل از به اتمام رسیدن نابود کنند.
CSF/LFD دو نوع تنظیمات دارد که میتواند قاتل جان یک فرایند LSPHP باشد:
PT_USERTIME و PT_FORKBOMB
ممکن است دلیل طولانی شدن تکمیل فرایند LSPHP، فراخوانی PT_USERTIME برای نابودی آن باشد. اگر عملیات نابودسازی موفق باشد، احتمالاً یک ایمیل یا پیامی در /var/log/lfd.log دریافت خواهید کرد که حاوی پیغام زیر است:
lfd[18304]: *User Processing* PID:18264 Kill:1 User:xxxxx VM:538(MB) EXE:/usr/local/lsws/fcgi-bin/lsphp-5.4.42 CMD:lsphp5
این یعنی باید فرایند LSPHP را در CSF/LFD مجاز اعلام کنیم تا جلوی وقوع این اتفاق را بگیریم.
برای انجام این کار، باید دستور زیر را اجرا کنیم:
sudo echo “pexe:/usr/local/lsws/fcgi-bin/lsphp.*” >> /etc/csf/csf.pignore
sudo csf -r; sudo service lfd restart
در مواردی نادر، LSPHP توسط PT_FORKBOMB و بهخاطر داشتن تعداد زیادی فرایند نابود میشود! در عوض این کار، فرستادن سیگنال 9/SIGKILL به فرایند اصلی Litespeed را متوقف میکند. برای جلوگیری از متوقفسازی فرایندهای Litespeed توسط CSF/LFD، باید تنظیمات زیر را در /etc/csf/csf.conf اعمال کنید:
PT_LIMIT - Default: 10
PT_USERPROC - Default: 10
PT_FORKBOMB - Default: 0
PT_INTERVAL - Default 60
از آنجایی که هر مورد با دیگری فرق میکند، اعمال این تنظیمات برای هر مورد باید بهصورت جداگانه انجام شود. مقادیر باید تا زمانی که مشکل متوقف شود به آهستگی افزایش پیدا کنند. برای اینکه تغییر تنظیمات اثر کنند، باید هم CSF و هم LFD را Restart کنید. این کار هم میتواند از طریق یک افزونه WHM یا از طریق ترمینال و با کمک دستور زیر انجام شود:
$ sudo csf -r; sudo service lfd restart
استفاده از افزونههای LSPHP که با نسخه LSPHP شما سازگار نیستند، میتوانند منجر به خطای 503 شوند. اگر دلیل خطای 503 همین باشد، پیام زیر را داخل یک لاگ stderr.log خواهید دید:
Warning: PHP Startup: imap: Unable to initialize module
Module compiled with module API=20090626
PHP compiled with module API=20100525
These options need to match in Unknown on line 0
برای رفع این مشکل، باید ماژول یا PHP را از نو بسازید! از نسخهای از PHP استفاده کنید که با ماژول سازگاری داشته باشد. همچنین اطمینان حاصل کنید که افزونه در مسیر درست نصب شده است.
در صورت استفاده از PHP، برخی از افزونهها به افزونههای دیگری نیاز دارند تا به ترتیب بارگذاری شوند و بتوانند بهترین عملکرد را ارائه کنند. این کار با تغییر فایل .ini از mysql.so به 20-mysql.so انجام میشود.
۲۰- الویت بارگذاری را مشخص میکند. این عدد میتواند بین ۱ تا ۹۹ متغیر باشد.
اگر دلیل بروز خطا همین باشد، باید پیغام زیر را در لاگ stderr.log مشاهده کنید:
PHP Warning: PHP Startup: Unable to load dynamic library
اگر پیغام زیر را در لاگ وبسرورتان دیدید، یعنی سیستمتان به نهایت مقدار فایلهای باز ممکن رسیده است:
[INFO] [319934] [1.1.1.1:49873-1#APVH:lsapi] connection to [uds://tmp/lshttpd/APVH-php56.sock] on request #0, confirmed, 0, associated process: 0, running: 0, error: Too many open files!
برای بررسی محدودیت فعلی، دستور زیر را اجرا کنید:
$ sudo ulimit -n
خروجی این دستور، محدودیت کنونی سیستمتان را نشان میدهد. برای رفع مشکل ۵۰۳ باید این محدودیت را با اجرای دستور زیر افزایش دهید:
$ sudo ulimit -n <Increased_Number>
حالا احتمالاً دیگر مشکل 503 از بین خواهد رفت؛ چراکه LSPHP میتواند فایلهای بیشتری را در سیستم باز کند.
اگر از WordPress استفاده میکنید، احتمالاً هنگام کار با تصاویر گرافیکی با این خطا مواجه خواهید شد:
libgomp: Thread creation failed: Resource temporarily unavailable
اگر از WordPress استفاده میکنید، احتمالاً هنگام کار با تصاویر گرافیکی با این خطا مواجه خواهید شد:
حتما بخوانید: htaccess چیست؟ چگونه از آن برای SEO تکنیکال استفاده کنیم؟
معمولاً این مشکل به خاطر ماژول ImageMagick ایجاد میشود. این ماژول به استفاده از منابع بهمیزان زیاد مشهور است. برای رفع مشکل، میزان memory_limit را در فایل php.ini افزایش دهید، یا محدودیت حافظه خارجی app را به میزان بالاتری مثل 8G افزایش دهید.
از دستور زیر برای رصد کردن فرایندهای PHP استفاده کنید تا بفهمید چه اتفاقاتی در جریان هستند:
strace -tt -T -f -p <pid>
در این بخش فرض میگیریم که قبلاً core dumpها را برای سنتوس و اوبنتو فعال کردهاید:
Environment: LSAPI_ALLOW_CORE_DUMP=1
GNU Debugger یا GDB از خط gdb <path/to/lsphp/binary> <path/to/core/file>. استفاده میکند.
<path/to/lsphp/binary> مسیری است که PHP binary در آن قرار دارد و برنامههای PHP از آن استفاده میکنند. مسیر منتهی به Core File، مکانی است که Core File در آن قرار دارد.
ابتدا برای لود کردن GDB باید ` را اجرا کنید.
سپس یک prompt همراه با gdb خواهید دید. در محله بعدی هم باید bt را بنویسید و enter را بزنید.
انجام این کارها، خروجیای مثل خروجی زیر ایجاد خواهد کرد:
gdb <path/to/lsphp/binary> <path/to/core/file>
Program received signal SIGSEGV, Segmentation fault.
0x000000000061c91b in ?? ()
(gdb) bt
#0 0x000000000061c91b in ?? ()
#1 0x0000000000641ac3 in zend_stack_push ()
#2 0x000000000060bbf9 in ?? ()
#3 0x0000000000611515 in lex_scan ()
#4 0x000000000061fb60 in ?? ()
#5 0x0000000000608223 in ?? ()
#6 0x0000000000614965 in compile_file ()
#7 0x00007fd3c99eda21 in ?? () from /opt/alt/php55/usr/lib64/php/modules/phar.so
#8 0x00007fd3d0993359 in ?? () from /opt/alt/php55/usr/lib64/php/modules/opcache.so
#9 0x00007fd3d0994187 in ?? () from /opt/alt/php55/usr/lib64/php/modules/opcache.so
#10 0x00000000006b54da in ?? ()
#11 0x00000000006b68e8 in execute_ex ()
#12 0x000000000064239c in zend_execute_scripts ()
#13 0x00000000005e2fb0 in php_execute_script ()
#14 0x00000000006f29ff in ?? ()
#15 0x00000000006f2c5c in ?? ()
#16 0x00000000006f2f85 in ?? ()
#17 0x00007fd3d37cdd1d in __libc_start_main () from /lib64/libc.so.6
#18 0x0000000000424bc9 in _start ()
در این خروجی برخی از ماژولهایی را میبینیم که هنگام کرش شدن، در phar.so و opache.so بارگذاری میشوند. اگر قصد عیبیابی این مورد را دارید، باید phar.so و opache.so را غیرفعال کنید تا بفهمید کدام ماژولها منجر به این خطا شدهاند.
حتی امکان بررسی دقیقتر فایل core هم وجود دارد. این کار در پیدا کردن عمکردی که منجر به ایراد شده موثر است. برای فهمیدن این موضوع، دستور زیر را اجرا کنید:
(gdb) frame 13
(gdb) print (char *)(executor_globals.function_state_ptr->function)->common.function_name
(gdb) print (char *)executor_globals.active_op_array->function_name
(gdb) print (char *)executor_globals.active_op_array->filename
حتی اگر پاسخ یک صفحه خالی هم باشد مشکلی ندارد. آنقدر اجرای این دستور را ادامه دهید تا عمکلرد یا فایل مخرب را پیدا کنید..