คำตอบสั้น ๆ: เข้าใจว่า WP-Cron ไม่ใช่ Cron จริงและทำงานเมื่อมีคนเข้าเว็บเท่านั้น แล้วเปลี่ยนไปใช้ Cron ของระบบเพื่อให้งานตามเวลาทำงานตรงและเว็บไม่หน่วง
คู่มือนี้อธิบาย WP-Cron ทีละขั้นตอน พร้อมคำสั่งที่ใช้ได้จริงและปัญหาที่พบบ่อย
หลายคนเข้าใจว่า WP-Cron คือระบบตั้งเวลาเหมือน Cron ของ Linux แต่ความจริงมันทำงานก็ต่อเมื่อมีคนเข้าเว็บเท่านั้น ผลที่ตามมาคือสองปัญหาที่ดูตรงข้ามกันแต่มาจากสาเหตุเดียว
เว็บที่มีคนเข้าน้อยจะมีงานค้างไม่ทำงาน เช่น การสำรองข้อมูลอัตโนมัติที่ไม่เคยรัน ส่วนเว็บที่มีคนเข้าเยอะจะหน่วง เพราะผู้เข้าชมบางคนต้องรอให้งานเบื้องหลังเสร็จก่อนที่หน้าเว็บจะโหลด
สิ่งที่ต้องเตรียม (WP-Cron)
- สิทธิ์แก้ไฟล์
wp-config.php - สิทธิ์ตั้ง Cron บนเซิร์ฟเวอร์ หรือ Scheduled Task บนแผงควบคุมโฮสติ้ง
- WP-CLI จะสะดวกที่สุด แต่ใช้ปลั๊กอิน WP Crontrol แทนได้
ขั้นตอนที่ 1: ดูงานที่ตั้งไว้ทั้งหมด
wp cron event list
ดูคอลัมน์ next_run_relative หากเห็นค่าเป็นลบหรือข้อความว่าเลยกำหนดมานาน แปลว่างานนั้นค้างไม่ได้ทำงาน
# นับงานที่เลยกำหนดแล้ว
wp cron event list --fields=hook,next_run_relative | grep -c 'ago'
# ดูตารางเวลาที่มี
wp cron schedule list
ตรวจว่าระบบทำงานได้หรือไม่
wp cron test
ขั้นตอนที่ 2: ปิด WP-Cron แล้วใช้ Cron จริง
nano /var/www/example.com/wp-config.php
เพิ่มก่อนบรรทัด /* That's all, stop editing! */
define('DISABLE_WP_CRON', true);
ตั้ง Cron ของระบบให้เรียกแทน
sudo crontab -u www-data -e
# เรียกทุก 5 นาที ผ่าน PHP โดยตรง ซึ่งเร็วกว่าและไม่กิน worker ของเว็บ
*/5 * * * * cd /var/www/example.com && /usr/bin/php wp-cron.php >/dev/null 2>&1
หรือเรียกด้วย WP-CLI ซึ่งให้การควบคุมที่ดีกว่าและบันทึกผลได้
*/5 * * * * cd /var/www/example.com && /usr/local/bin/wp cron event run --due-now --quiet >> /var/log/wp-cron.log 2>&1
อย่าเรียกผ่าน curl หรือ wget ไปที่ URL ของเว็บ เพราะจะใช้ worker ของ PHP-FPM ที่ควรเอาไว้บริการผู้ใช้จริง และหากเว็บมี Basic Auth หรืออยู่หลัง Cloudflare จะยิ่งซับซ้อน
ตรวจว่า Cron ทำงาน
sudo tail -f /var/log/wp-cron.log
wp cron event list | head
ขั้นตอนที่ 3: จัดการงานที่ค้างสะสม
# สั่งรันงานที่ถึงกำหนดทั้งหมดทันที
wp cron event run --due-now
# รันงานเฉพาะตัว
wp cron event run wp_scheduled_delete
หากมีงานค้างจำนวนมากจนรันทีเดียวไม่ไหว ให้ทยอยรัน และตรวจว่างานนั้นยังจำเป็นหรือไม่
ขั้นตอนที่ 4: ลบงานของปลั๊กอินที่ถอนไปแล้ว
ปลั๊กอินจำนวนมากไม่ล้างงานของตัวเองตอนถอนการติดตั้ง ทำให้มีงานที่ชี้ไปยังฟังก์ชันที่ไม่มีอยู่จริง ซึ่งสร้างข้อผิดพลาดใน Log ทุกครั้งที่ถึงกำหนด
# ดูรายชื่อ hook ทั้งหมด
wp cron event list --fields=hook | sort | uniq -c | sort -rn
# ลบงานของ hook ที่ไม่ใช้แล้ว
wp cron event delete ชื่อ_hook_ของปลั๊กอินเก่า
ตรวจว่า hook นั้นมีโค้ดรองรับอยู่จริงหรือไม่
grep -rn "ชื่อ_hook" /var/www/example.com/wp-content/plugins/ | head
หากไม่พบอะไรเลย แปลว่าเป็นงานกำพร้าและลบได้อย่างปลอดภัย