اگر logrotate هنگام چرخش لاگ پیام skipping ... because parent directory has insecure permissions میدهد، مشکل معمولاً مجوز نوشتن یا مالکیت پوشه والد فایل لاگ است؛ نه صرفاً خود فایل. ابتدا مسیر، مالک و permission را بررسی کنید. سپس بهجای بازکردن بیرویه دسترسیها، مالکیت پوشه را اصلاح کنید یا در فایل تنظیمات همان سرویس، دستور su user group را با حسابی که واقعاً مجوز مدیریت آن لاگ را دارد تنظیم کنید. پیش از اعمال تغییر، با logrotate -d یک Dry Run بگیرید.
پیام خطا چه معنایی دارد؟
logrotate برای جلوگیری از چرخش ناامن فایل در پوشهای که کاربران غیرمجاز امکان تغییر آن را دارند، بعضی مسیرها را رد میکند. متن خطا ممکن است پیشنهاد کند از دستور su در پیکربندی استفاده شود. این خطا با پر شدن فضای دیسک یا خرابی خود سرویس تفاوت دارد. در صورت مشاهده No space left on device ابتدا تفاوت پرشدن دیسک و inode در لینوکس را بررسی کنید.
مرحله اول: مسیر واقعی و تنظیمات logrotate را پیدا کنید
نمونه زیر از /var/log/myapp/app.log استفاده میکند؛ آن را با مسیر واقعی سرویس خود جایگزین کنید. هیچ فرمان تغییر مجوز را قبل از تطبیق مسیر اجرا نکنید.
sudo logrotate --version
sudo grep -R -n -F '/var/log/myapp/' /etc/logrotate.conf /etc/logrotate.d 2>/dev/null
sudo namei -l /var/log/myapp/app.log
sudo stat -c '%A %a %U:%G %n' /var/log /var/log/myapp /var/log/myapp/app.log
sudo ls -ld /var/log/myappبا namei -l تمام اجزای مسیر را ببینید. اگر پوشه والد برای گروهی غیرقابلاعتماد یا همه کاربران قابلنوشتن باشد، احتمال رد شدن rotation افزایش مییابد. مجوز 777 راهحل امن نیست.
مرحله دوم: اجرای آزمایشی بدون تغییر لاگ
فایل پیکربندی مرتبط با سرویس را پیدا کنید؛ برای مثال /etc/logrotate.d/myapp. سپس حالت Debug را اجرا کنید:
sudo logrotate -d /etc/logrotate.d/myappگزینه -d عملیات چرخش و تغییر state را انجام نمیدهد. اگر تنظیمات از includeهای سراسری یا متغیرهای دیگر استفاده میکنند، خروجی اجرای فایل منفرد را با پیکربندی اصلی نیز مقایسه کنید:
sudo logrotate -d /etc/logrotate.confخطای permission را در خروجی پیدا کنید؛ اجرای -f در این مرحله توصیه نمیشود، زیرا برخلاف Debug ممکن است واقعاً لاگها را بچرخاند.
مرحله سوم: اصلاح مجوز پوشه بدون chmod 777
اگر سرویس با حساب اختصاصی مانند myapp کار میکند، ابتدا با systemctl cat و systemctl show حساب واقعی آن را بررسی کنید:
systemctl show myapp.service -p User -p Group
systemctl cat myapp.serviceدر مثال فرضی، پوشه لاگ باید در اختیار حساب سرویس و گروه مورداعتماد باشد. فقط بعد از تأیید اینکه این پوشه مختص همین برنامه است، مالکیت و مجوز همان پوشه را اصلاح کنید:
sudo chown myapp:myapp /var/log/myapp
sudo chmod 0750 /var/log/myapp
sudo stat -c '%A %a %U:%G %n' /var/log/myappهشدار: این فرمانها را برای /var/log یا مسیرهای اشتراکی اجرا نکنید. تغییر مالکیت بازگشتی (chown -R) نیز بدون بررسی ساختار و نیاز سرویس ممکن است دسترسی برنامههای دیگر را خراب کند. اگر حساب سرویس متفاوت است، مقادیر مثال را کورکورانه اجرا نکنید.
مرحله چهارم: استفاده درست از su در logrotate
اگر سیاست مالکیت پوشه را نمیتوان یا نباید تغییر داد و فایل باید با مجوز حساب مشخصی چرخانده شود، از su در بلوک همان لاگ استفاده کنید. ابتدا از فایل تنظیمات موجود نسخه پشتیبان بگیرید:
sudo cp -a /etc/logrotate.d/myapp /etc/logrotate.d/myapp.bak.$(date +%Y%m%d-%H%M%S)نمونه پیکربندی زیر صرفاً برای سرویسی است که حساب و گروه myapp دارد و مجوز لازم برای فایل و پوشه را دریافت کرده است:
/var/log/myapp/app.log {
daily
rotate 7
missingok
notifempty
compress
su myapp myapp
create 0640 myapp myapp
}su myapp myapp عملیات چرخش را با هویت تعیینشده انجام میدهد؛ create مالک و مجوز فایل جدید را تعیین میکند. این دو گزینه جایگزین اصلاح مجوزهای ناامن یا تضمین دسترسی برنامه نیستند. اگر برنامه فایل باز را نگه میدارد، باید رفتار reopen/reload یا نیاز به postrotate را از مستندات همان برنامه بررسی کنید. copytruncate را بدون سنجش احتمال از دست رفتن چند خط لاگ فعال نکنید.
مرحله پنجم: Verify و بررسی اجرای زمانبندیشده
پس از اصلاح، یک Dry Run دیگر بگیرید و سپس وضعیت timer یا سرویس logrotate را بررسی کنید. نام unit بسته به توزیع متفاوت است:
sudo logrotate -d /etc/logrotate.conf
systemctl list-timers --all | grep -i logrotate
sudo systemctl status logrotate.timer --no-pager
sudo journalctl -u logrotate.service -n 50 --no-pagerنبودن logrotate.timer الزاماً خطا نیست؛ برخی توزیعها از cron استفاده میکنند. برای تفاوت زمانبندیها، مقاله آموزش systemd Timer و تفاوت آن با Cron را بخوانید.
اگر Dry Run بدون خطا بود و پنجره نگهداری دارید، میتوانید فقط با آگاهی از اثر واقعی چرخش روی برنامه، تست اجرایی انجام دهید. خروجی state، وجود فایل چرخیده، مالکیت فایل تازه و ادامه نوشتن لاگ را کنترل کنید. از اجرای کورکورانه sudo logrotate -f /etc/logrotate.conf روی تمام سرویسهای سرور خودداری کنید.
Rollback و نکات امنیتی
اگر با تغییر مجوز پوشه، سرویس دیگر نمیتواند لاگ بنویسد، مقادیر مالکیت و permission را از خروجی stat اولیه بازگردانید. اگر فایل پیکربندی را تغییر دادهاید، نسخه پشتیبان همان فایل را پس از بررسی نام و زمان آن برگردانید و دوباره logrotate -d اجرا کنید. فایلهای لاگ واقعاً rotate یا حذفشده با برگرداندن تنظیمات بازیابی نمیشوند.
- Permission denied پس از اصلاح: حساب تعریفشده در
suباید مجوز پوشه و فایل را داشته باشد؛ SELinux/AppArmor و ACL را هم بررسی کنید. - فضای دیسک همچنان پر است: logrotate برای فایلهای متنی معمولی با
journalctl --vacuumیکسان نیست. برای لاگ کانتینر، راهنمای چرخش لاگ Docker و کنترل حجم دیسک VPS را ببینید. - لاگ جدید نوشته نمیشود: ممکن است سرویس به reopen نیاز داشته باشد؛ فقط طبق مستندات همان برنامه reload/restart کنید.
اگر روی VPS خودمدیریت، حتی پس از اصلاح گردش لاگ، محدودیت فضای ذخیرهسازی یا منابع همچنان مانع نگهداری امن لاگها است، پس از اندازهگیری مصرف و بررسی نیاز واقعی میتوانید پلنهای سرور مجازی وانسرور را برای ظرفیت مناسب مقایسه کنید؛ تغییر VPS بهتنهایی خطای مجوز logrotate را برطرف نمیکند.
مرجع فنی: راهنمای logrotate(8) و مستندات upstream پروژه logrotate.
