Laravel menjadwalkan tugas berulang melalui satu mekanisme terpusat, bukan melalui banyak entri cron yang terpisah. Topik ini membahas peran perintah schedule:run beserta entri cron yang memanggilnya setiap menit, cara mendefinisikan jadwal di routes/console.php, pemetaan metode frekuensi ke ekspresi cron, serta cara memeriksa dan menjalankan jadwal pada proyek aplikasi catatan.
Peran scheduler dan entri cron#
Aplikasi web hanya aktif ketika ada permintaan, sehingga tugas berulang seperti ekspor laporan harian tidak dapat mengandalkan siklus permintaan. Laravel menyelesaikannya dengan scheduler: satu entri cron memanggil php artisan schedule:run setiap menit, kemudian perintah itu membaca definisi jadwal aplikasi dan menjalankan yang jatuh tempo. Definisi jadwal tersimpan di dalam kode bersama sisa aplikasinya, sedangkan server hanya memuat satu entri cron untuk seluruh tugas. Diagram berikut merangkum alurnya.
crontab -e. Bentuknya seperti berikut, dengan lima bidang waktu di depan dan perintahnya di belakang.
* * * * * cd /home/kal/aplikasi-catatan && php artisan schedule:run >> /dev/null 2>&1Lima bidang * * * * * berarti setiap menit pada setiap jam, hari, bulan, dan hari dalam minggu. Perintah di belakangnya masuk ke direktori proyek terlebih dahulu sehingga artisan menemukan aplikasinya, menjalankan schedule:run, lalu mengarahkan keluarannya ke /dev/null agar kotak surat cron tidak terisi. Bidang-bidang waktu tersebut menggunakan konvensi yang sama dengan ekspresi cron pada definisi jadwal, sehingga keduanya mengikuti format yang seragam.
Pada lingkungan lokal yang belum memiliki daemon cron, perintah php artisan schedule:work menggantikan entri cron dengan memanggil schedule:run setiap menit. Perintah ini berjalan terus sampai dihentikan, sehingga sesuai untuk pengembangan dan bukan untuk produksi.
# tidak-dijalankan
# menjalankan scheduler secara berkelanjutan pada lingkungan lokal
cd ~/aplikasi-catatan
php artisan schedule:workMendefinisikan jadwal di routes/console.php#
Berkas routes/console.php dimuat framework pada setiap proses, sehingga pemanggilan facade Schedule di berkas itu mendaftarkan event jadwal ke scheduler. Berkas yang sama juga menjadi tempat definisi perintah Artisan berbasis closure, dan penempatan ini wajar karena jadwal sering menunjuk perintah yang didefinisikan di sana. Proyek yang masih polos belum memiliki jadwal apa pun, dan keadaan itu dapat diperiksa dengan schedule:list.
# memeriksa daftar jadwal pada proyek yang belum mendefinisikannya
cd ~/aplikasi-catatan
php artisan schedule:list INFO No scheduled tasks have been defined.Perbarui berkas tersebut sehingga mendaftarkan satu perintah closure beserta jadwalnya. Perintah catatan:ekspor berperan sebagai contoh tugas, sedangkan Schedule::command() dengan metode everyMinute() menjadwalkannya untuk berjalan setiap menit.
// tidak-dijalankan
<?php
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Schedule;
Artisan::command('catatan:ekspor', function () {
$this->info('Laporan catatan diekspor ke berkas CSV.');
})->purpose('Mengekspor laporan catatan ke berkas CSV');
Schedule::command('catatan:ekspor')->everyMinute()->description('Ekspor laporan catatan');Blok pertama mendefinisikan perintah catatan:ekspor yang keluarannya ditulis dengan $this->info(), sedangkan blok kedua menjadwalkannya dan memberi deskripsi melalui description(). Metode command() menerima tanda tangan (signature) perintah, sehingga jadwal juga dapat menunjuk perintah kelas maupun perintah bawaan framework. Apabila tugasnya hanya satu langkah pendek, Schedule::call(function () { /* aksi */ }) menjadwalkan closure tanpa membuat perintah sama sekali. Setelah definisi ini ditambahkan, schedule:list menampilkan jadwalnya beserta ekspresi cron dan perkiraan pemanggilan berikutnya.
* * * * * php artisan catatan:ekspor ........ Next Due: 20 seconds from nowMetode frekuensi dan ekspresi cron#
Metode frekuensi pada definisi jadwal diterjemahkan menjadi ekspresi cron, yaitu lima bidang yang sama dengan yang digunakan crontab. Tabel berikut memetakan beberapa metode yang sering digunakan beserta artinya.
| Metode | Ekspresi cron | Arti |
|---|---|---|
everyMinute() | * * * * * | setiap menit |
dailyAt("06:00") | 0 6 * * * | setiap hari pukul 06.00 |
weeklyOn(1, "08:00") | 0 8 * * 1 | setiap Senin pukul 08.00 |
monthlyOn(28, "15:00") | 0 15 28 * * | tanggal 28 pukul 15.00 |
Ekspresi tersebut tersimpan pada properti expression setiap event jadwal, sehingga pemetaannya dapat dibaca langsung dari proyek.
# membaca ekspresi cron dari beberapa metode frekuensi
cd ~/aplikasi-catatan
php artisan tinker --execute='
use Illuminate\Support\Facades\Schedule;
echo Schedule::command("catatan:ekspor")->everyMinute()->expression . PHP_EOL;
echo Schedule::command("catatan:ekspor")->dailyAt("06:00")->expression . PHP_EOL;
echo Schedule::command("catatan:ekspor")->weeklyOn(1, "08:00")->expression . PHP_EOL;
echo Schedule::command("catatan:ekspor")->monthlyOn(28, "15:00")->expression . PHP_EOL;
'* * * * *
0 6 * * *
0 8 * * 1
0 15 28 * *Setiap baris cocok dengan tabel di atas, dan angka pada bidang tertentu menegaskan perilakunya, misalnya 0 8 * * 1 yang bidang terakhirnya berarti hari ke-1 dalam minggu, yaitu Senin. Kombinasi lain juga tersedia, misalnya weekdays() untuk membatasi pada hari kerja dan between("08:00", "17:00") untuk membatasi rentang jam. Untuk tugas yang berpotensi berjalan lebih lama dari jeda jadwalnya, metode withoutOverlapping() menahan pemanggilan berikutnya sampai yang sebelumnya selesai, sedangkan onOneServer() mencegah tugas yang sama dijalankan ganda ketika aplikasi ditempatkan pada beberapa server.
Menjalankan tugas yang jatuh tempo#
Pada server, entri cron memanggil schedule:run tanpa keluaran yang terlihat, sehingga perilakunya perlu dipahami melalui simulasi. Perintah php artisan schedule:run memeriksa seluruh event yang terdaftar, menjalankan yang jatuh tempo pada menit itu, lalu melaporkan pelaksanaannya ke konsol.
# tidak-dijalankan
# menjalankan seluruh tugas yang jatuh tempo pada menit ini
cd ~/aplikasi-catatan
php artisan schedule:runKeluaran berikut diambil dari eksekusi nyata pada proyek yang berisi jadwal di atas.
2026-11-03 14:26:39 Running ['artisan' catatan:ekspor] ....... 123.07ms DONE
⇂ Ekspor laporan catatanBaris pertama memuat waktu mulai, identitas event, durasi eksekusi, dan statusnya. Baris kedua menampilkan deskripsi yang ditetapkan melalui description(), atau perintah lengkap yang dieksekusi apabila deskripsi tidak diberikan. Keluaran tugas itu sendiri tidak tampak pada keluaran tersebut karena entri cron mengarahkannya ke /dev/null, dan apabila keluaran perlu disimpan, metode sendOutputTo() pada event mengarahkan hasilnya ke berkas tertentu. Pelaksanaan rutin pada produksi tidak dipantau secara langsung, melainkan melalui log dan mekanisme pemberitahuan yang disiapkan aplikasi.
Kesalahan umum#
Kesalahan pertama adalah menambahkan definisi jadwal tanpa memasang entri cron. Tidak ada satu pun tugas yang berjalan karena schedule:run tidak pernah dipanggil, dan schedule:list tetap menampilkan definisinya sehingga keadaannya tampak sehat. Pasang entri cron pada setiap server produksi, dan gunakan schedule:work hanya pada lingkungan lokal.
Kesalahan kedua adalah menggunakan jalur relatif pada entri cron, misalnya php artisan schedule:run tanpa cd. Cron menjalankan perintah dari direktori kerja yang bukan direktori proyek, sehingga artisan tidak menemukan aplikasinya dan cron mencatat error yang sama setiap menit. Selalu masuk ke direktori proyek terlebih dahulu, atau tulis jalur absolut menuju artisan.
Kesalahan ketiga adalah membiarkan tugas berjalan lebih lama dari jeda jadwalnya. Tugas ekspor yang membutuhkan tiga menit pada jadwal everyMinute() bertumpuk menjadi tiga proses yang bersaing menggunakan sumber daya yang sama. Tandai tugas semacam itu dengan withoutOverlapping() agar pemanggilan berikutnya menunggu, lalu pantau durasi eksekusinya pada keluaran schedule:run.
Ringkasan#
- Satu entri cron
* * * * *memanggilschedule:runsetiap menit, dan perintah itu menjalankan seluruh tugas yang jatuh tempo. - Jadwal didefinisikan di
routes/console.phpmelalui facadeSchedule, dengan metode frekuensi yang diterjemahkan menjadi ekspresi cron lima bidang. schedule:listmenampilkan daftar jadwal beserta ekspresi cron-nya, sedangkanschedule:workmenggantikan cron pada lingkungan lokal.withoutOverlapping()mencegah tugas bertumpuk, dandescription()membuat laporan pelaksanaannya mudah dibaca.
Referensi#
- Task Scheduling — Laravel — Dokumentasi resmi definisi jadwal, entri cron, metode frekuensi, dan schedule:run.
- Artisan Console — Laravel — Dokumentasi perintah Artisan dan closure command pada routes/console.php.