Pola produkcijskih problema dolazi iz cron jobova koji ne rade kako bi trebali. WP-Cron koji čeka traffic da se okine, Laravel scheduler bez supervisor-a, kalendar-tasksi koji su trebali poslat reminder a nisu. Ovo je vodič kako pravilno postavit i monitorat scheduled tasks.
Što je cron i kako radi
Cron = Unix scheduler koji pokreće komande u definirano vrijeme. Format:
* * * * * command
│ │ │ │ │
│ │ │ │ └─ day of week (0-7)
│ │ │ └─── month (1-12)
│ │ └───── day of month (1-31)
│ └─────── hour (0-23)
└───────── minute (0-59)
Primjeri:
0 * * * *— svaki sat na :00.*/15 * * * *— svakih 15 minuta.0 3 * * *— svaki dan u 3 ujutro.0 0 * * 0— nedjeljom u ponoć.30 2 1 * *— prvi dan u mjesecu u 02:30.
Alati za testirat: crontab.guru — vizualno objašnjava bilo koji cron expression.
cPanel cron jobs
U cPanel: Advanced → Cron Jobs. Form za dodavanje s padajućim listama za minutu/sat/dan.
Tipičan WP cron unos:
*/5 * * * * cd /home/USER/public_html && /usr/local/bin/php -q wp-cron.php >/dev/null 2>&1
Tipičan Laravel scheduler:
* * * * * cd /home/USER/app && /usr/local/bin/php artisan schedule:run >> /dev/null 2>&1
Šta NE radit u cPanel cron
- Ne stavljaj output u email osim ako stvarno hoćeš inbox spam. Default cron output ide na cPanel email.
- Ne pokušavaj
*/1 * * * *ako shared hosting ima 5-min minimum policy (cPanel admin može ograničit). - Ne pokreći više jobova s istim resource-heavy task u istoj minuti — server overload.
WP-Cron — problematični default
WordPress ima ugrađen "cron" — wp-cron.php. ALI: NIJE pravi cron. WP-Cron se pokreće samo kad netko posjeti stranicu. Posljedice:
- Niski traffic sajtovi: scheduled posts ne objavljuju se na vrijeme, automated emails ne idu, transients ne čiste se.
- Visoki traffic: WP-Cron se pokreće na svakom (10. ili tako) requestu, dodaje latency.
- WooCommerce email notifikacije za narudžbe mogu kasniti satima ako nitko ne posjeti sajt.
Pravilan WP-Cron setup
- U
wp-config.phpdodaj:define('DISABLE_WP_CRON', true); - U cPanel cron dodaj job koji pokreće
wp-cron.phpsvakih 5 min preko CLI. - Rezultat: cron radi predvidivo, nezavisno od traffic-a.
Laravel scheduler
Laravel ima elegantnu apstrakciju cron-a. U routes/console.php (ili u Console/Kernel.php u staroj verziji):
Schedule::command('reports:generate')->daily();
Schedule::command('queue:prune-batches')->hourly();
Schedule::call(fn() => Cache::flush())->weekly();
Sve to pokreće JEDAN cron unos:
* * * * * cd /path/to/app && php artisan schedule:run >> /dev/null 2>&1
Laravel sam odlučuje koji command pokrenut u kojoj minuti. Predivno.
withoutOverlapping
Ako command traje 7 min, a okida se svakih 5 min — pokreneš se dva put paralelno, gubitak resursa, race condition. Rješenje:
Schedule::command('long:task')->everyFiveMinutes()->withoutOverlapping();
Lock se drži u cache-u (Redis ili file).
onOneServer (multi-server setup)
Ako Laravel teče na više servera load-balanced, cron radi na svakom — duplikati. Rješenje:
Schedule::command('reports:send')->daily()->onOneServer();
Lock se drži u shared cache (Redis), samo jedan server izvršava.
Queue workers — različita stvar od cron-a
Cron = trigger u definirano vrijeme. Queue = posao koji se izvršava kad ima radnika.
Use cases za queue:
- Slanje emaila (ne blokirat user request).
- Image processing (resize, watermark).
- API integracije (third-party API call s retry-em).
- Notifikacije.
Laravel queue setup
Backend opcije: Redis (najbolji), database, SQS. config/queue.php → default 'redis'.
Worker mora teći kontinuirano:
php artisan queue:work --queue=high,default,low --sleep=3 --tries=3
Ali process će umrijet (memory leak, deploy restart, server reboot). Treba supervisor.
Supervisor setup
/etc/supervisor/conf.d/laravel-worker.conf:
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /path/to/app/artisan queue:work --sleep=3 --tries=3
autostart=true
autorestart=true
numprocs=4
user=www-data
redirect_stderr=true
stdout_logfile=/var/log/laravel-worker.log
Komande:
supervisorctl reread
supervisorctl update
supervisorctl start laravel-worker:*
Laravel Horizon (Redis only)
Web dashboard za monitoring queue + supervisor logic ugrađena. Top za production Laravel apps.
composer require laravel/horizon
php artisan horizon:install
Pokreće se sa php artisan horizon (i to mora supervisor čuvat).
Monitoring cron jobova
Cron koji ne radi je tihi failure. Mora se monitorat.
Healthchecks.io
Pošalji HTTP request na URL svaki put cron završi. Ako Healthchecks ne primi ping u expected interval-u, šalje alert.
0 3 * * * /path/to/script.sh && curl -fsS --retry 3 https://hc-ping.com/UUID
Free tier 20 checks. Self-host opcija također.
Cronitor
Sličan Healthchecks-u, lijepi UI, hosted-only.
Better Stack Heartbeats
Već koristiš Better Stack za uptime? Add heartbeats za cron monitoring.
Laravel native
Laravel scheduler ima onSuccess i onFailure hooks. Možeš direktno pingat Healthchecks ili slat Slack notif.
System cron vs application cron
- System cron (Linux
/etc/cron.d/) — za system maintenance (log rotation, backup, OS update). Ne za app logiku. - cPanel cron — za pojedinačni app/account. Per-user.
- Application-level scheduler (Laravel, Django Celery beat) — za business logic, code-first, version-controlled.
Pravilo: business cronovi ne smiju biti u sistemskom crontabu — onda nisu u git-u, izgube se na server migraciji.
Pitfalls
- Time zone: cron koristi server TZ. Postavi server TZ (Europe/Zagreb) ili koristi cron u UTC i kalkuliraj. Najlakše: server na Europe/Zagreb.
- PATH: cron environment je minimalan. Možda
phpne radi, treba full path/usr/local/bin/php. - Working directory: cron ne zna gdje pokreće. Uvijek koristi
cd /path/to/appili apsolutne staze. - Tihi failure: ako script padne, cron samo briše output. Loguj sve.
- Overlap: dugi job + brzi interval = paralelni instance-i, race condition. Koristi lock file ili
flock. - Email spam: default cron output ide na mail. Suffix
>/dev/null 2>&1ako ne želiš mail.
Best practices
- Svaki cron job mora bit version-controlled (u app kodu kroz Laravel scheduler, ili u deployment script-u).
- Svaki cron job mora pingat heartbeat (Healthchecks.io, Better Stack).
- Svaki cron job mora logirat start, completion, errors.
- Long-running cronovi (>1min) →
withoutOverlapping. - Critical cronovi → alert pri failure (Slack, email).
- Pre-deploy: testiraj nove cron jobove na stagingu prije production.
WMD i cron management
Sav WMD WordPress hosting dolazi sa DISABLE_WP_CRON + system cron job za wp-cron.php setup po default-u. Za Laravel klijente postavljamo schedule:run cron + Supervisor za queue workers + Horizon dashboard. Healthchecks.io integration uključen u Maintenance Plan — svaki kritičan cron monitor-an, alert ako ne ping-a u 2x interval-u. Time zone setup, log rotation, scheduled audit cronova svaki mjesec.
FAQ
Smije li WP-Cron raditi na production sajtu? Ne, gasi ga (define DISABLE_WP_CRON) i postavi system cron. Default behavior je nepouzdan.
Šta ako klijent nema SSH pristup za supervisor? Koristi cPanel Application Manager (Node) ili shared cron + restart logic u skripti. Nije idealno, ali radi za male queue volumes.
Mogu li imat cron u Docker kontejneru? Da, ali bolje: koristi host cron koji pokreće docker exec, ili dedicated scheduler container (k8s CronJob). Cron unutar app container-a je antipattern.
Koliko često mogu pokretat cron? Standard min interval je 1 minuta. Ako trebaš češće — koristi long-running daemon process s sleep(30) loop-om umjesto cron-a.
Race condition pri prvom pokretanju queue worker-a? Provjeri schedule:run output, lock fajlovi u storage/framework/. Pokušaj php artisan queue:restart nakon deploya da svi worker-i pokupe novi kod.
Trebaš pravilan cron + queue setup? WMD postavlja system cron, Laravel scheduler, Supervisor, Horizon i Healthchecks za WP/Laravel klijente. Javi se preko kontakt forme.