Vấn đề
Bạn lên lịch đăng bài lúc 9:00 sáng. Chín giờ đến rồi qua đi. Bài vẫn nằm im ở trạng thái "Scheduled" — không có thông báo, không có lỗi, chỉ là im lặng. Refresh trang admin cũng không ăn thua. Bài bị kẹt.
Hầu như mỗi lần gặp tình trạng này, thủ phạm đều là một: wp-cron.
Nguyên nhân gốc rễ
WordPress không dùng cron hệ thống thực sự. Thay vào đó, nó có bộ lập lịch giả riêng gọi là WP-Cron (wp-cron.php), chịu trách nhiệm xuất bản bài, gửi email, chạy công việc plugin và các tác vụ theo thời gian khác. Vấn đề nằm ở chỗ: nó chỉ chạy khi có người truy cập vào site. Không có khách, không có cron nào được kích hoạt.
Thiết kế này hoạt động ổn trên những site đông khách. Nhưng sẽ gặp sự cố trong các trường hợp sau:
DISABLE_WP_CRONđược đặt thànhtruetrongwp-config.php— cực kỳ phổ biến trên các host quản lý hoặc sau khi làm theo hướng dẫn "tối ưu hiệu suất"- Site ít traffic — một blog chỉ có 50 lượt truy cập mỗi ngày có thể mất nhiều giờ giữa các lần kích hoạt cron
- Cấu hình Nginx hoặc tường lửa chặn các yêu cầu HTTP loopback (server không thể tự gọi chính mình)
- Một plugin gây ra lỗi PHP nghiêm trọng khiến quá trình thực thi bị dừng trước khi cron kịp chạy
Bước 1: Kiểm tra xem DISABLE_WP_CRON có được đặt không
Mở wp-config.php và tìm dòng này:
define('DISABLE_WP_CRON', true);
Tìm thấy rồi? Đó chính là vấn đề. Hãy xóa dòng đó đi, hoặc đổi thành false:
define('DISABLE_WP_CRON', false);
Lưu file lại. Tạo một bài kiểm tra được lên lịch sau 2–3 phút và xem thử nó có được đăng đúng giờ không.
Bước 2: Kiểm tra WP-Cron thủ công
Trước khi nghĩ đến điều tệ nhất, hãy kích hoạt wp-cron trực tiếp để xem chuyện gì xảy ra:
# Qua WP-CLI (khuyến nghị)
wp cron event run --due-now
# Hoặc truy cập URL này trực tiếp trên trình duyệt
https://yourdomain.com/wp-cron.php?doing_wp_cron
Nếu WP-CLI báo lỗi, hoặc URL đó trả về mã khác 200, có nghĩa là có thứ gì đó đang chặn các yêu cầu loopback.
Kiểm tra kết nối Loopback
# Chạy lệnh này ngay trên server
curl -I https://yourdomain.com/wp-cron.php
Nếu bị từ chối kết nối hoặc timeout, server không thể tự gửi yêu cầu HTTP đến chính mình. Điều này thường xảy ra trên một số cấu hình VPS và đằng sau reverse proxy với quy tắc tường lửa nghiêm ngặt.
Bước 3: Thay thế WP-Cron bằng cron hệ thống thực sự
Cron kích hoạt theo lượt truy cập vốn đã không đáng tin cậy. Trên bất kỳ site production nào phụ thuộc vào lịch đăng bài, hãy bỏ nó đi và dùng cron hệ thống thay thế. Đặt DISABLE_WP_CRON thành true, rồi tự thiết lập cron hệ thống.
3a. Tắt WP-Cron tích hợp sẵn
// Trong wp-config.php
define('DISABLE_WP_CRON', true);
3b. Thêm Cron Job hệ thống
Chỉnh sửa crontab của bạn:
crontab -e
Chọn một trong các cách dưới đây — chạy mỗi 5 phút là điểm cân bằng tốt giữa độ phản hồi và tải server:
# Cách 1: PHP trực tiếp (đơn giản nhất)
*/5 * * * * php /var/www/html/wp-cron.php > /dev/null 2>&1
# Cách 2: WP-CLI (đáng tin cậy hơn, hỗ trợ multisite)
*/5 * * * * cd /var/www/html && wp cron event run --due-now --quiet
# Cách 3: wget/curl (hữu ích nếu đường dẫn PHP thay đổi)
*/5 * * * * wget -q -O - https://yourdomain.com/wp-cron.php?doing_wp_cron >/dev/null 2>&1
Trên cPanel
Vào cPanel → Cron Jobs, đặt chu kỳ mỗi 5 phút và nhập:
php /home/yourusername/public_html/wp-cron.php > /dev/null 2>&1
Bước 4: Xuất bản thủ công các bài đang bị kẹt
Các bài đã bị kẹt ở trạng thái "Scheduled" sẽ không tự phục hồi sau khi cron hoạt động trở lại — chúng cần được xử lý thêm. WP-CLI giải quyết việc này gọn gàng:
# Xem những bài nào đang bị kẹt
wp post list --post_status=future --fields=ID,post_title,post_date
# Xuất bản một bài cụ thể (thay 123 bằng ID thực tế)
wp post update 123 --post_status=publish
Cần xử lý hàng loạt?
wp post list --post_status=future --format=ids | xargs wp post update --post_status=publish
Kiểm tra ngày tháng trước. Lệnh này sẽ xuất bản ngay tất cả bài ở trạng thái "future" — kể cả những bài được lên lịch hợp lệ cho tuần sau.
Bước 5: Kiểm tra plugin đang chặn Cron
Các plugin bảo mật thường là thủ phạm. Wordfence và iThemes Security đều có tùy chọn chặn truy cập trực tiếp vào wp-cron.php — hãy kiểm tra cài đặt của chúng trong mục quy tắc tường lửa hoặc tùy chọn "disable WP-Cron".
Để cô lập vấn đề, hãy tắt tất cả plugin rồi kiểm tra:
wp plugin deactivate --all
wp cron event run --due-now
Nếu lúc đó hoạt động được, hãy kích hoạt lại từng plugin một cho đến khi vấn đề xuất hiện trở lại. Plugin cuối cùng bạn kích hoạt chính là thủ phạm.
Xác nhận đã sửa xong
- Tạo bài mới và lên lịch đăng sau 2–3 phút
- Chờ đến thời điểm đó
- Refresh danh sách bài — bài phải hiển thị trạng thái "Published"
Bạn cũng có thể kiểm tra hàng đợi cron trực tiếp:
# Liệt kê các sự kiện sắp tới
wp cron event list
# Xem thời điểm các sự kiện được lên lịch tiếp theo
wp cron event list --fields=hook,next_run_relative
Phòng ngừa
- Dùng cron hệ thống thực sự trên bất kỳ site nào mà thời điểm đăng bài quan trọng — WP-Cron ổn cho môi trường phát triển, nhưng không phù hợp cho production
- Cài WP Crontrol khi debug. Plugin này hiển thị toàn bộ sự kiện được lên lịch trong một bảng dễ đọc và cho phép kích hoạt thủ công ngay từ trang admin WordPress
- Sau khi chuyển sang server hoặc host mới, hãy xác nhận cron đang hoạt động trước khi site ra mắt. Một bài kiểm tra lên lịch sau 5 phút sẽ cho bạn biết ngay lập tức
- Các tác vụ được lên lịch với khối lượng lớn (email WooCommerce, xuất dữ liệu hàng loạt) sẽ hoạt động tốt hơn với Action Scheduler, vốn bổ sung tính năng quản lý hàng đợi và logic thử lại trên nền WP-Cron

