1. ทำไม VPS disk ถึงเต็มโดยไม่รู้ตัว?
VPS ที่รันมาสักพักมักเจอปัญหา disk full โดยไม่ทันตั้งตัว เนื่องจากมีหลายแหล่งที่สะสมพื้นที่อย่างเงียบๆ ทั้ง access log ของ web server ที่เติบโตขึ้นทุกวัน, package cache ที่ดาวน์โหลดสะสมไว้, database binary log ที่ไม่ถูกล้าง, หรือ Docker image เก่าที่ไม่ได้ใช้แล้ว
ผลที่ตามมาเมื่อดิสก์เต็มมักรุนแรงกว่าที่คิด:
| บริการ | อาการเมื่อ disk full | ความรุนแรง |
|---|---|---|
| Nginx / Apache | ตอบกลับ HTTP 500 ไม่สามารถเขียน log | 🔴 สูง |
| MySQL / MariaDB | Crash, ไม่สามารถ commit transaction | 🔴 สูง |
| Mail Server | ไม่รับ/ส่งอีเมล, queue เต็ม | 🟠 กลาง |
| PHP-FPM | session write ล้มเหลว, PHP error | 🟠 กลาง |
| Cron Jobs | ไม่สามารถสร้าง temp file เพื่อรัน | 🟡 ต่ำ |
2. ตรวจสอบพื้นที่ดิสก์ขั้นแรก
เริ่มต้นด้วยการดูภาพรวมพื้นที่ดิสก์ทั้งหมดก่อนเสมอ:
# ดูพื้นที่ทั้งหมดแบบ human-readable
df -h
# ดูเฉพาะ disk หลัก (ไม่รวม tmpfs)
df -h --type=ext4 --type=xfs
# ดู inode (บางทีไฟล์เล็กเยอะมากทำให้ inode หมดก่อน)
df -i
ผลลัพธ์ตัวอย่างที่ควรสังเกต:
Filesystem Size Used Avail Use% Mounted on
/dev/vda1 50G 47G 3.0G 94% /
tmpfs 1.9G 1.2M 1.9G 1% /dev/shm
df -i ตรวจด้วย ถ้า IUse% เกิน 90% ก็ต้องล้างไฟล์จำนวนมากโดยเฉพาะ
3. หาไฟล์และโฟลเดอร์ขนาดใหญ่
หลังรู้ว่าดิสก์เต็ม ขั้นตอนต่อไปคือหาว่าใครกินพื้นที่มากที่สุด:
วิธีที่ 1: du + sort (ไม่ต้องติดตั้งอะไรเพิ่ม)
# หา 20 ไดเรกทอรีที่ใหญ่ที่สุดจาก root
du -ah / --max-depth=3 2>/dev/null | sort -rh | head -20
# หาเฉพาะ /var ซึ่งมักเป็นตัวการ
du -sh /var/* 2>/dev/null | sort -rh | head -10
# หาไฟล์ขนาดใหญ่กว่า 100MB
find / -type f -size +100M -not -path "/proc/*" 2>/dev/null | xargs du -sh | sort -rh
วิธีที่ 2: ncdu (แนะนำ — ใช้งานง่าย)
# ติดตั้ง ncdu
apt install ncdu -y # Ubuntu/Debian
yum install ncdu -y # CentOS/RHEL
# สแกนและดู interactive
ncdu /
# หรือสแกนเฉพาะ /var
ncdu /var
/var/log — log ของ web server, mail, syslog/var/cache/apt — package ที่ดาวน์โหลดไว้/var/lib/mysql — binary log ของ MySQL/tmp — ไฟล์ชั่วคราว/home — ไฟล์ของ user/var/lib/docker — Docker image/volume
4. ล้าง Log Files อย่างปลอดภัย
Log files คือตัวการอันดับต้นๆ ที่ทำให้ดิสก์เต็ม ล้างได้อย่างปลอดภัยด้วยวิธีต่อไปนี้:
Nginx / Apache Log
# ดูขนาด log
ls -lh /var/log/nginx/
ls -lh /var/log/apache2/
# ล้างเนื้อหา (SAFE — ไม่ลบไฟล์ process ยังเปิดอยู่ได้)
> /var/log/nginx/access.log
> /var/log/nginx/error.log
> /var/log/apache2/access.log
> /var/log/apache2/error.log
# Reload service เพื่อให้เปิด file descriptor ใหม่
nginx -s reopen
# หรือ
systemctl reload nginx
System Log (/var/log)
# ดู log ขนาดใหญ่ใน /var/log
find /var/log -name "*.log" -size +50M | xargs ls -lh
# ล้าง journal log เก่ากว่า 7 วัน
journalctl --vacuum-time=7d
# หรือจำกัดขนาด journal ไม่เกิน 200MB
journalctl --vacuum-size=200M
# ล้าง syslog เก่า (rotate แล้ว)
find /var/log -name "*.gz" -mtime +30 -delete
find /var/log -name "*.1" -mtime +7 -delete
MySQL/MariaDB Binary Log
# ดู binary log ที่มี
ls -lh /var/lib/mysql/mysql-bin.*
# ลบ binary log เก่ากว่า 7 วัน (รันใน MySQL)
mysql -u root -p -e "PURGE BINARY LOGS BEFORE DATE_SUB(NOW(), INTERVAL 7 DAY);"
# หรือปิด binary log ถ้าไม่ได้ใช้ replication (แก้ใน /etc/mysql/mysql.conf.d/mysqld.cnf)
# skip-log-bin
> แทน
5. ล้าง apt/yum Package Cache
Package manager สะสม .deb หรือ .rpm ไว้หลังติดตั้งทุกครั้ง ล้างได้ปลอดภัย 100%:
Ubuntu / Debian (apt)
# ล้าง cache ทั้งหมด
apt clean
# ลบ package ที่ไม่ได้ใช้แล้ว (orphan)
apt autoremove -y
# ดูขนาด cache ก่อนล้าง
du -sh /var/cache/apt/archives/
# ล้างแบบ aggressive ทั้ง cache + lists
apt clean && apt autoclean
CentOS / RHEL / Rocky Linux (yum/dnf)
# ล้าง yum cache
yum clean all
# ล้าง dnf cache (CentOS 8+/Rocky)
dnf clean all
# ลบ package ไม่ใช้
dnf autoremove
| คำสั่ง | สิ่งที่ล้าง | พื้นที่ที่ได้คืนโดยเฉลี่ย |
|---|---|---|
apt clean | ไฟล์ .deb ใน cache | 200MB – 2GB |
apt autoremove | package ที่ไม่ได้ใช้ | 50MB – 500MB |
journalctl --vacuum-time=7d | system journal เก่า | 100MB – 1GB |
| Nginx log truncate | access/error log | 100MB – 10GB+ |
docker system prune | Docker ที่ไม่ใช้ | 1GB – 20GB+ |
6. ล้าง Temp Files และ Old Kernels
Temp Files
# ดูขนาด /tmp
du -sh /tmp/
# ล้างไฟล์ใน /tmp เก่ากว่า 7 วัน
find /tmp -type f -mtime +7 -delete
find /tmp -type d -empty -delete
# ล้าง /var/tmp เก่ากว่า 30 วัน
find /var/tmp -type f -mtime +30 -delete
Old Linux Kernels
# ดู kernel ที่ติดตั้งอยู่
dpkg --list | grep linux-image
# ดู kernel ปัจจุบัน (ห้ามลบอันนี้)
uname -r
# ลบ kernel เก่า (Ubuntu ทำให้อัตโนมัติ)
apt autoremove --purge -y
# หรือลบเฉพาะ kernel เก่าที่ระบุ
dpkg --purge linux-image-OLD-VERSION-generic
/var/lib/php/sessions/ ล้างได้ด้วย find /var/lib/php/sessions/ -type f -mtime +1 -delete
7. ล้าง Docker Images และ Volumes
ถ้า VPS ของคุณรัน Docker เป็นแหล่งที่กิน disk เยอะมากโดยเฉพาะ image เก่าที่ build ค้างไว้:
# ดูว่า Docker ใช้พื้นที่เท่าไหร่
docker system df
# ล้าง container ที่ stop + image ที่ไม่ใช้ + network + build cache
docker system prune -f
# ล้างทุกอย่างรวม volume (ระวัง! data จะหาย)
docker system prune -af --volumes
# ล้างเฉพาะ image ที่ไม่มี tag (dangling)
docker image prune -f
# ดู volume ที่ไม่มี container ใช้
docker volume ls -qf dangling=true | xargs -r docker volume rm
8. ตั้งค่า logrotate กันปัญหาซ้ำ
การแก้ครั้งเดียวไม่เพียงพอ ต้องตั้ง logrotate เพื่อหมุนเวียน log อัตโนมัติ:
# ดู config logrotate ของ nginx
cat /etc/logrotate.d/nginx
# สร้าง/แก้ config สำหรับ nginx
cat > /etc/logrotate.d/nginx << 'EOF'
/var/log/nginx/*.log {
daily
missingok
rotate 7
compress
delaycompress
notifempty
create 0640 www-data adm
sharedscripts
postrotate
nginx -s reopen
endscript
}
EOF
# ทดสอบว่า config ถูกต้อง
logrotate -d /etc/logrotate.d/nginx
# รัน logrotate ทันที (force)
logrotate -f /etc/logrotate.conf
ตั้ง Cron Job ล้าง apt cache อัตโนมัติ
# เปิด crontab
crontab -e
# เพิ่มบรรทัดนี้ (ล้าง cache ทุกวันอาทิตย์เที่ยงคืน)
0 0 * * 0 apt clean && apt autoremove -y >> /var/log/apt-cleanup.log 2>&1
# ล้าง journal ทุกวันตอนตี 2
0 2 * * * journalctl --vacuum-time=7d >> /var/log/journal-cleanup.log 2>&1
rotate 14 เก็บ 14 วัน, compress บีบอัด .gz, daily หมุนทุกวัน — ช่วยลดพื้นที่ได้ 70-90% เมื่อเทียบกับไม่ตั้งค่าเลย
9. Monitor ดิสก์ก่อนเต็ม
วิธีที่ดีที่สุดคือรู้ก่อนดิสก์จะเต็ม ด้วยการตั้ง alert:
Script Alert ง่ายๆ ผ่าน Email
#!/bin/bash
# /usr/local/bin/disk-alert.sh
THRESHOLD=80
DISK_USAGE=$(df / | awk 'NR==2 {print $5}' | tr -d '%')
if [ "$DISK_USAGE" -gt "$THRESHOLD" ]; then
echo "WARNING: Disk usage is ${DISK_USAGE}% on $(hostname)" | \
mail -s "Disk Alert: ${DISK_USAGE}% used" [email protected]
fi
# ตั้ง cron ตรวจทุก 6 ชั่วโมง
0 */6 * * * /usr/local/bin/disk-alert.sh
ใช้ Netdata (แนะนำ)
# ติดตั้ง Netdata
bash <(curl -Ss https://my-netdata.io/kickstart.sh)
# เข้าดูที่ http://YOUR_IP:19999
# ตั้ง alert ใน /etc/netdata/health.d/
| เครื่องมือ | ข้อดี | ข้อเสีย |
|---|---|---|
| df + cron script | เบา ไม่ต้องติดตั้งเพิ่ม | แจ้งเตือนอย่างเดียว ไม่ visual |
| Netdata | Dashboard สวย real-time | กิน RAM ~100MB |
| Prometheus + Grafana | ครบครัน historical data | ซับซ้อน ต้องใช้ Node Exporter |
| Zabbix | Alert รูปแบบหลากหลาย | ติดตั้งยาก |
10. คำถามที่พบบ่อย
du -ah / | sort -rh | head -20 เพื่อหา 20 ไฟล์/โฟลเดอร์ขนาดใหญ่ที่สุด หรือติดตั้ง ncdu แล้วรัน ncdu / สำหรับ interface แบบ visual ที่ navigate ได้สะดวกกว่า> /var/log/nginx/access.log แต่ห้ามลบไฟล์โดยตรงเพราะ process ยังถือ file descriptor อยู่ ควรใช้ logrotate หรือ truncate เพื่อความปลอดภัยapt clean หรือ apt autoremove ได้อย่างปลอดภัย หากต้องการติดตั้งใหม่ก็ดาวน์โหลดใหม่ได้เสมอdocker system prune -af เพื่อล้าง image, container, network และ cache ที่ไม่ได้ใช้งานทั้งหมด แต่ต้องระวังว่าจะลบ image ที่ stop อยู่ด้วยสรุป
การแก้ปัญหา VPS disk full ทำได้ใน 3 ขั้นตอนหลัก: (1) ตรวจสอบด้วย df -h และหาตัวการด้วย ncdu หรือ du (2) ล้างสิ่งที่ปลอดภัย ได้แก่ log เก่า, apt cache, temp files, Docker ที่ไม่ใช้ และ (3) ป้องกันซ้ำด้วย logrotate + cron + monitoring ถ้าดิสก์ยังไม่พอหลังล้างแล้ว อาจถึงเวลา upgrade แพ็กเกจ VPS ของคุณ
คำสั่งสรุปฉุกเฉิน (เมื่อ disk เต็มทันที):
apt clean && apt autoremove -y
journalctl --vacuum-time=3d
> /var/log/nginx/access.log
find /tmp -mtime +1 -delete
df -h # ตรวจผล