ลดความยุ่งยากในการใช้คลาวด์ พูดคุยกับเจ้าหน้าที่

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

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

ไฟล์ 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 เพิ่มขึ้นตามรอบ และขนาดรวมของโฟลเดอร์ไม่โตขึ้นเรื่อย ๆ

ปัญหาที่พบบ่อย

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 ที่พบ เพื่อให้ตรวจสอบได้รวดเร็วขึ้น

ผู้ให้บริการคลาวด์ไทย
เพื่อธุรกิจของคนไทย

"มุ่งมั่น" และ "มั่นคง"
พร้อมรับมือทุกการเติบโต
Trust Cloud
คลาว์ที่ปลอดภัย
คือรากฐานที่มั่นคง
cloud security