دیسک سرور روی ۹۸ درصد قفل شده، سایت بالا نمیآید، و وقتی df -h میزنید میبینید /var پر است. بعد du -sh /var/log/* | sort -h را میزنید و یک فایل ۱۲ گیگابایتی جلوی چشمتان است: syslog یا access.log که ماههاست کسی به آن دست نزده. این دقیقاً همان جایی است که logrotate باید کار میکرد و نکرده.
logrotate یک ابزار خط فرمان است که لاگها را بر اساس زمان یا حجم میچرخاند، فشرده میکند و قدیمیها را حذف میکند. روی تقریباً هر توزیع لینوکسی از قبل نصب است و از طریق cron یا systemd timer اجرا میشود. مشکل معمولاً خود ابزار نیست؛ پیکربندیای است که یا وجود ندارد، یا اشتباه نوشته شده، یا فایل لاگ جدیدی خارج از مسیرهای پیشفرض ساخته شده و کسی برایش قانون ننوشته.
چرا logrotate روی سرور شما اجرا نمیشود
قبل از هر تغییری، بفهمید چرا چرخش انجام نشده. سه علت رایج را در عمل دیدهام:
- سرویس logrotate غیرفعال است. با
systemctl status logrotate.timerوضعیت تایمر systemd را چک کنید. اگرinactive (dead)بود، یعنی هیچوقت اجرا نشده. - فایل لاگ خارج از مسیرهای استاندارد است. مثلاً اپلیکیشنی که در
/home/deploy/app/logs/app.logمینویسد و هیچ فایلی در/etc/logrotate.d/برایش وجود ندارد. - پیکربندی خراب است و logrotate بیصدا رد میشود. با
logrotate -d /etc/logrotate.confدر حالت debug اجرا کنید تا ببینید کدام فایل را نادیده میگیرد.
خروجی حالت debug معمولاً خودش جواب را میدهد. اگر خطی مثل error: skipping "/var/log/app.log" because parent directory has insecure permissions دیدید، مشکل مجوز پوشه است نه پیکربندی. logrotate بهطور پیشفرض روی پوشههایی که گروه یا دیگران اجازه نوشتن دارند حساس است و از چرخش رد میشود.
یک فایل پیکربندی که واقعاً کار میکند
فرض کنید اپلیکیشن شما در /var/log/myapp/app.log مینویسد. یک فایل جدید در /etc/logrotate.d/myapp بسازید:
/var/log/myapp/app.log {
daily
rotate 14
size 100M
compress
delaycompress
missingok
notifempty
create 0640 www-data adm
sharedscripts
postrotate
systemctl reload myapp > /dev/null 2>&1 || true
endscript
}
نکتهای که خیلیها از دست میدهند: وقتی هم daily و هم size را میگذارید، شرط حجم برنده است. یعنی فایل حتی اگر یک ساعت هم عمر نداشته باشد، به محض رسیدن به ۱۰۰ مگابایت چرخانده میشود. این رفتار در مستندات man صفحه logrotate.conf صریح آمده ولی در عمل نادیده گرفته میشود.
خط create 0640 www-data adm هم مهم است. اگر مالک و گروه فایل جدید را اشتباه بدهید، بعد از اولین چرخش اپلیکیشن دیگر نمیتواند در فایل بنویسد و لاگها بیصدا قطع میشوند. این خطای خاموش بدترین نوع خرابی است چون تا روزها بعد کسی متوجهش نمیشود.
copytruncate در برابر create: کدام را انتخاب کنم
اینجا جایی است که بیشترین اشتباه رخ میدهد. دو روش برای چرخش وجود دارد و انتخاب بینشان به رفتار اپلیکیشن بستگی دارد، نه به سلیقه.
| روش | نحوه کار | مناسب برای | هزینه |
|---|---|---|---|
create | فایل قدیمی rename میشود، فایل جدید ساخته میشود | سرویسهایی که با سیگنال reload فایل را دوباره باز میکنند (Nginx, Apache, syslog) | نیاز به postrotate و reload دارد |
copytruncate | محتوای فایل کپی میشود، سپس فایل اصلی خالی میشود | اپلیکیشنهایی که فایل را باز نگه میدارند و سیگنال نمیفهمند | پنجره از دست رفتن داده در لحظه کپی |
اگر اپلیکیشن شما فایل لاگ را باز نگه میدارد و راهی برای reload ندارد، copytruncate انتخاب درست است. اما هزینهاش را بدانید: بین لحظهای که logrotate محتوا را کپی میکند و لحظهای که فایل را truncate میکند، هر خطی که اپلیکیشن بنویسد از دست میرود. برای لاگهای تراکنشی این قابل قبول نیست؛ برای لاگ دیباگ معمولاً هست.
در ۹۰ درصد مواردی که سرور خودم را پیکربندی کردهام، create را انتخاب کردهام چون سرویسها سیگنال reload را میفهمند و هیچ دادهای از دست نمیرود. فقط وقتی سراغ copytruncate میروم که اپلیکیشن باینری باشد و کدش دست من نباشد.
اینجا اشتباه میکنند: خیلیها copytruncate را با create همزمان در یک بلوک میگذارند. logrotate این ترکیب را رد نمیکند ولی نتیجه غیرقابل پیشبینی است؛ گاهی فایل جدید ساخته میشود و اپلیکیشن همچنان در فایل renameشده مینویسد. نشانهاش این است: فایل app.log.1 مدام بزرگ میشود و app.log همیشه خالی میماند. اگر این را دیدید، یکی از دو گزینه را حذف کنید.
تست پیکربندی بدون انتظار یک هفتهای
منتظر ماندن تا فردا صبح که ببینید چرخش کار کرده یا نه، وقت تلف کردن است. با -f میتوانید چرخش را به زور اجرا کنید:
logrotate -vf /etc/logrotate.d/myapp
فلگ -v هر تصمیمی که logrotate میگیرد را چاپ میکند و -f باعث میشود بدون توجه به شرط زمان، چرخش انجام شود. بعد از اجرا، ls -lh /var/log/myapp/ را بزنید و ببینید فایل app.log.1 ساخته شده یا نه. اگر delaycompress گذاشته باشید، فایل .1 هنوز فشرده نیست و .2.gz وجود دارد.
یک نکته عملی: قبل از تست روی سرور production، فایل لاگ را با truncate -s 0 خالی نکنید. اگر اپلیکیشن فایل را باز نگه داشته باشد، offset داخلیاش به هم میریزد و تا ریاستارت بعدی چیزی نمینویسد. برای تست، یک فایل لاگ مصنوعی در مسیر موقت بسازید و پیکربندی را روی آن امتحان کنید.
اگر روی هاست اشتراکی یا مدیریتشده کار میکنید و دسترسی root ندارید، معمولاً logrotate از قبل برای سرویسهای اصلی پیکربندی شده و فقط لاگ اپلیکیشن خودتان را باید از داخل پنل مدیریت کنید. در هاست وردپرس این کار از طریق ابزارهای پنل انجام میشود و نیازی به دست زدن به /etc/logrotate.d/ نیست.
وقتی لاگها را جای دیگری میفرستید
اگر از rsyslog یا journald استفاده میکنید، logrotate روی فایلهای journal کار نمیکند. برای journald باید از journalctl --vacuum-size=500M یا تنظیم SystemMaxUse= در /etc/systemd/journald.conf استفاده کنید. این تفاوت را خیلیها نمیدانند و ساعتها دنبال فایل پیکربندی logrotate میگردند که وجود ندارد.
برای لاگهای Nginx و Apache، پیکربندی پیشفرض توزیع معمولاً کافی است ولی اگر دامنههای زیادی روی یک سرور دارید، هر دامنه فایل لاگ جداگانه دارد و باید مطمئن شوید الگوی wildcard درست نوشته شده. یک خط مثل /var/log/nginx/*.log همه را پوشش میدهد ولی اگر بعداً دامنه جدیدی اضافه کنید، خودکار شامل میشود. این بهتر از نوشتن دستی هر مسیر است.
اگر مطمئن نیستید کدام سرویس مسئول لاگنویسی است، مستندات و پایگاه دانش سرورنت مسیرهای پیشفرض هر سرویس را فهرست کرده. همچنین برای بررسی سریع حجم و دسترسی فایلها، ابزارهای رایگان میتوانند کمک کنند.
پرسشهای پرتکرار
چرا logrotate فایل لاگ من را نمیچرخاند؟
سه علت رایج دارد: تایمر systemd غیرفعال است، فایل لاگ در مسیر غیراستاندارد قرار دارد و پیکربندیای برایش نوشته نشده، یا مجوز پوشه والد نامناسب است و logrotate از چرخش رد میشود. با logrotate -d /etc/logrotate.conf در حالت debug دقیقاً ببینید کدام فایل رد شده و چرا.
تفاوت copytruncate و create در logrotate چیست؟
در create فایل قدیمی rename میشود و فایل جدید ساخته میشود؛ اپلیکیشن باید با سیگنال reload فایل را دوباره باز کند. در copytruncate محتوا کپی و فایل اصلی خالی میشود؛ اپلیکیشن نیازی به reload ندارد ولی ممکن است چند خط در لحظه کپی از دست برود.
چطور logrotate را بدون صبر کردن تا فردا تست کنم؟
با دستور logrotate -vf /etc/logrotate.d/yourconfig چرخش را به زور و با خروجی کامل اجرا کنید. فلگ -f شرط زمان را نادیده میگیرد و -v هر تصمیم را چاپ میکند. بعد از اجرا با ls -lh وجود فایل چرخیده را تأیید کنید.
آیا logrotate روی journald هم کار میکند؟
نه. journald لاگها را در فرمت باینری نگه میدارد و logrotate نمیتواند آنها را بچرخاند. برای محدود کردن حجم journal باید از journalctl --vacuum-size یا تنظیم SystemMaxUse در فایل /etc/systemd/journald.conf استفاده کنید.
همین امروز یک بار logrotate -d /etc/logrotate.conf بزنید و خروجیاش را بخوانید. اگر خطایی دیدید، همانجا مشکل دیسک پر شدن را برای ماههای آینده حل کردهاید.
دیدگاهها ۰
هنوز دیدگاهی ثبت نشده؛ اولین نفر باشید!