SSD Nodes Learn 🎉 VPS از $5.50/ماه
راهنماها Matt Connorتوسط Matt Connor · به‌روزرسانی شده 2026-08-13

غیرفعال کردن WP-Cron و تنظیم System Cron در وردپرس

سیستم WP-Cron تنها با بازدید کاربران اجرا می‌شود که باعث کندی یا تداخل در سایت است. با استفاده از WP-CLI و تنظیم یک crontab دقیق، اجرای وظایف را بهینه و تضمین کنید.

wp-cron چیست و چرا system cron جایگزین آن می‌شود

WP-Cron زمان‌بند وظایف داخلی در WordPress است که تنها زمانی اجرا می‌شود که شخصی درخواستی برای یک صفحه ارسال کند. هیچ فرآیندی در داخل WordPress به‌صورت خودکار فعال نمی‌شود. در هر درخواستی که از حافظه کش (cache) پاسخ داده نشود، WordPress لیستی از وظایف زمان‌بندی‌شده را می‌خواند و اگر موعد اجرای یکی از آن‌ها فرا رسیده باشد، یک درخواست HTTP دوم به آدرس /wp-cron.php برای خودش ارسال می‌کند تا آن وظیفه را انجام دهد. انتقال این وظیفه به system cron باعث می‌شود که اجرای آن در یک زمان‌بندی ثابت و قابل پیش‌بینی انجام شود، فارغ از اینکه سایت در آن لحظه هزار بازدیدکننده داشته باشد یا هیچ بازدیدی نداشته باشد.

دو خط کد، وظیفه اصلی را انجام می‌دهند: یک ثابت (constant) در فایل wp-config.php و یک ورودی در crontab. تمام موارد دیگر در این راهنما، جزئیاتی هستند که آن دو خط کد به شما نمی‌گویند. اینکه وظیفه باید با چه کاربری اجرا شود، چگونه می‌توان اثبات کرد که رویدادهای زمان‌بندی‌شده واقعاً اجرا شده‌اند، و سه روشی که این تنظیمات ممکن است بدون نمایش هیچ خطایی در سایت، با شکست مواجه شوند.

مثال‌ها از /srv/www/example.com به‌عنوان دایرکتوری WordPress و از www-data به‌عنوان کاربر وب‌سرور استفاده می‌کنند. در همه جا، مسیرها و نام کاربری خود را جایگزین کنید.

کدام بازدیدکننده باعث اجرای cron در یک سایت پربازدید می‌شود

هر درخواست بدون کش (uncached)، هزینه بررسی را پرداخت می‌کند. وردپرس گزینه cron را بارگذاری کرده، برچسب‌های زمانی را مقایسه می‌کند و هنگامی که موعد کاری فرا برسد، spawn_cron() را فراخوانی می‌کند که یک درخواست loopback غیرمسدودکننده به /wp-cron.php می‌فرستد. بازدیدکننده منتظر نتیجه نمی‌ماند، اما یک worker در PHP منتظر می‌ماند. در یک VPS کوچک که PHP-FPM را با pm.max_children = 5 اجرا می‌کند، یک کار زمان‌بندی‌شدهٔ کند، یک‌پنجم ظرفیت PHP شما را تا زمانی که طول بکشد اشغال می‌کند و احتمال وقوع آن در شلوغ‌ترین دقیقه شما بیشتر است، زیرا در آن زمان بیشترین بارگذاری صفحه رخ می‌دهد.

وردپرس تعداد موارد تکراری را محدود می‌کند. این سیستم یک قفل با طول عمر WP_CRON_LOCK_TIMEOUT (به‌طور پیش‌فرض 60 ثانیه) ایجاد می‌کند تا بازدیدکنندگان همزمان، هر کدام یک اجرای جدید را شروع نکنند. این قفل فقط از تکرار جلوگیری می‌کند، اما کار را از مسیر درخواست خارج نمی‌کند.

پیش از آنکه تصمیم بگیرید این موضوع اهمیت دارد یا خیر، تعداد دفعات اجرای آن را روی سرور خود بشمارید. هر درخواست loopback در لاگ دسترسی وب‌سرور ظاهر می‌شود:

sudo grep -c 'wp-cron.php' /var/log/nginx/access.log

آپاچی به‌جای آن در /var/log/apache2/access.log می‌نویسد. تعداد هزاران درخواست در روز یک هزینه واقعی است و این عددی است که باید به‌جای خواندن در مقالات، روی سرور خودتان اندازه‌گیری کنید؛ همان‌طور که پیش و پس از هر تغییر دیگری، یک VPS را بنچمارک می‌کنید.

کش کردن، وضعیت را تغییر می‌دهد. اگر یک کش صفحه، اکثر درخواست‌ها را به‌عنوان HTML ایستا پاسخ دهد، PHP برای آن درخواست‌ها هرگز اجرا نمی‌شود و در نتیجه بررسی cron هرگز اتفاق نمی‌افتد. یک سایت پربازدید که به‌شدت کش شده باشد، شروع به رفتاری مشابه سایت‌های کم‌ترافیک (که در ادامه آمده) می‌کند.

چرا بازدیدکنندگان باعث اختلال در cron در سایت‌های کم‌بازدید می‌شوند

نبود بازدیدکننده به معنای نبود cron است. سایتی که در روز تنها چند بازدید دارد، کارهای زمان‌بندی‌شده‌اش را نیز تنها چند بار در روز و در لحظات تصادفی ورود بازدیدکنندگان اجرا می‌کند.

علائم این مشکل همگی مشابه هستند. پستی که برای ساعت 09:00 زمان‌بندی شده است، تا زمانی که کسی صفحه‌ای را بارگذاری نکند، در لیست پست‌ها با وضعیت Missed schedule باقی می‌ماند. افزونه‌های پشتیبان‌گیری، کارهای شبانه را انجام نمی‌دهند. بررسی به‌روزرسانی‌ها با تأخیر مواجه می‌شود، بنابراین در حالی که یک نسخه امنیتی جدید منتشر شده است، پیشخوان (dashboard) هیچ موردی برای به‌روزرسانی نشان نمی‌دهد. ایمیل‌های سفارش، اعلان‌های تمدید و هشدارهای انقضا با تأخیر ارسال می‌شوند.

هیچ‌کدام از این موارد خطایی ثبت نمی‌کنند. از دیدگاه WordPress، کار هرگز دیر نشده است، زیرا اصلاً شروع نشده بود.

گام 1: غیرفعال‌سازی محرک بازدیدکننده در wp-config.php

فایل /srv/www/example.com/wp-config.php را باز کرده و ثابت زیر را به آن اضافه کنید:

define( 'DISABLE_WP_CRON', true );

این ثابت را بالای خطی که شامل /* That's all, stop editing! Happy publishing. */ است قرار دهید؛ زیرا خطی که بلافاصله پس از آن کامنت قرار دارد به wp-settings.php نیاز دارد و wp-settings.php جایی است که وردپرس بررسی cron را به init متصل می‌کند. ثابتی که پس از آن require تعریف شود، بسیار دیر اعمال می‌شود و هیچ تغییری ایجاد نمی‌کند؛ در نتیجه با وجود اینکه فایل از نظر ظاهری درست به نظر می‌رسد، محرک همچنان به اجرا ادامه می‌دهد.

تأیید کنید که این خط در جای درست قرار گرفته است:

grep -n "DISABLE_WP_CRON\|stop editing" /srv/www/example.com/wp-config.php

این ثابت مانع از زمان‌بندی رویدادها نمی‌شود. افزونه‌ها همچنان وظایف را طبق روال قبل به صف اضافه می‌کنند. این تنظیم فقط مانع از اجرای صف توسط بارگذاری صفحات می‌شود؛ به این معنی که صف تا زمانی که گام 3 را به پایان نرسانید، هرگز اجرا نخواهد شد.

این کار همچنین مانع از درخواست‌های مستقیم به /wp-cron.php نمی‌شود. هر کسی همچنان می‌تواند این URL را درخواست کند و این موضوع معمولاً بی‌خطر است، زیرا فایل فقط وظایف سررسید شده را اجرا می‌کند. مسدود کردن آن در تنظیمات وب‌سرور اختیاری است. اگر آن را مسدود کنید، مکانیزم جایگزین curl که در انتهای این راهنما آمده است نیز از کار می‌افتد.

گام 2: نصب WP-CLI

ابزار WP-CLI رابط خط فرمان رسمی برای WordPress است. این ابزار به باینری خط فرمان PHP نیاز دارد که بسته‌ای مجزا از ماژول PHP وب‌سرور است.

php -v
sudo apt install -y php-cli

ابزار WP-CLI را از طریق فایل phar نصب کنید؛ این روشی است که راهنمای نصب رسمی توصیه می‌کند:

cd /tmp
curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
php wp-cli.phar --info
chmod +x wp-cli.phar
sudo mv wp-cli.phar /usr/local/bin/wp
wp --info

دستور php wp-cli.phar --info مسیر باینری PHP، نسخه PHP و نسخه WP-CLI را چاپ می‌کند. اگر هر سه مورد نمایش داده شوند، فایل phar به‌درستی کار می‌کند. تا اوت 2026، راهنمای نصب، نسخه PHP 7.2.24 را به عنوان حداقل نیاز اعلام کرده است و از آنجا که Ubuntu 24.04 با PHP 8.3 عرضه می‌شود، سرورهای امروزی به‌راحتی از این محدودیت عبور می‌کنند. برای به‌روزرسانی در آینده از sudo wp cli update استفاده کنید.

ابزار WP-CLI را با کاربرِ سایت اجرا کنید و هرگز آن را با کاربر root اجرا نکنید:

sudo -u www-data /usr/local/bin/wp --path=/srv/www/example.com core version

در صورت اجرا با کاربر root، ابزار WP-CLI از شروع کار خودداری می‌کند:

Error: YIKES! It looks like you're running this as root.

این ابزار استفاده از --allow-root را پیشنهاد می‌دهد. در اینجا از این گزینه استفاده نکنید. دلیل آن در اولین حالت خطا در ادامه توضیح داده شده است.

همچنین توجه داشته باشید که sudo -u www-data -i کار نمی‌کند، زیرا shell ورود آن حساب کاربری /usr/sbin/nologin است و شما با خطای This account is currently not available. مواجه می‌شوید. ارسال مستقیم دستور به sudo -u باعث نادیده گرفتن shell ورود می‌شود و در نتیجه دستور به‌درستی اجرا می‌گردد.

اکنون تأیید کنید که خودِ WordPress مقدار ثابت (constant) تعریف‌شده در گام 1 را شناسایی می‌کند:

sudo -u www-data /usr/local/bin/wp --path=/srv/www/example.com eval 'var_dump( DISABLE_WP_CRON );'

این دستور مقدار bool(true) را چاپ می‌کند. بروز خطای مهلک (fatal error) مبنی بر تعریف‌نشده بودن ثابت، به این معناست که خط define() اجرا نمی‌شود؛ که معمولاً نشان‌دهنده قرار گرفتن آن در زیر دستور require است.

گام 3: افزودن ورودی cron با کاربر صحیح

کاربر صحیح، همان کاربری است که مالک فایل‌هایی است که PHP می‌نویسد. هر دو سمت را بررسی کنید:

stat -c '%U %G' /srv/www/example.com/wp-content/uploads
grep -E '^(user|group) = ' /etc/php/8.3/fpm/pool.d/www.conf

در نصب پیش‌فرض Ubuntu، هر دو پاسخ www-data را برمی‌گردانند. اگر برای سایت خود یک pool اختصاصی PHP-FPM با کاربر مخصوص به آن ایجاد کرده‌اید—که در تنظیمات هر سایت روی یک LAMP stack روی Ubuntu 24.04 معمولاً به همین صورت انجام می‌شود—از همان کاربر برای تمام مراحل زیر استفاده کنید.

یک دایرکتوری لاگ بسازید که آن کاربر بتواند در آن بنویسد:

sudo install -d -o www-data -g www-data -m 750 /var/log/wp-cron

فایل crontab آن کاربر را ویرایش کنید:

sudo crontab -u www-data -e

یک خط زیر را اضافه کنید:

*/5 * * * * /usr/bin/flock -n /run/lock/wp-cron-example.lock /usr/local/bin/wp --path=/srv/www/example.com cron event run --due-now >> /var/log/wp-cron/example.log 2>&1

تکه‌به‌تکه بررسی می‌کنیم. */5 دستور را هر پنج دقیقه اجرا می‌کند. flock -n از یک فایل قفل (lock file) استفاده می‌کند و اگر اجرای قبلی هنوز در حال انجام باشد، بلافاصله متوقف می‌شود. /usr/local/bin/wp مسیر مطلق است که cron به آن نیاز دارد. --path اجازه می‌دهد دستور از هر دایرکتوری کاری اجرا شود. --due-now فقط رویدادهایی را اجرا می‌کند که زمانشان فرا رسیده است، نه تمام رویدادهای موجود در صف. تغییر مسیر (redirect) خروجی عادی و خطاها را به فایلی می‌فرستد که می‌توانید آن را بخوانید.

این تغییر مسیر در عمل اختیاری نیست. Cron خروجی یک job را به کاربر مربوطه ایمیل می‌کند، اکثر ایمیج‌های VPS هیچ عامل انتقال ایمیلی (MTA) نصب ندارند و در نتیجه cron خطای (CRON) info (No MTA installed, discarding output) را ثبت کرده و خروجی را دور می‌ریزد. یک فایل، شواهد را حفظ می‌کند.

فایل ذخیره‌شده را بررسی کنید:

sudo crontab -u www-data -l

برای چندین سایت، برای هر کدام یک خط با دقایق متفاوت بنویسید تا همگی هم‌زمان شروع نشوند:

*/5 * * * * /usr/bin/flock -n /run/lock/wp-cron-one.lock /usr/local/bin/wp --path=/srv/www/one.example.com cron event run --due-now >> /var/log/wp-cron/one.log 2>&1
2-59/5 * * * * /usr/bin/flock -n /run/lock/wp-cron-two.lock /usr/local/bin/wp --path=/srv/www/two.example.com cron event run --due-now >> /var/log/wp-cron/two.log 2>&1

این لاگ تا ابد رشد می‌کند مگر اینکه آن را چرخش (rotate) دهید. فایل /etc/logrotate.d/wp-cron را بنویسید:

/var/log/wp-cron/*.log {
    weekly
    rotate 4
    missingok
    notifempty
    compress
    create 640 www-data www-data
}

بررسی کنید که فایل بدون ایجاد تغییر، تحلیل (parse) شود: sudo logrotate --debug /etc/logrotate.d/wp-cron.

گام 4: تأیید اجرای رویدادهای زمان‌بندی‌شده

ذخیره شدن موفقیت‌آمیز یک خط در crontab به معنای اجرای آن نیست. از ارزان‌ترین روش بررسی شروع کنید و به سراغ روشی بروید که وضعیت را به‌طور قطعی مشخص می‌کند.

نخست، آیا cron دستور را اجرا کرده است؟ Cron لاگ‌های خود را در journal تحت واحد اختصاصی‌اش ثبت می‌کند:

journalctl -u cron.service --since "15 min ago" | grep wp

یک ورودی سالم به این شکل است (زمان و نام میزبان از ابتدای آن حذف شده‌اند):

CRON[24913]: (www-data) CMD (/usr/bin/flock -n /run/lock/wp-cron-example.lock /usr/local/bin/wp --path=/srv/www/example.com cron event run --due-now >> /var/log/wp-cron/example.log 2>&1)

این خط نشان می‌دهد که cron دستور شما را با کاربر www-data اجرا کرده است. این خروجی هیچ اطلاعاتی درباره موفقیت‌آمیز بودن اجرای دستور نمی‌دهد.

دوم، آیا WordPress چیزی اجرا کرده است؟ فایل لاگ را بخوانید:

sudo tail -n 20 /var/log/wp-cron/example.log

WP-CLI برای هر رویداد یک خط و در نهایت یک جمع‌بندی چاپ می‌کند:

Executed the cron event 'wp_version_check' in 0.418s.
Success: Executed a total of 2 cron events.

خطاها در همان فایل ثبت می‌شوند که هدف اصلی 2>&1 است. در بیشتر اجراها، رویدادی برای پردازش وجود ندارد و فایل تغییر چندانی نمی‌کند؛ بنابراین فایل را پس از زمانی که می‌دانید کاری برای انجام دادن وجود دارد، بررسی کنید.

سوم، اجرای کامل (end-to-end) را اثبات کنید. یک رویداد نشانگر (marker event) زمان‌بندی کنید و ناپدید شدن آن را زیر نظر بگیرید:

sudo -u www-data /usr/local/bin/wp --path=/srv/www/example.com cron event schedule wp_cli_cron_check now
sudo -u www-data /usr/local/bin/wp --path=/srv/www/example.com cron event list --fields=hook,next_run_relative --format=csv | grep wp_cli_cron_check

یک بازه زمانی صبر کنید و سپس دستور لیست کردن را دوباره اجرا کنید. اگر hook حذف شده باشد، یعنی رویداد یک‌باره (one-off) پس از اجرا از صف پاک شده است. هیچ افزونه‌ای callback روی آن نام hook ثبت نکرده است، بنابراین اجرای آن تأثیر دیگری روی سایت ندارد. اگر پس از دو بازه زمانی، hook همچنان در لیست باشد، یعنی صف پردازش نمی‌شود. دو بررسی اول به شما می‌گویند که مشکل از cron است یا WP-CLI.

برای این کار از wp cron test استفاده نکنید. این دستور بررسی می‌کند که آیا فراخوانی توسط بازدیدکننده (visitor triggered spawning) کار می‌کند یا خیر، و زمانی که DISABLE_WP_CRON فعال باشد، خطا می‌دهد. در سروری که به‌درستی پیکربندی شده باشد، این خطا خروجی مورد انتظار است، نه یک نقص فنی.

جایگزین systemd timer

اگر سایر کارهای زمان‌بندی‌شدهٔ سرور شما از قبل به صورت systemd services and timers اجرا می‌شوند، وردپرس را نیز به همان‌جا منتقل کنید. در این صورت، هر اجرا در systemctl list-timers نمایش داده می‌شود و خروجی به‌جای فایلی که نیاز به چرخش (rotate) داشته باشد، به journal ارسال می‌گردد.

فایل /etc/systemd/system/wp-cron-example.service را بنویسید:

[Unit]
Description=Run due WordPress cron events for example.com

[Service]
Type=oneshot
User=www-data
Group=www-data
ExecStart=/usr/local/bin/wp --path=/srv/www/example.com cron event run --due-now

سپس /etc/systemd/system/wp-cron-example.timer را ایجاد کنید:

[Unit]
Description=Run WordPress cron for example.com every 5 minutes

[Timer]
OnCalendar=*:0/5
AccuracySec=30s
Persistent=true

[Install]
WantedBy=timers.target
sudo systemctl daemon-reload
sudo systemctl enable --now wp-cron-example.timer
systemctl list-timers wp-cron-example.timer
journalctl -u wp-cron-example.service -n 20

Systemd اجازه نمی‌دهد دو نسخه از یک سرویس به‌طور هم‌زمان اجرا شوند، بنابراین این نسخه نیازی به flock ندارد. گزینه Persistent=true باعث می‌شود اگر در زمان خاموش بودن دستگاه اجرایی از دست رفته باشد، سیستم آن را جبران کند؛ کاری که در crontab امکان‌پذیر نیست.

یکی از دو روش crontab یا timer را انتخاب کنید. اجرای هم‌زمان هر دو برای یک سایت به این معناست که صف پردازش دو بار تخلیه می‌شود و اجرای تکراری کارهای مربوط به ایمیل یا سفارش برای مشتریان شما قابل مشاهده خواهد بود.

چرا cron job نباید با کاربر root اجرا شود

این اولین مورد از سه روشی است که پیکربندی در آن شکست می‌خورد. اگر job را در crontab کاربر root قرار دهید، WP-CLI پیش از انجام هر کاری متوقف می‌شود:

Error: YIKES! It looks like you're running this as root.

صف پردازش (queue) هرگز اجرا نمی‌شود و اگر خروجی را redirect نکرده باشید، هرگز پیام خطا را نخواهید دید. راه‌حل خطرناک، افزودن --allow-root است، زیرا در این صورت هر فایلی که یک افزونه در طول آن اجرا می‌نویسد، متعلق به root خواهد بود. درخواست وب بعدی که با کاربر www-data اجرا می‌شود، نمی‌تواند در آن دایرکتوری‌ها بنویسد و سایت شروع به گزارش خطاهایی مانند این می‌کند:

Unable to create directory wp-content/uploads/2026/08. Is its parent directory writable by the server?

مالکیت فایل‌ها را اصلاح کنید و سپس job را منتقل نمایید:

sudo chown -R www-data:www-data /srv/www/example.com/wp-content

فایل crontab کاربر root و crontab کاربر www-data دو فایل مجزا هستند، بنابراین حذف خط از یکی، دیگری را تحت تأثیر قرار نمی‌دهد. هر دو را بررسی کنید:

sudo crontab -u root -l
sudo crontab -u www-data -l

چرا cron گزارش می‌دهد wp: not found

این دومین خرابی رایج است. Cron به کارهای کاربر یک PATH بسیار کوتاه می‌دهد، /usr/bin:/bin. ابزار WP-CLI در مسیر /usr/local/bin نصب می‌شود که در آن لیست وجود ندارد. کار شروع می‌شود، در کسری از ثانیه شکست می‌خورد و لاگ فقط شامل یک خط است:

/bin/sh: 1: wp: not found

به‌جای حدس‌زدن، محیط اجرای cron را خودتان مشاهده کنید. یک خط موقت اضافه کنید:

*/5 * * * * env > /tmp/cron-env.txt 2>&1

پس از گذشت یک بازه زمانی، فایل /tmp/cron-env.txt را بخوانید و سپس آن خط را حذف کنید. مقدار PATH= در آن فایل دقیقاً همان چیزی است که کار شما دریافت می‌کند.

دو راه برای رفع این مشکل وجود دارد. از مسیر مطلق /usr/local/bin/wp استفاده کنید، همان‌طور که در مرحله 3 گفته شد. یا PATH را یک‌بار در بالای crontab، قبل از تمام خطوط مربوط به کارها، تنظیم کنید:

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

همین تله یک سطح پایین‌تر نیز وجود دارد. فایل wp با #!/usr/bin/env php شروع می‌شود، بنابراین shell باید بتواند php را نیز پیدا کند. اگر PHP خارج از /usr/bin قرار داشته باشد (که در buildهای سفارشی و buildهای پنل‌های مدیریتی اتفاق می‌افتد)، با این خطا مواجه می‌شوید:

/usr/bin/env: 'php': No such file or directory

در این حالت، مفسر را به‌صورت صریح فراخوانی کنید، برای مثال /usr/local/bin/php /usr/local/bin/wp --path=/srv/www/example.com cron event run --due-now.

چرا بازه زمانی یک دقیقه مشکل اصلی را بازتولید می‌کند

این سومین شکست است. * * * * * نسبت به پنج دقیقه امن‌تر به نظر می‌رسد، اما در یک سایت پربازدید، شما را به نقطه شروع بازمی‌گرداند. اگر اجرای یک پردازش طولانی‌تر از بازه زمانی باشد، اجرای بعدی در حالی آغاز می‌شود که اولی هنوز در حال انجام است. ده دقیقه بعد، ده پردازش PHP وجود خواهد داشت که هر کدام حافظه و اتصال دیتابیس اختصاصی خود را اشغال کرده‌اند.

به‌طور مستقیم به دنبال انباشتگی (pileup) بگردید:

ps -eo etimes,user,args | grep '[c]ron event run'

etimes سن پردازش به ثانیه است. یک خط نشان‌دهنده وضعیت سالم است. وجود چندین خط با سن بسیار بیشتر از بازه زمانی شما، به این معنی است که اجراها در حال انباشته شدن هستند؛ این وضعیت در یک VPS کوچک به خطای Too many connections در MySQL یا کشته شدن PHP توسط هسته سیستم‌عامل برای بازیابی حافظه منجر می‌شود که می‌توانید آن را با sudo dmesg -T | grep -i 'killed process' تأیید کنید.

WP-CLI فراخوانی‌های رویداد (event callbacks) را مستقیماً اجرا می‌کند و به جای درخواست wp-cron.php، از آن استفاده نمی‌کند؛ بنابراین قفل 60 ثانیه‌ای که وردپرس برای جلوگیری از اجرای همزمان استفاده می‌کند، در اینجا اعمال نمی‌شود. flock -n در ورودی مرحله 3 همان چیزی است که اکنون از هم‌پوشانی جلوگیری می‌کند. یک اجرای نادیده گرفته شده (skipped run) طبق طراحی، بلافاصله و بدون خروجی متوقف می‌شود.

بازه زمانی را بر اساس کوتاه‌ترین زمان‌بندی که واقعاً به آن وابسته هستید انتخاب کنید و ابتدا مدت زمان یک اجرا را اندازه‌گیری کنید:

time sudo -u www-data /usr/local/bin/wp --path=/srv/www/example.com cron event run --due-now

پنج دقیقه یک پیش‌فرض معقول است: پستی که برای ساعت 09:00 زمان‌بندی شده، تا ساعت 09:05 منتشر می‌شود. پانزده دقیقه برای سایتی که محتوای حساس به زمان ندارد، مناسب است. یک دقیقه مختص فروشگاه‌ها و افزونه‌های مبتنی بر صف است که واقعاً به آن نیاز دارند، و تنها زمانی از آن استفاده کنید که مطمئن باشید یک اجرا در عرض چند ثانیه به پایان می‌رسد.

اگر نمی‌توانید WP-CLI را نصب کنید

برخی از میزبان‌ها ابزارهای shell را مسدود می‌کنند. یک درخواست HTTP ساده به wp-cron.php همان صف را اجرا می‌کند، با این تفاوت که از کل پشته وب عبور می‌کند:

*/5 * * * * /usr/bin/curl -sS --max-time 120 "https://example.com/wp-cron.php?doing_wp_cron" > /dev/null

آنچه به‌وضوح از دست می‌دهید:

  • اجرای دستور توسط محدودیت‌های زمانی (timeout) وب‌سرور و PHP-FPM محدود می‌شود، بنابراین ممکن است یک عملیات طولانی در میانه راه قطع شود.
  • گواهی باید معتبر باشد، در غیر این صورت curl با خطای SSL certificate problem متوقف می‌شود؛ بنابراین تمدید گواهی‌ها را با Certbot روی nginx فعال نگه دارید.
  • کش صفحات نباید wp-cron.php را ذخیره کند، در غیر این صورت درخواست‌های cron یک پاسخ کش‌شده دریافت می‌کنند و هیچ عملیاتی اجرا نمی‌شود.
  • شما هیچ خروجی برای هر رویداد دریافت نمی‌کنید، بنابراین تنها مدرک اجرای یک عملیات، تأثیری است که بر جای گذاشته است.

-sS باعث می‌شود curl در صورت موفقیت ساکت بماند و فقط خطاها را چاپ کند؛ این دقیقاً همان چیزی است که در یک cron job به آن نیاز دارید.

چه موارد دیگری باید در زمان‌بندی سرور قرار گیرند

هنگامی که cron سیستم مدیریت صف WordPress را بر عهده می‌گیرد، سایر کارهای روتین سرور را نیز در همان مکان متمرکز کنید تا دید کاملی نسبت به آن‌ها داشته باشید. وصله‌های امنیتی سیستم‌عامل باید توسط unattended upgrades مدیریت شوند، نه با یک خط دستور cron که به‌صورت دستی نگهداری می‌کنید. به‌روزرسانی افزونه‌ها و پوسته‌های WordPress تصمیم متفاوتی است: اجرای wp plugin update --all در crontab ممکن است باعث خرابی سایت در ساعت 3 بامداد شود، بدون آنکه کسی متوجه آن باشد. بنابراین، این کار را به‌صورت آگاهانه یا پس از طی مراحل تست در محیط staging و تهیه نسخه پشتیبان انجام دهید.

FAQ

آیا غیرفعال کردن WP-Cron مانع از انتشار پست‌های زمان‌بندی‌شده می‌شود؟

خیر، تا زمانی که چیز دیگری صف را اجرا کند. DISABLE_WP_CRON فقط مانع از این می‌شود که بارگذاری صفحات، صف را فعال کند. رویدادها همچنان دقیقاً مانند قبل زمان‌بندی می‌شوند. پستی که برای ساعت 09:00 تنظیم شده است، در اولین اجرای cron پس از ساعت 09:00 منتشر می‌شود؛ بنابراین با یک بازه زمانی پنج دقیقه‌ای، پست تا ساعت 09:05 منتشر خواهد شد. اگر این ثابت (constant) را تنظیم کنید و هرگز ورودی cron را اضافه نکنید، پست در لیست با وضعیت Missed schedule باقی می‌ماند تا زمانی که چیزی صف را اجرا کند.

کدام کاربر باید job مربوط به cron وردپرس را اجرا کند؟

کاربری که مالک فایل‌هایی است که PHP می‌نویسد؛ این کاربر در نصب پیش‌فرض Ubuntu برابر با www-data است. با استفاده از stat -c '%U %G' /srv/www/example.com/wp-content/uploads بررسی کنید و آن را با خط user = در پیکربندی pool مربوط به PHP-FPM مقایسه کنید. اجرای job به عنوان root باعث می‌شود WP-CLI با خطای YIKES متوقف شود و اجبار آن با استفاده از --allow-root باعث می‌شود فایل‌هایی با مالکیت root در داخل wp-content باقی بمانند که وب‌سرور بعداً قادر به نوشتن در آن‌ها نخواهد بود.

سیستم cron هر چند وقت یک‌بار باید cron وردپرس را اجرا کند؟

هر پنج دقیقه برای اکثر سایت‌ها مناسب است. بازه زمانی را با کوتاه‌ترین زمان‌بندی که واقعاً به آن نیاز دارید مطابقت دهید و آن را به‌طور مطمئنی بیشتر از زمانی که یک اجرای تکی طول می‌کشد نگه دارید؛ این زمان را می‌توانید با قرار دادن time قبل از دستور WP-CLI اندازه‌گیری کنید. بازه‌های یک دقیقه‌ای در سایت‌های شلوغ باعث انباشته شدن اجراها روی یکدیگر می‌شوند، مگر اینکه flock از آن‌ها محافظت کند.

چرا wp cron test پس از غیرفعال کردن WP-Cron با شکست مواجه می‌شود؟

زیرا آن دستور، ایجاد رویداد توسط بازدیدکننده را تست می‌کند و زمانی که DISABLE_WP_CRON روی true تنظیم شده باشد، خطا گزارش می‌دهد. این نتیجه در سروری که به این شکل پیکربندی شده، صحیح است. در عوض مسیر system cron را بررسی کنید: /var/log/wp-cron/example.log را بخوانید، یا یک رویداد نشانگر (marker event) با wp cron event schedule زمان‌بندی کنید و تأیید کنید که پس از اجرای بعدی، از wp cron event list حذف شده است.

آیا به WP-CLI نیاز دارم یا استفاده از curl برای wp-cron.php کافی است؟

Curl کار می‌کند و زمانی که نمی‌توانید WP-CLI را نصب کنید، پاسخ درستی است. این روش کندتر است، زیرا وردپرس را از طریق وب‌سرور بارگذاری می‌کند و توسط timeout درخواست محدود می‌شود. WP-CLI رویدادها را در یک پردازش PHP خط فرمان بدون timeout وب اجرا می‌کند و به ازای هر رویداد، یک خط شامل مدت زمان آن چاپ می‌کند؛ بنابراین لاگ دقیقاً به شما می‌گوید چه چیزی اجرا شده و چقدر طول کشیده است.