ตั้งค่า logrotate ไม่ให้ไฟล์ Log เต็มดิสก์

ตั้งค่า logrotate ให้หมุนเวียน บีบอัด และลบไฟล์ Log เก่าของแอปตามรอบที่กำหนด ทดสอบก่อนใช้งานจริง และแก้ปัญหา Log ไม่ถูกหมุนหรือพื้นที่ไม่คืน

โดย ทีมงาน THAI DATA CLOUD อัปเดต อ่าน 12 นาที เข้าชม 10 ครั้ง

แชร์FacebookXLINELinkedIn
ตั้งค่า logrotate ไม่ให้ไฟล์ Log เต็มดิสก์
logrotate — ตั้งค่า logrotate ไม่ให้ไฟล์ Log เต็มดิสก์
ตั้งค่า logrotate ไม่ให้ไฟล์ Log เต็มดิสก์

คำตอบสั้น ๆ: ตั้งค่า logrotate ให้หมุนเวียน บีบอัด และลบไฟล์ Log เก่าของแอปตามรอบที่กำหนด ทดสอบก่อนใช้งานจริง และแก้ปัญหา Log ไม่ถูกหมุนหรือพื้นที่ไม่คืน

คู่มือนี้อธิบาย logrotate ทีละขั้นตอน พร้อมคำสั่งที่ใช้ได้จริงและปัญหาที่พบบ่อย

ไฟล์ Log ที่ไม่มีใครดูแลจะโตขึ้นเรื่อย ๆ จนวันหนึ่งดิสก์เต็ม ฐานข้อมูลเขียนไม่ได้ และเว็บล่ม logrotate คือเครื่องมือมาตรฐานของ Linux ที่ทำหน้าที่หมุนเวียนไฟล์ Log โดยเปลี่ยนชื่อไฟล์ปัจจุบันเป็นไฟล์เก่า เริ่มไฟล์ใหม่ บีบอัดไฟล์เก่า และลบไฟล์ที่เก่าเกินจำนวนที่กำหนด แพ็กเกจอย่าง Nginx, Apache และ MariaDB มีการตั้งค่า logrotate มาให้แล้ว แต่ Log ของแอปที่คุณเขียนเองหรือโฟลเดอร์ Log ที่สร้างขึ้นใหม่ ต้องตั้งค่าเอง

สิ่งที่ต้องเตรียม

  • เซิร์ฟเวอร์ Ubuntu 22.04/24.04 หรือ AlmaLinux/Rocky Linux 8-9 ที่มีแพ็กเกจ logrotate (ติดตั้งมาเป็นค่าเริ่มต้น)
  • สิทธิ์ sudo
  • Path ของไฟล์ Log ที่ต้องการควบคุม เจ้าของไฟล์ และวิธีที่แอปเปิดไฟล์ Log (เพื่อเลือกระหว่าง postrotate กับ copytruncate)

ขั้นตอนที่ 1: ทำความเข้าใจโครงสร้างการตั้งค่า

ไฟล์หลักคือ /etc/logrotate.conf ซึ่งกำหนดค่าเริ่มต้นและดึงไฟล์ทุกไฟล์ใน /etc/logrotate.d/ เข้ามา แต่ละแพ็กเกจจะมีไฟล์ของตัวเองในโฟลเดอร์นั้น ดูตัวอย่างได้ด้วย

ls /etc/logrotate.d/
cat /etc/logrotate.d/nginx

logrotate ไม่ได้ทำงานตลอดเวลา แต่ถูกเรียกวันละครั้ง ตรวจได้ว่าเครื่องของคุณเรียกด้วยวิธีใด

systemctl list-timers | grep logrotate
ls /etc/cron.daily/ | grep logrotate

Ubuntu 22.04/24.04 และ AlmaLinux/Rocky 9 ใช้ systemd timer ชื่อ logrotate.timer ส่วน AlmaLinux/Rocky 8 ใช้สคริปต์ใน /etc/cron.daily/ ไม่ว่าแบบใด ค่า daily หรือ weekly ในการตั้งค่าหมายถึงเงื่อนไขว่าไฟล์ถึงรอบแล้วหรือยัง ณ ตอนที่ logrotate ถูกเรียก

ขั้นตอนที่ 2: สร้างการตั้งค่าสำหรับ Log ของแอป

ตัวอย่างนี้ใช้แอปที่เขียน Log ไว้ที่ /var/www/example.com/storage/logs/*.log โดยไฟล์เป็นของผู้ใช้ deploy กลุ่ม www-data สร้างไฟล์ใหม่

sudo nano /etc/logrotate.d/example-app
/var/www/example.com/storage/logs/*.log {
    daily
    rotate 14
    maxsize 200M
    missingok
    notifempty
    compress
    delaycompress
    dateext
    su deploy www-data
    create 0664 deploy www-data
    sharedscripts
    postrotate
        systemctl reload php8.3-fpm > /dev/null 2>&1 || true
    endscript
}

ความหมายของแต่ละคำสั่ง

คำสั่งความหมาย
daily / weekly / monthlyรอบการหมุนเวียน
rotate 14เก็บไฟล์เก่าไว้ 14 ชุด เกินจากนี้ลบทิ้ง
maxsize 200Mหมุนก่อนถึงรอบถ้าไฟล์ใหญ่เกิน 200 MB (ตรวจเฉพาะตอนที่ logrotate ถูกเรียก)
missingokไม่ถือเป็น Error ถ้าไม่พบไฟล์
notifemptyไม่หมุนไฟล์ที่ว่าง
compress / delaycompressบีบอัดไฟล์เก่าด้วย gzip แต่เว้นไฟล์ล่าสุดไว้หนึ่งรอบ เผื่อแอปยังเขียนค้างอยู่
dateextต่อท้ายชื่อไฟล์ด้วยวันที่ เช่น app.log-20260919 แทนเลข .1 .2
su deploy www-dataทำงานในนามผู้ใช้และกลุ่มนี้ จำเป็นเมื่อโฟลเดอร์ไม่ได้เป็นของ root
create 0664 deploy www-dataสร้างไฟล์ใหม่ด้วยสิทธิ์และเจ้าของที่กำหนด
sharedscripts + postrotateรันคำสั่งหลังหมุนเพียงครั้งเดียวแม้จะมีหลายไฟล์

ปรับชื่อ Service ใน postrotate ให้ตรงกับเครื่อง บน AlmaLinux/Rocky ใช้ php-fpm และกลุ่ม Web Server มักเป็น apache หรือ nginx

ขั้นตอนที่ 3: เลือกระหว่าง postrotate กับ copytruncate

โปรแกรมที่เปิดไฟล์ Log ค้างไว้จะเขียนต่อลงไฟล์เดิมแม้ไฟล์จะถูกเปลี่ยนชื่อไปแล้ว จึงต้องบอกให้โปรแกรมเปิดไฟล์ใหม่ มี 2 วิธี

  • postrotate + reload: ส่งสัญญาณให้โปรแกรมเปิดไฟล์ใหม่ เช่น Nginx ใช้ kill -USR1 กับ Master Process ซึ่งไฟล์ /etc/logrotate.d/nginx ของแพ็กเกจทำไว้ให้แล้ว วิธีนี้ไม่ทำให้ Log หาย
  • copytruncate: คัดลอกไฟล์ไปเป็นไฟล์เก่า แล้วตัดไฟล์เดิมให้ว่าง ใช้กับโปรแกรมที่ไม่รองรับการเปิดไฟล์ใหม่ เช่น สคริปต์ที่เขียนด้วย >> แต่มีโอกาสสูญเสีย Log ไม่กี่บรรทัดที่เขียนระหว่างคัดลอก และต้องมีพื้นที่ว่างเท่าขนาดไฟล์ชั่วคราว

แอป PHP ส่วนใหญ่ เช่น Laravel เปิดและปิดไฟล์ทุกครั้งที่เขียน จึงไม่จำเป็นต้องมี postrotate ก็ได้ ถ้าไม่แน่ใจให้ใช้ copytruncate แทน create และ postrotate ห้ามใช้ copytruncate พร้อมกับ create

ขั้นตอนที่ 4: ทดสอบด้วยโหมด debug

sudo logrotate -d /etc/logrotate.d/example-app

-d แสดงว่า logrotate จะทำอะไรโดยไม่เปลี่ยนไฟล์จริง ผลที่คาดหวังคือบรรทัดอย่าง considering log /var/www/example.com/storage/logs/laravel.log ตามด้วย log does not need rotating หรือ log needs rotating ถ้ามี Error ของ Syntax จะแสดงตรงนี้

เมื่อผลถูกต้อง ให้บังคับหมุนหนึ่งครั้งเพื่อทดสอบจริง

sudo logrotate -v -f /etc/logrotate.d/example-app
ls -lh /var/www/example.com/storage/logs/

ควรเห็นไฟล์ Log ใหม่ขนาดเล็ก และไฟล์เก่าที่มีวันที่ต่อท้าย

หมายเหตุ: การรัน -f กับไฟล์ /etc/logrotate.conf ทั้งไฟล์จะบังคับหมุน Log ทุกตัวในระบบ ให้ทดสอบเฉพาะไฟล์การตั้งค่าของคุณเอง

ขั้นตอนที่ 5: ตัวอย่างการตั้งค่าอื่นที่ใช้บ่อย

Log ของสคริปต์ Cron ที่เขียนต่อท้ายไฟล์ ขนาดไม่แน่นอน เก็บไว้ 8 สัปดาห์

/var/log/backup-script.log {
    weekly
    rotate 8
    compress
    missingok
    notifempty
    copytruncate
}

Log ของ Nginx แยกตามเว็บไซต์ที่อยู่นอก /var/log/nginx/ ให้ใช้การตั้งค่าเดียวกับของแพ็กเกจ โดยคัดลอกบล็อก postrotate จาก /etc/logrotate.d/nginx มาใช้ เพื่อให้ส่งสัญญาณเปิดไฟล์ใหม่ด้วยวิธีเดียวกัน

สำหรับ Log ของ Docker Container ไม่ต้องใช้ logrotate ให้ตั้งค่าที่ Docker แทน ดู จำกัดขนาด Log ของ Docker Container

ตรวจสอบผลลัพธ์

sudo cat /var/lib/logrotate/status | grep example.com
du -sh /var/www/example.com/storage/logs/

บน AlmaLinux/Rocky ไฟล์สถานะอยู่ที่ /var/lib/logrotate/logrotate.status ไฟล์นี้บันทึกวันที่หมุนครั้งล่าสุดของแต่ละไฟล์ หลังผ่านไป 2-3 วัน ให้ตรวจว่ามีไฟล์ .gz เพิ่มขึ้นตามรอบ และขนาดรวมของโฟลเดอร์ไม่โตขึ้นเรื่อย ๆ

ปัญหาที่พบบ่อยเกี่ยวกับ logrotate

error: skipping ... because parent directory has insecure permissions

โฟลเดอร์ที่เก็บ Log เขียนได้โดยผู้ใช้ที่ไม่ใช่ root หรือเขียนได้โดยกลุ่ม logrotate จึงไม่ยอมทำงานเพื่อความปลอดภัย ให้เพิ่มคำสั่ง su ผู้ใช้ กลุ่ม ที่ตรงกับเจ้าของโฟลเดอร์ตามตัวอย่างในขั้นตอนที่ 2

หมุนแล้วแต่ df ยังแสดงว่าดิสก์เต็ม

โปรแกรมยังเปิดไฟล์เก่าที่ถูกลบค้างไว้ พื้นที่จึงยังไม่คืน ตรวจด้วย sudo lsof +L1 ถ้าพบไฟล์ที่มีคำว่า (deleted) ให้ reload หรือ restart Service นั้น แล้วปรับการตั้งค่าให้มี postrotate หรือ copytruncate การหาไฟล์ใหญ่อื่น ๆ ดูที่ ดิสก์เต็ม: ตรวจสอบพื้นที่และหาไฟล์ขนาดใหญ่บน Linux

แอปเขียน Log ไม่ได้หลังหมุน (Permission denied)

ไฟล์ใหม่ถูกสร้างด้วยเจ้าของหรือสิทธิ์ที่แอปเขียนไม่ได้ แก้ค่า create ให้ตรงกับผู้ใช้ที่แอปรันอยู่ ตรวจด้วย ls -l และอ่านเรื่องสิทธิ์ใน ทำความเข้าใจสิทธิ์ไฟล์บน Linux ด้วย chmod และ chown

Log ไม่หมุนเลยแม้ถึงรอบ

ตรวจว่า timer หรือ cron ของ logrotate ทำงานอยู่ด้วย systemctl status logrotate.timer และดูผลการรันล่าสุดด้วย sudo journalctl -u logrotate ถ้ามีไฟล์การตั้งค่าใดไฟล์หนึ่งผิด Syntax อาจทำให้รอบนั้นแจ้ง Error ทั้งรอบได้

หากทำตามขั้นตอนแล้วยังติดปัญหา สามารถติดต่อทีมงาน THAI DATA CLOUD ได้ที่ https://thaidata.cloud/contact/ โดยแจ้งชื่อเซิร์ฟเวอร์ ระบบปฏิบัติการ คำสั่งที่ใช้ และข้อความ Error ที่พบ เพื่อให้ตรวจสอบได้รวดเร็วขึ้น

อ่านเพิ่มเติมเกี่ยวกับ logrotate

แชร์FacebookXLINELinkedIn

มีคำถามเรื่องบริการ? ติดต่อทีมงาน