Uzun yıllardır sunucularda cron ile idare ettim; küçük script’leri sabitlemek ve unutmamak pratik geliyordu. Ancak bir süre sonra zamanlama, logging ve kaçırılan çalışmaları yönetmek zorlaştı. Systemd timer’lara geçince, işleri daha kontrollü, izlenebilir ve güvenli hale getirdim. Aşağıda gerçek dünyada işe yarayan adımları, örnek unit dosyalarını ve dikkat edilmesi gereken noktaları paylaşıyorum.
Neden systemd timer?
Benim için üç ana sebep öne çıktı: merkezi loglama (journal), boot sonrası kaçırılan görevleri yakalama (Persistent=yes) ve birim bazında izin/çalışma ortamı tanımlama (User=, Environment=). Ayrıca timer’lar OnCalendar/OnBootSec gibi esnek tetikleyiciler sunuyor; yani sadece cron benzeri zamanlama değil, sistem olaylarına bağlanan işlemler de kolaylaşıyor.
Temel yapı: .service ve .timer
Her scheduled iş iki dosyayla modellenir: bir .service (yapılacak iş) ve onu hangi zamanlarda tetikleyeceğini söyleyen .timer. Basit bir örnek veriyorum.
# /etc/systemd/system/backup-db.service
[Unit]
Description=Günlük veritabanı yedeği
[Service]
Type=oneshot
User=backup
Group=backup
EnvironmentFile=/etc/default/backup-db
ExecStart=/usr/local/bin/backup-db.sh
TimeoutStartSec=1800
# /etc/systemd/system/backup-db.timer
[Unit]
Description=Günlük veritabanı yedeği timer
[Timer]
OnCalendar=*-*-* 02:30:00
Persistent=true
RandomizedDelaySec=600
[Install]
WantedBy=timers.target
Açıklamalar kısaca: Persistent=true sistem kapalıyken kaçırılan tetiklemeyi tekrar çalıştırır; RandomizedDelaySec aynı anda çok sayıda sunucuda çakışmayı azaltır; TimeoutStartSec uzun çalışan işlemleri sınırlar.
Cron’dan geçiş adımları (pratik sıra)
- 1) Cron girdilerini envanterle:
crontab -l,/etc/cron.*ve servis hesabı crontab’larını topla. - 2) Her komut için bir servis dosyası tasarla; komutu doğrudan
ExecStartiçine koyma — wrapper script kullan. Bu, ortam değişkenleri ve loglama için temiz olur. - 3) Zamanlamayı timer’a çevir: cron zamanını OnCalendar veya OnActiveSec ile eşleştir. (Ör: her gece 02:30 için
OnCalendar=*-*-* 02:30:00.) - 4) Persistent ihtiyacını değerlendir. Kaçırılan çalışmaları çalıştırmak istiyorsan
Persistent=yesekle. - 5) Overlap (üst üste çalışma) kontrolü ekle: systemd’nin yerleşik tekil çalıştırma kontrolü sınırlı olduğu için flock kullan; wrapper içinde
flock -n /var/lock/myjob.lockşeklinde kilitle. - 6) Yükle, test et ve izlemeye al:
systemctl daemon-reload,systemctl enable --now myjob.timer, sonrasystemctl list-timers --allvejournalctl -u myjob.service -f.
Çakışma ve tekil çalıştırma (concurrency) yönetimi
Ben genelde flock kullanıyorum çünkü güvenilir ve basit. Service içinde şöyle:
ExecStart=/usr/bin/flock -n /var/lock/backup-db.lock /usr/local/bin/backup-db.sh
Eğer flock yoksa, script içinde PID file kontrolü veya systemd’nin RuntimeMaxSec ile zaman sınırı eklemek ikinci tercihim. Ancak gerçek tekil-lock için flock en pratiktir.
Loglama ve hata takibi
Artık her iş journal’a yazılıyor. Hızlı kontroller için benim kullandığım komutlar:
systemctl list-timers --all --no-pager
systemctl status backup-db.timer backup-db.service
journalctl -u backup-db.service -n 200 -f
Hatalı durumlarda servis çıkış kodunu ve journalctl -u çıktısını inceleyin. İhtiyaç varsa service içine StandardOutput=append:/var/log/myjob.log ile ilave dosya logu tutabilirsiniz (ama merkezi journal tercih edilir).
Kullanıcı seviyesinde timer’lar
Systemd kullanıcı timer’ları da var: --user ile yönetilir. Masaüstü araçları veya kullanıcının cron işlerini migrate ederken kullanışlıdır. Unutmayın: user timers için enable/ start yaparken systemctl --user enable --now myjob.timer kullanın ve kullanıcı oturumunun systemd user instance’ının aktif olduğunu doğrulayın.
Pratik ipuçları ve sık yapılan hatalar
- Timezone farklarını netleyin: OnCalendar genelde sistem saat dilimini kullanır; kritik zamanlarda TZ belirtin veya UTC standardı benimseyin.
- Çevresel değişkenleri
EnvironmentFileile yönetin; unit içine uzun env yazmaktan kaçının. - Daemon-reload unutmayın; birimleri değiştirdikten sonra
systemctl daemon-reloadgerekli. - Karmaşık zincirlerde
Wants=veyaAfter=ile bağımlılık tanımlayın (ör. network-online.target). - Timer’ı başlatmadan önce hizmeti manuel çalıştırıp çıktıyı kontrol edin; hatayı erken yakalarsınız.
Kapanış olarak: cron’ı tamamen kötülemiyorum — küçük, tek seferlik makinelerde hâlâ işe yarıyor. Ama üretim sınıfında izlenebilirlik, hata kurtarma ve yönetilebilirlik istiyorsanız systemd timer’lar bana göre daha sürdürülebilir bir çözüm oldu. Birkaç basit wrapper script ve bir çift unit dosyasıyla sisteminizin zamanlanmış işler katmanını epey sağlamlaştırırsınız. Benim geçişimde en çok işe yarayan şey: ilk hafta loglara bakmaya vakit ayırmak oldu — orada göreceğiniz küçük hatalar, ileride büyük işler kaybetmenizi engeller.