سایت خطا میدهد. مشتری زنگ زده. شما نمیدانید از کجا شروع کنید. در این لحظه، لاگهای سرور بهترین دوست شما هستند — اگر بلد باشید آنها را بخوانید. لاگها مثل صندوق سیاه هواپیما هستند: هر اتفاقی با زمان دقیق ثبت شده، هر درخواست، هر خطا، هر هشدار. توانایی خواندن و تفسیر لاگها یکی از اساسیترین مهارتهای هر مدیر سیستم و توسعهدهنده وب است.
در این راهنما همه چیز درباره لاگهای سرور را پوشش میدهیم: انواع لاگها، محل قرارگیری آنها، روشهای جستجو، تفسیر خطاهای رایج و مدیریت درست لاگها.
لاگ چیست و چه اطلاعاتی دارد؟
هر خط لاگ معمولاً شامل این بخشها است:
- Timestamp: تاریخ و زمان دقیق رویداد — برای یافتن دقیق زمان وقوع مشکل
- Severity Level: سطح اهمیت — Error، Warning، Info، Debug
- منبع: کدام سرویس یا ماژول این رویداد را ثبت کرده
- پیام: شرح رویداد — اینجا اطلاعات اصلی است
بدون لاگ، عیبیابی مثل دیدن در تاریکی است. با لاگ، میتوانید دقیقاً ببینید چه اتفاقی افتاده، کجا، و از کِی.
انواع لاگهای سرور
Error Log (لاگ خطا)
مهمترین لاگ برای عیبیابی. خطاهای برنامهنویسی، مشکلات پیکربندی، خطاهای دیتابیس و هر چیزی که «اشتباه» رفته اینجا ثبت میشود. این باید اول بررسی شود — قبل از هر چیز دیگری.
Access Log (لاگ دسترسی)
هر درخواست HTTP به سرور ثبت میشود: IP کاربر، URL درخواست شده، کد HTTP پاسخ، حجم پاسخ، User-Agent و زمان پردازش. برای تحلیل ترافیک، شناسایی الگوهای حمله و debug مشکلات مربوط به درخواستهای خاص مفید است.
System Log
رویدادهای سیستمعامل: راهاندازی سرویسها، ورود کاربران، تغییرات سیستمی و پیامهای kernel. در لینوکس در /var/log/syslog (Debian/Ubuntu) یا /var/log/messages (CentOS/RHEL) قرار دارد.
Authentication Log
تلاشهای ورود به سیستم (موفق و ناموفق) ثبت میشود. برای تشخیص حملات brute force حیاتی است. چند صد خط "Failed password for root" از یک IP به معنای حمله brute force است. در /var/log/auth.log یا /var/log/secure قرار دارد.
Application Log
لاگهایی که خود اپلیکیشن مینویسد. بیشترین اطلاعات مفید برای debugging اینجاست — چون اپلیکیشن میداند دقیقاً چه اتفاقی افتاده.
محل قرارگیری لاگهای مختلف
Apache
معمولاً در /var/log/apache2/ (Debian/Ubuntu) یا /var/log/httpd/ (CentOS):
- Error log: /var/log/apache2/error.log
- Access log: /var/log/apache2/access.log
- هر Virtual Host میتواند لاگ جداگانه داشته باشد — مسیرش در تنظیمات vhost تعریف میشود
Nginx
در /var/log/nginx/:
- Error log: /var/log/nginx/error.log
- Access log: /var/log/nginx/access.log
- میتوانید در تنظیمات هر site مسیر لاگ را تغییر دهید
PHP
مسیر لاگ PHP در php.ini با دایرکتیو error_log تنظیم میشود:
- با PHP-FPM: /var/log/php8.1-fpm.log (بستگی به نسخه دارد)
- خطاهای PHP ممکن است در لاگ وب سرور هم ظاهر شوند
- با دستور php --ini مسیر php.ini فعال را پیدا کنید
MySQL / MariaDB
- Error log: /var/log/mysql/error.log
- Slow query log: در
my.cnfباslow_query_log=1وlong_query_time=1فعال کنید - General log: برای debug موقت — همه کوئریها را ثبت میکند اما روی performance تأثیر میگذارد
لاراول
لاگهای لاراول در storage/logs/laravel.log قرار دارند. با تنظیم LOG_CHANNEL در .env میتوانید کانال لاگگیری را عوض کنید. لاراول از کتابخانه Monolog استفاده میکند و channel های مختلفی مثل daily (لاگ جداگانه هر روز) دارد.
WordPress
وردپرس به صورت پیشفرض لاگ نمینویسد. برای فعال کردن، در wp-config.php اضافه کنید:
- define('WP_DEBUG', true);
- define('WP_DEBUG_LOG', true);
- define('WP_DEBUG_DISPLAY', false); — در production حتماً false باشد
لاگ در wp-content/debug.log ذخیره میشود.
دستورات کار با لاگ در لینوکس
مشاهده لاگ
دستورات پایه که باید حفظ باشند:
- tail -n 100 /var/log/nginx/error.log — آخرین ۱۰۰ خط
- tail -f /var/log/nginx/error.log — دنبال کردن لحظهای (مثل تماشای live) — Ctrl+C برای خروج
- tail -f /var/log/nginx/error.log | grep "crit" — فقط خطاهای بحرانی در real-time
- less /var/log/nginx/error.log — مرور با قابلیت جستجو (دستور / برای search)
جستجو در لاگ
- grep "404" /var/log/nginx/access.log — همه خطاهای ۴۰۴
- grep -i "error" /var/log/nginx/error.log — جستجو بدون case sensitivity
- grep "2024-05-15" /var/log/nginx/access.log — لاگهای یک روز خاص
- grep -A 5 -B 5 "Uncaught exception" storage/logs/laravel.log — ۵ خط قبل و بعد از match
آنالیز لاگ
- awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20 — ۲۰ IP با بیشترین درخواست
- grep " 500 " /var/log/nginx/access.log | wc -l — تعداد خطاهای ۵۰۰ در یک روز
- grep " 500 " /var/log/nginx/access.log | awk '{print $7}' | sort | uniq -c | sort -rn — کدام URL بیشترین خطای ۵۰۰ دارد
تفسیر خطاهای رایج
۴۰۴ Not Found
فایل یا صفحه پیدا نشد. دلایل رایج: URL اشتباه یا فایل حذف شده. پیکربندی rewrite اشتباه (مثلاً .htaccess مشکل دارد). فایل استاتیک (CSS، JS، تصویر) از مسیر اشتباهی load میشود. اگر تعداد زیادی ۴۰۴ برای یک URL مشخص میبینید، به احتمال زیاد یک لینک یا redirect خراب دارید.
۵۰۰ Internal Server Error
خطای کلی سمت سرور. باید error log را چک کنید تا دلیل دقیق را بفهمید. دلایل رایج:
- خطای syntax در کد PHP — PHP parse error است
- خطای
.htaccess— یک directive اشتباه کل سایت را down میکند - permission اشتباه روی فایلها یا پوشهها
- حافظه PHP ناکافی (
memory_limitکم است) - اتصال به دیتابیس برقرار نشده
۵۰۲ Bad Gateway
Nginx نمیتواند با backend (PHP-FPM، Node.js، Gunicorn) ارتباط برقرار کند. شایعترین دلیل این است که PHP-FPM از کار افتاده:
- systemctl status php8.1-fpm — آیا سرویس در حال اجراست؟
- systemctl restart php8.1-fpm — ریاستارت سرویس
اگر PHP-FPM دائماً crash میکند، لاگ آن را چک کنید.
۵۰۳ Service Unavailable
سرور موقتاً در دسترس نیست. دلایل: منابع سرور تمام شده (CPU یا RAM). سرویس در حالت maintenance. تعداد اتصالها از حد مجاز (MaxClients در Apache یا worker_processes در Nginx) بیشتر شده. اول CPU و RAM را با htop چک کنید.
خطاهای PHP رایج
- PHP Fatal error: Call to undefined function: تابع یا extension ای که استفاده میکنید نصب نیست — نام extension را پیدا کنید و نصب کنید
- PHP Warning: Cannot modify header information: output قبل از header ارسال شده — معمولاً یک space یا BOM در ابتدای یک فایل PHP
- PHP Fatal error: Allowed memory size exhausted:
memory_limitرا در php.ini یا.htaccessبالا ببرید:php_value memory_limit 256M - Permission denied: فایل یا پوشه permission مناسب ندارد —
chmodیاchownاجرا کنید
خطاهای MySQL رایج
- Too many connections:
max_connectionsرا درmy.cnfبالا ببرید یا connection pooling تنظیم کنید - Deadlock found when trying to get lock: نشانه کوئریهای همزمان متعارض — کدی که transaction ها را درست مدیریت نمیکند
- Table './db/tablename' is marked as crashed: جدول corrupt شده — با
REPAIR TABLE tablename;تعمیر کنید
مدیریت لاگها
Log Rotation با logrotate
لاگها با گذشت زمان بزرگ میشوند. یک فایل access.log پرترافیک میتواند در چند هفته چند گیگابایت شود. logrotate این مشکل را حل میکند:
- لاگهای قدیمی را فشرده میکند (.gz)
- پس از مدت مشخص حذف میکند
- لاگ جدید را شروع میکند
فایلهای پیکربندی logrotate در /etc/logrotate.d/ قرار دارند. برای چک کردن درست بودن پیکربندی: logrotate --debug /etc/logrotate.d/nginx
Centralized Log Management
وقتی چند سرور دارید، مدیریت جداگانه لاگها دردسرساز میشود. سیستمهای متمرکز لاگ همه لاگها را یکجا جمع میکنند:
- ELK Stack: Elasticsearch (ذخیرهسازی)، Logstash (پردازش) و Kibana (نمایش) — قدرتمندترین گزینه
- Loki + Grafana: سبکتر از ELK، ادغام خوب با Grafana که احتمالاً برای مانیتورینگ هم دارید
- Graylog: یک جایگزین مدیریتپذیرتر برای ELK با رابط کاربری بهتر
امنیت لاگها
لاگها ممکن است اطلاعات حساس داشته باشند. چند نکته:
- دسترسی به فایلهای لاگ را با permission محدود کنید — فقط root یا www-data
- رمزهای عبور، API key ها و اطلاعات حساس نباید در لاگ باشند — اگر اپلیکیشن آنها را log میکند، باید سانسور شوند
- لاگهای دسترسی HTTP آدرس IP کاربران را ذخیره میکنند که باید طبق قوانین حریم خصوصی مدیریت شوند
سوالات متداول
چطور خطای PHP را در هاست اشتراکی ببینم؟
در هاستهای اشتراکی معمولاً به لاگهای سرور مستقیم دسترسی ندارید. اما میتوانید PHP را تنظیم کنید که خطاها را در یک فایل ذخیره کند. در .htaccess:
- php_flag display_errors off
- php_value error_log /home/user/logs/php_errors.log
در لاراول، فایل storage/logs/laravel.log همیشه در دسترس است و اول باید آنجا را چک کنید.
آیا لاگها میتوانند دیسک را پر کنند؟
بله — و این یکی از رایجترین دلایل پر شدن ناگهانی دیسک است. یک سایت پرترافیک میتواند روزانه صدها مگابایت access log تولید کند. حتماً logrotate را برای همه لاگهای مهم تنظیم کنید. اگر دیسک ناگهانی پر شد:
- du -sh /var/log/* — نشان میدهد کدام لاگ بزرگ شده
- find /var/log -size +100M — فایلهای لاگ بالای ۱۰۰ مگابایت
چطور یک خطای ۵۰۰ را step by step debug کنم؟
گام اول: error log وب سرور را چک کنید. گام دوم: error log PHP را بخوانید. گام سوم: اگر از لاراول استفاده میکنید، storage/logs/laravel.log را بخوانید. گام چهارم: permission پوشه storage و bootstrap/cache را چک کنید. گام پنجم: اگر مطمئن نیستید، موقتاً APP_DEBUG=true کنید تا جزئیات خطا در مرورگر نشان داده شود — اما بعد از debug حتماً false کنید.
چطور حملات brute force را از لاگ تشخیص دهم؟
در auth.log، دستور زیر IP هایی را که بیشترین failed login داشتهاند نشان میدهد:
- grep "Failed password" /var/log/auth.log | awk '{print $11}' | sort | uniq -c | sort -rn | head -10
ابزار fail2ban این کار را خودکار میکند — لاگ را میخواند و IP های مشکوک را بلاک میکند. در access log هم، تعداد زیاد درخواست به URL هایی مثل /wp-login.php یا /admin/login از یک IP نشانه brute force است.
جمعبندی
لاگها اولین جایی هستند که باید هنگام بروز مشکل به آنها مراجعه کنید. بدانید لاگها کجا قرار دارند، با دستورات tail، grep و awk آشنا باشید، و معنی خطاهای رایج را یاد بگیرید.
مهمترین نکات عملی: logrotate را برای جلوگیری از پر شدن دیسک تنظیم کنید. دسترسی به لاگها را محدود کنید تا اطلاعات حساس افشا نشود. برای پروژههای با چند سرور، یک سیستم مانیتورینگ متمرکز لاگ راهاندازی کنید. با تسلط بر لاگها، هر مشکلی که در سرور پیش میآید را میتوانید در کوتاهترین زمان شناسایی و رفع کنید.