คำตอบสั้น ๆ: ตั้งค่า 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