itsrda

systemd Timer mı Cron mu? Zamanlanmış Görevler İçin Karşılaştırma ve Örnekler

Cron onlarca yıldır işini görüyor, ama systemd timer günlük kaydı, kaçırılan çalıştırmayı telafi etme ve bağımlılık yönetimi gibi alanlarda öne çıkıyor. İkisini örneklerle karşılaştırıyoruz.

Linux'ta bir işi belirli saatte çalıştırmak için iki yaygın yol vardır: cron ve systemd timer. Cron daha eski ve daha kısadır; timer ise biraz daha fazla yazı gerektirir ama karşılığında önemli özellikler sunar. Hangisini ne zaman seçeceğinizi bilmek, "gece yedeği sessizce çalışmıyormuş" türü sürprizleri azaltır.

Cron'un kısa tarifi

crontab -e ile her satıra beş zaman alanı ve bir komut yazılır:

15 3 * * *  /usr/local/bin/db-yedek.sh

Anlamı: her gün 03:15'te çalıştır. Alanlar sırasıyla dakika, saat, ayın günü, ay ve haftanın günüdür. Basit ve herkesin bildiği bir sözdizimidir.

Cron'un zayıf yönleri

  • Çıktı kaybolur. Cron çıktıyı varsayılan olarak yerel posta kutusuna göndermeye çalışır; çoğu sunucuda posta sistemi yoktur ve hata mesajı sessizce yok olur. Çözüm için her satırın sonuna >> /var/log/is.log 2>&1 yazmak gerekir.
  • Kaçırılan çalıştırma telafi edilmez. Cihaz 03:15'te kapalıysa o gün yedek alınmaz. Raspberry Pi gibi elektrik kesintisine açık cihazlarda bu gerçek bir risktir (anacron bu boşluğu doldurur ama ayrı kurulumdur).
  • Ortam farklıdır. Cron'un PATH değişkeni kısıtlıdır. Elle çalışan komut, cron'da "komut bulunamadı" verebilir.
  • Bağımlılık yoktur. "Ağ gelsin, veritabanı hazır olsun, sonra çalış" diyemezsiniz.

systemd timer'ın iki parçası

Timer, iki dosyadan oluşur: işi tanımlayan .service ve zamanı tanımlayan .timer.

# /etc/systemd/system/rapor.service
[Unit]
Description=Gunluk rapor
After=network-online.target

[Service]
Type=oneshot
User=pi
ExecStart=/usr/bin/python3 /home/pi/rapor.py
# /etc/systemd/system/rapor.timer
[Unit]
Description=Her sabah rapor

[Timer]
OnCalendar=*-*-* 08:00:00
Persistent=true

[Install]
WantedBy=timers.target
sudo systemctl daemon-reload
sudo systemctl enable --now rapor.timer

Timer'ın üstün yönleri

Günlük kaydı hazırdır. Çıktı ve hata mesajları otomatik olarak journal'a düşer: journalctl -u rapor.service. Son çalıştırmanın ne zaman olduğunu systemctl list-timers gösterir.

Persistent=true kaçırılanı telafi eder. Cihaz kapalıyken geçen zamanlama, açıldığında hemen çalıştırılır.

Bağımlılık ve ortam tanımlanabilir. After=, Requires=, EnvironmentFile= ve User= ile işin hangi koşulda ve hangi kullanıcıyla çalışacağı açıkça yazılır.

Sınırlama getirilebilir. TimeoutStartSec=, MemoryMax=, Nice= gibi ayarlarla kontrolden çıkan bir işin sistemi boğması önlenir.

Elle tetiklenebilir. Beklemeden denemek için sudo systemctl start rapor.service yeterlidir. Test için saati değiştirmenize gerek kalmaz.

OnCalendar ifadeleri

Timer'ın zaman sözdizimi okunaklıdır:

İfade Anlamı
daily Her gün 00:00
*-*-* 08:00:00 Her gün 08:00
Mon..Fri 09:00 Hafta içi 09:00
*:0/2 Her 2 dakikada bir
*-*-01 04:00:00 Her ayın 1'i 04:00
Sun *-*-* 02:30 Her pazar 02:30

İfadeyi yazmadan önce doğrulamak için şu komutu kullanın; bir sonraki çalışma zamanını gösterir:

systemd-analyze calendar "Mon..Fri 09:00"

Aralıklı ve sık çalışan işler için (ör. 2 dakikada bir kontrol) OnUnitActiveSec=2min ve OnBootSec=1min birlikte kullanılabilir.

Hangisi ne zaman?

  • Cron seçin: Tek satırlık, önemsiz, hata olursa kaybolması sorun olmayan işler; çok eski sistemler; hızlı denemeler.
  • Timer seçin: Yedekleme, rapor, e-posta, alarm gibi sonucu önemli olan işler; kapanıp açılabilen cihazlar; günlük kaydı gereken her şey.

Basit bir kural: işin başarısız olduğunu bilmek sizin için önemliyse timer kullanın.

Cron'dan geçiş

Mevcut bir cron satırını timer'a çevirmek için komutu ExecStart= satırına, zamanı OnCalendar= satırına taşımanız yeterlidir. ExecStart içinde komutun tam yolunu yazın; PATH'e güvenmeyin. Geçişi doğruladıktan sonra cron satırını silmeyi unutmayın, aksi halde iş iki kez çalışır.

İlgili örnek: MariaDB otomatik yedekleme yazımızda gece yedeği için timer kurulumunu uygulamalı olarak görebilirsiniz.

Not: Komutları üretim ortamında çalıştırmadan önce yedek alın ve önce test ortamında deneyin. Bir adım sizde farklı davranıyorsa bize yazın, rehberi güncelleyelim.