Modern Linux dağıtımlarının çoğu systemd ile geldiğinden beri zamanlanmış görevler için iki güçlü seçenek var: klasik cron ve systemd timer birimleri. İkisi de belirlenen zamanda komut çalıştırır; loglama, bağımlılık, kaynak sınırı ve kaçan görev telafisinde ayrışırlar. Resmi referans: systemd.timer(5).
Bu rehber yan yana karşılaştırma, çalışan .service/.timer kurulumu, OnCalendar sözdizimi, gerçek senaryolar ve sık hata mesajlarını verir. Beş alanlı cron ifadeleri için crontab sözdizimi; kaçan günlük işler için ayrıca anacron seçeneği vardır.
Karar kuralı kısa: tek satırlık, taşınabilir iş → cron; servis bağımlılığı, journald, cgroup veya Persistent=true → systemd timer. İkisi aynı sunucuda birlikte çalışabilir.
Hızlı Karşılaştırma
| Özellik | Cron | Systemd Timer |
|---|---|---|
| Kurulum kolaylığı | Tek satır (crontab -e) | İki dosya (.timer + .service) |
| Loglama | Elle yönlendirme (>> log 2>&1) | Otomatik — journalctl |
| Kaçan görev telafisi | Yok (anacron gerekir) | Persistent=true (yalnız OnCalendar) |
| Servis bağımlılığı | Yok | After=, Requires= |
| Kaynak sınırlama | Yok | cgroup: MemoryMax=, CPUQuota= |
| Çakışma koruması | Elle (flock) | Aynı servis üst üste başlamaz |
| Rastgele gecikme | Elle sleep | RandomizedDelaySec= |
| Saniye hassasiyeti | Yok (min. 1 dakika) | Ayarlanabilir; varsayılan AccuracySec=1min |
| Taşınabilirlik | Her Unix'te aynı | Yalnızca systemd'li Linux |
| Öğrenme eğrisi | Düşük | Orta |
Systemd Timer Nasıl Kurulur?
Bir timer iki birimden oluşur: işi tanımlayan .service ve zamanlamayı tanımlayan .timer. Varsayılan eşleştirmede dosya adları aynı tabanı paylaşır (yedek.service + yedek.timer).
1. Service birimi
# /etc/systemd/system/yedek.service
[Unit]
Description=Gunluk veritabani yedegi
After=network-online.target mysql.service
[Service]
Type=oneshot
User=yedek_user
ExecStart=/opt/scripts/yedek.sh
MemoryMax=512M
Nice=10
Type=oneshot kısa süreli, bitince çıkan script'ler içindir. After= yalnızca sıralama garantisi verir; bağımlılığı da başlatmak için Requires= veya Wants= ekleyin; Wants= başarısız bağımlılıkta görevi engellemez.
2. Timer birimi
# /etc/systemd/system/yedek.timer
[Unit]
Description=Gunluk veritabani yedegi zamanlayicisi
[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true
RandomizedDelaySec=300
[Install]
WantedBy=timers.target
Persistent=true, timer kapalıyken (ör. makine kapalı) kaçan OnCalendar tetiklerini açılışta yakalar; man sayfasına göre yalnızca OnCalendar= ile etkilidir. RandomizedDelaySec= yükü yaymak için kullanılır; kalıcı tetikte de gecikme uygulanabilir.
3. Etkinleştirme ve izleme
- Dosyaları
/etc/systemd/system/altına yazın. sudo systemctl daemon-reloadsudo systemctl enable --now yedek.timersystemctl list-timersile sonraki çalışma zamanını doğrulayın.- Zamanı beklemeden test:
sudo systemctl start yedek.service - Log:
journalctl -u yedek.service -n 50 --no-pager
sudo systemctl daemon-reload
sudo systemctl enable --now yedek.timer
systemctl list-timers
journalctl -u yedek.service -n 50
sudo systemctl start yedek.service
OnCalendar Sözdizimi vs Cron
Cron'un 5 alanlı sözdizimi yerine systemd okunabilir takvim ifadeleri kullanır (systemd.time(7)):
| Zamanlama | Cron | OnCalendar |
|---|---|---|
| Her gün 02:00 | 0 2 * * * | *-*-* 02:00:00 |
| Her 15 dakikada | */15 * * * * | *:0/15 |
| Hafta içi 09:00 | 0 9 * * 1-5 | Mon..Fri 09:00 |
| Ayın 1'i 04:30 | 30 4 1 * * | *-*-01 04:30:00 |
| Her saat başı | 0 * * * * | hourly |
Test: systemd-analyze calendar "Mon..Fri 09:00". Cron ifadeleri için cron expression generator kullanabilirsiniz.
Gerçek Senaryolar
Senaryo 1: MySQL ayaktayken gece yedeği (timer)
After=mysql.service ve Requires=mysql.service ile yedek, MySQL biriminin başarılı başlangıcından sonra çalışır; veritabanının bağlantı kabul etmeye hazır olması servis türüne bağlıdır. MemoryMax=512M gece yedeğinin tüm RAM'i yemesini engeller. Log için ekstra yönlendirme gerekmez; journalctl -u yedek.service yeterlidir. Cron'da aynı bağımlılığı güvenilir kurmak zordur.
Senaryo 2: Her 5 dakikada kuyruk (cron)
*/5 * * * * /usr/bin/flock -n /tmp/kuyruk.lock /usr/bin/php /var/www/app/kuyruk.php >>/var/log/kuyruk.log 2>&1
Bağımsız, sık ve taşınabilir bir işte iki unit dosyası fazla tören olabilir. Çakışmayı flock, logu dosya yönlendirmesi ile çözersiniz. PATH tuzakları için cron job çalışmıyor listesine bakın.
Systemd Timer'ın Öne Çıktığı Senaryolar
- Bağımlılık: Script başlangıcını veritabanı/ağ birimlerinin başlangıcına göre sıralama.
- Kaynak kontrolü:
MemoryMax=,CPUQuota=. - Merkezi log: Her şey journald'de — cron'da log yönlendirme gerekir.
- Telafi:
Persistent=trueanacron benzeri yakalama. - Üst üste binme: Aynı oneshot servis bitmeden yeniden başlamaz.
Cron'un Hâlâ Kazandığı Senaryolar
- Hız: Tek satır +
crontab -e. - Taşınabilirlik: FreeBSD, Alpine (OpenRC), paylaşımlı hosting — crontab her yerde.
- Kullanıcı görevleri: Root'suz
crontab -e(user timer da vardır ama daha az yaygın). - Ekip alışkanlığı: Crontab cheatsheet çoğu ekipte yeterlidir.
İkisinin de koşullarınızı karşılamadığı durumlar — dağıtık ekip, HTTP tabanlı tetikleme, bulut zamanlayıcılar — cron alternatifleri karar tablosunda tek bakışta karşılaştırılmıştır.
Sık Hatalar ve Çözümleri
1. Failed to enable unit: Unit yedek.timer does not exist
Neden: Dosya yolu/adı yanlış veya daemon-reload atlandı.
Çözüm: /etc/systemd/system/yedek.timer olduğundan emin olun; daemon-reload çalıştırın.
2. Failed to parse calendar specification
Neden: Geçersiz OnCalendar.
Çözüm: systemd-analyze calendar "..." ile doğrulayın; cron sözdizimini olduğu gibi yapıştırmayın.
3. Timer aktif ama servis çalışmıyor
Neden: Service ExecStart yolu hatalı; kullanıcı izni; bağımlılık başarısız.
Çözüm: systemctl status yedek.service ve journalctl -u yedek.service -xe; script'i aynı kullanıcıyla elle çalıştırın.
4. Persistent=true beklenen telafiyi yapmıyor
Neden: Timer OnCalendar kullanmıyor (ör. yalnızca OnBootSec); veya state temizlenmiş.
Çözüm: Takvim ifadesi kullanın; state için man sayfasındaki systemctl clean --what=state uyarısını bilinçli uygulayın.
5. Unit dosyası değişti ama eski davranış sürüyor
Neden: daemon-reload veya timer restart unutuldu.
Çözüm: daemon-reload sonra systemctl restart yedek.timer.
cronjob.com.tr ile HTTP Tabanlı Alternatif
Hem cron hem systemd timer sunucu üzerinde yapılandırma ve bakım ister. Görev HTTP ile tetiklenebiliyorsa cronjob.com.tr unit dosyası veya crontab olmadan zamanlar. Ücretsiz; kayıtta kredi kartı istenmez. En kısa aralık 1 dakika; 5 alanlı cron ifadesi veya hazır aralık seçilebilir (saat dilimi iş bazında, varsayılan Europe/Istanbul).
<?php
declare(strict_types=1);
$beklenen = getenv('CRON_SECRET') ?: '';
$gelen = $_SERVER['HTTP_X_CRON_TOKEN'] ?? '';
if ($beklenen === '' || !hash_equals($beklenen, $gelen)) {
http_response_code(403);
exit('forbidden');
}
http_response_code(200);
echo 'ok';
Panelde URL, metot, özel header, isteğe bağlı gövde ve zamanlamayı girin. Başarı HTTP 200–399; en fazla 5 yönlendirme; TLS doğrulanır; localhost/özel ağa istek yok. Timeout aralığa göre (1 dk → 55 sn, cron ifadeli → 290 sn). Çalışma logları ~7 gün; ardışık hata eşiğinde e-posta.
Sıkça Sorulan Sorular (SSS)
Systemd timer cron'dan daha mı iyi?
Duruma bağlı. Systemd timer log yönetimi, servis bağımlılığı, kaynak sınırlama ve kaçan görev telafisi (Persistent=true) sunar; buna karşılık her görev için iki dosya (.timer + .service) gerektirir ve öğrenme eğrisi daha diktir. Tek satırlık basit görevlerde cron hâlâ en hızlı çözümdür.
Systemd timer'da kaçan görevler telafi edilir mi?
Evet. Timer'ın [Timer] bölümüne Persistent=true eklerseniz, makine kapalıyken kaçan görev bir sonraki açılışta otomatik çalıştırılır — anacron'a gerek kalmaz. Bu ayar yalnızca OnCalendar= kullanan timer'larda geçerlidir.
Systemd timer loglarını nasıl görürüm?
journalctl -u gorev-adi.service komutuyla görevin tüm çıktı ve hata kayıtlarını, systemctl list-timers --all komutuyla da tüm timer'ların son ve sonraki çalışma zamanlarını görebilirsiniz.
OnCalendar ifadesini nasıl test ederim?
systemd-analyze calendar "Mon..Fri 09:00" komutu bir sonraki tetiklenme zamanını gösterir. Hatalı takvim ifadesi burada veya timer yüklenirken ortaya çıkar.
User-level systemd timer kullanabilir miyim?
Evet. ~/.config/systemd/user/ altına .service ve .timer koyup systemctl --user enable --now kullanın. Oturum kapalıyken çalışması için linger (loginctl enable-linger) gerekebilir.
Sonuç
Tek satırlık, bağımsız ve taşınabilir görevlerde cron; bağımlılık, kaynak sınırı, merkezi log ve telafi gerektiren görevlerde systemd timer tercih edin. Doğru araç, görevin karmaşıklığına göre seçilir.
Sunucu Yapılandırmadan Cron Job Oluşturun
Unit dosyası veya crontab olmadan HTTPS işlerinizi panelden zamanlayın. Ücretsiz; kayıtta kredi kartı istenmez.
Ücretsiz Başla →