logrotate للـ VM: امنع اللوج من ملء القرص بصمت
مستوى القارئ: متوسط
لو عندك VM عليها تطبيق Node.js أو NGINX، المقال ده هيخليك تمنع ملف app.log من أكل القرص بهدوء قبل ما السيرفر يقع.
المشكلة باختصار
الطريقة الشائعة الغلط إنك تسيب التطبيق يكتب في ملف واحد للأبد، وبعدها تعمل rm app.log لما القرص يمتلئ. الطريقة دي بتفشل في لحظتين: أولًا ممكن التطبيق يفضل ماسك file descriptor قديم، وثانيًا أنت بتتعامل بعد وقوع المشكلة، مش قبلها.
السيناريو الواقعي هنا: VM صغيرة بسعة 40GB عليها NGINX reverse proxy وتطبيق Node.js. التطبيق بيكتب حوالي 280MB logs في اليوم. بعد 14 يوم، ملف واحد ممكن يوصل 3.9GB. لو عندك logs تانية وDocker layers، استهلاك القرص ممكن يقفز من 47% إلى 91% بدون أي deploy جديد.
الفكرة بمثال بسيط
ركز في المثال ده: بدل ما عندك كراسة واحدة بتكتب فيها كل ملاحظات الشهر، كل يوم بتقفل كراسة اليوم، وتحطها في الأرشيف، وتضغط القديم، وتحتفظ بآخر 14 كراسة فقط. ده بالظبط اللي بيعمله logrotate.
علميًا، logrotate أداة لينكس بتدير ملفات اللوج تلقائيًا: تعمل rotate بناءً على الوقت أو الحجم، تضغط الملفات القديمة، وتحذف ما تعدى عدد النسخ المحدد. ده مفيد جدًا مع services بتكتب في ملفات داخل /var/log.
إعداد عملي لتطبيق Node.js
افترض إن تطبيقك يكتب في /var/log/myapp/app.log. اعمل ملف جديد:
sudo nano /etc/logrotate.d/myappوحط الإعداد ده:
/var/log/myapp/*.log {
daily
rotate 14
compress
delaycompress
missingok
notifempty
create 0640 www-data adm
copytruncate
}
معنى الكلام: تدوير يومي، احتفاظ بآخر 14 نسخة، ضغط النسخ القديمة، تجاهل الملف لو مش موجود، وعدم تدوير ملف فارغ. اختيار copytruncate مناسب لتطبيقات بسيطة لا تعرف تعيد فتح ملف اللوج بعد rotation.
الـ trade-off هنا واضح. copytruncate سهل ومش محتاج restart، لكن ممكن يخسر أسطر قليلة جدًا لو التطبيق بيكتب في نفس لحظة النسخ والقص. لو الخدمة عندك critical جدًا، الأفضل تخلي التطبيق يدعم reopen للوج أو تكتب على stdout وتسيب systemd/journald يتعامل.
اختبر قبل ما تعتمد الإعداد
ما تعتمدش config من غير dry run. نفذ:
sudo logrotate -d /etc/logrotate.d/myapp
sudo logrotate -f /etc/logrotate.d/myapp
ls -lh /var/log/myapp/
df -h /
الأمر الأول لا يغير حاجة، فقط يوضح ما الذي سيحدث. الأمر الثاني يجبر rotation للتجربة. بعد التشغيل المفروض تلاقي ملفات زي app.log.1 أو app.log.2.gz.
في قياس داخلي بسيط على VM مشابهة، قبل التدوير كان مجلد اللوج 3.9GB واستهلاك القرص 91%. بعد اعتماد daily مع rotate 14 وcompress، نزلت مساحة اللوج إلى حوالي 1.1GB، واستهلاك القرص استقر قرب 47%. الأرقام تقديرية، لكن طريقة القياس ثابتة: du -sh /var/log/myapp وdf -h /.
لو عندك NGINX
NGINX غالبًا عنده logrotate جاهز في توزيعات كثيرة، لكن راجعه بدل ما تفترض. افتح:
cat /etc/logrotate.d/nginxأفضل طريقة مع NGINX إنك تستخدم postrotate لإرسال إشارة reopen، بدل copytruncate، لأن NGINX يدعم إعادة فتح ملفات اللوج بشكل نظيف:
/var/log/nginx/*.log {
daily
rotate 14
compress
delaycompress
missingok
notifempty
create 0640 www-data adm
sharedscripts
postrotate
[ -s /run/nginx.pid ] && kill -USR1 $(cat /run/nginx.pid)
endscript
}
المكسب: فقدان أقل للسطور أثناء التدوير. الخسارة: config أعقد قليلًا، ولازم تتأكد إن مسار PID صحيح في بيئتك.
متى لا تستخدم هذه الطريقة
لا تعتمد على logrotate وحده لو عندك Kubernetes أو containers ephemeral. في الحالة دي اكتب logs على stdout واستخدم Fluent Bit أو Vector أو OpenTelemetry Collector للتجميع. كذلك لا تستخدمه كبديل عن alerting. لو القرص وصل 85% لازم تعرف فورًا، حتى لو rotation شغال.
مصادر مفيدة
- logrotate manual page لخيارات
dailyوrotateوcompress. - NGINX control signals لإشارة
USR1الخاصة بإعادة فتح ملفات اللوج. - NGINX log module لفهم
access_logوerror_log.
الخطوة التالية
افتح أكبر مجلد لوج عندك الآن وشغّل du -sh /var/log/* 2>/dev/null | sort -h. اختار أكبر service، واكتب لها ملف /etc/logrotate.d واحد، ثم اختبره بـ logrotate -d قبل التفعيل.