Sunucu Yönetimi & Linux

    systemd Timer ile Zamanlanmış Görevler

    cron'a modern alternatif olan systemd timer ile görevleri zamanlama, loglama ve yönetme rehberi.

    11 dk okuma Güncellendi: 10 Temmuz 2026

    Bir Linux sunucusunda yedek almak, log dosyalarını temizlemek, sertifika yenilemek ya da bir raporu her sabah üretmek gibi işleri belirli aralıklarla çalıştırmanız gerektiğinde ilk aklınıza gelen araç muhtemelen cron olur. cron on yıllardır güvenle çalışan, sade bir zamanlayıcıdır; ancak modern dağıtımların hepsi artık systemd ile geldiği için elimizin altında çok daha güçlü bir alternatif var: systemd timer'ları. Timer'lar yalnızca "şu saatte şunu çalıştır" demekle kalmaz; görevin çıktısını merkezî bir günlüğe yazar, başka servislere bağımlı hâle getirir, kaçırılan çalışmaları telafi eder ve yükü dağıtmak için rastgele gecikme ekleyebilir.

    Bu rehberde bir systemd timer'ı sıfırdan nasıl kurduğunuzu, .timer ve ona eşlik eden .service dosyasının nasıl yazıldığını, OnCalendar ve OnBootSec sözdizimini, systemctl list-timers ile durumu izlemeyi ve journald üzerinden çıktı takibini adım adım göreceğiz. Örnekler gerçek bir sunucuda kopyalayıp deneyebileceğiniz komutlardan oluşuyor. cron'a alışkınsanız endişelenmeyin; her başlıkta iki dünyayı karşılaştırarak ilerleyeceğiz, böylece geçiş sizin için doğal olacak.

    systemd Timer Nedir ve Neden cron'a Tercih Edilir?#

    systemd timer, belirli bir zamanda ya da belirli bir olaydan sonra bir systemd servisini tetikleyen özel bir birim (unit) türüdür. cron'daki tek satırlık kayıt yerine burada iki dosya vardır: işi tanımlayan bir .service ve onu ne zaman çalıştıracağını söyleyen bir .timer. Bu ayrım ilk bakışta fazladan iş gibi görünse de, size zamanlama mantığı ile görev mantığını birbirinden ayırma özgürlüğü verir. Aynı servisi hem elle (systemctl start) hem de zamanlanmış şekilde çalıştırabilirsiniz.

    Timer'ların cron karşısındaki en somut üstünlüğü loglamadır. cron'da bir görev çalıştığında çıktı ya bir e-postaya gider ya da siz >> /var/log/... yönlendirmesi yazmadıysanız kaybolur. systemd'de ise her çalışma otomatik olarak journald'a düşer; hangi saatte başladı, ne kadar sürdü, çıkış kodu neydi, tüm bunları tek komutla görürsünüz. Bunun dışında bağımlılık yönetimi (bir görevi veritabanı ayağa kalktıktan sonra başlatmak), kaçırılan işleri telafi (Persistent=true) ve yük dağıtımı için rastgele gecikme (RandomizedDelaySec) gibi cron'da elle çözmeniz gereken şeyler burada birer satırlık ayardır.

    Aşağıdaki tablo iki yaklaşımın öne çıkan farklarını özetliyor:

    Özellikcronsystemd timer
    LoglamaElle yönlendirme gerekirjournald'a otomatik
    Kaçırılan çalışma telafisiYokPersistent=true
    Bağımlılık tanımıYokAfter=, Requires=
    Rastgele gecikmeYokRandomizedDelaySec
    Kaynak sınırı (CPU/RAM)Yokcgroup ile MemoryMax vb.
    Görevi elle tetiklemeZorsystemctl start
    Durum görüntülemecrontab -lsystemctl list-timers

    Yine de cron'un yeri var: tek satırlık, basit ve taşınabilir bir görev için hâlâ pratiktir. Klasik cron kullanımını hatırlamak isterseniz Linux'ta cron görevleri rehberimize göz atabilirsiniz. Bu yazıda ise ölçek büyüdükçe timer'ların neden hayat kurtardığını göreceksiniz.

    İlk Timer'ı Oluşturmak: .service ve .timer Dosyaları#

    Bir örnekle başlayalım. Diyelim ki her gece web kök dizinimizin yedeğini alan bir betiğimiz var. Önce görevin ne yapacağını tanımlayan servis dosyasını yazıyoruz. Kullanıcıya özel birimleri /etc/systemd/system/ altına koyuyoruz.

    sudo nano /etc/systemd/system/yedek.service
    

    Servis dosyasının içeriği şöyle olabilir:

    [Unit]
    Description=Web kok dizini gunluk yedegi
    Wants=network-online.target
    After=network-online.target
    
    [Service]
    Type=oneshot
    ExecStart=/usr/local/bin/yedek-al.sh
    User=yedek
    Nice=15
    IOSchedulingClass=idle
    

    Burada dikkat edilmesi gereken en önemli satır Type=oneshot. Bu, servisin bir arka plan hizmeti değil, başlayıp işini bitirip kapanan bir görev olduğunu söyler. Nice ve IOSchedulingClass ile yedeklemenin sunucunun asıl işini yavaşlatmaması için düşük önceliğe alındığına dikkat edin; cron'da bunları betiğin içinde nice/ionice ile sarmalamanız gerekirdi.

    Şimdi bu servisi ne zaman çalıştıracağımızı söyleyen timer dosyasını yazıyoruz. Önemli kural: timer ile servis aynı ada sahip olmalı (uzantı hariç). yedek.timer, yedek.service'i tetikler.

    sudo nano /etc/systemd/system/yedek.timer
    
    [Unit]
    Description=Gunluk yedek gorevini tetikler
    
    [Timer]
    OnCalendar=*-*-* 03:30:00
    Persistent=true
    RandomizedDelaySec=600
    
    [Install]
    WantedBy=timers.target
    

    OnCalendar=*-*-* 03:30:00 her gün saat 03.30'da çalıştır demektir. Persistent=true, sunucu o saatte kapalıysa açılınca kaçırılan çalışmayı hemen telafi eder. RandomizedDelaySec=600 ise gerçek çalışmayı 0 ile 10 dakika arasında rastgele kaydırarak birçok sunucunun aynı anda yük bindirmesini önler. Son olarak [Install] bölümündeki WantedBy=timers.target sayesinde timer, sistem açılışında etkinleşebilir.

    Timer'ı Etkinleştirme ve Yükleme#

    Dosyaları yazdıktan sonra systemd'nin bunları tanıması için birim tanımlarını yeniden yüklemeniz, ardından timer'ı etkinleştirip başlatmanız gerekir. Servisi değil, timer'ı etkinleştirdiğinize dikkat edin; servis, timer tarafından tetiklenecek.

    sudo systemctl daemon-reload
    sudo systemctl enable --now yedek.timer
    

    enable --now iki işi birden yapar: timer'ı açılışta otomatik başlayacak şekilde işaretler ve hemen çalıştırır. Timer'ın durumunu görmek için:

    systemctl status yedek.timer
    

    Görevin gerçekten çalışıp çalışmadığını, zamanlamayı beklemeden test etmek isterseniz servisi elle tetikleyebilirsiniz. Bu, cron'da olmayan çok değerli bir kolaylıktır:

    sudo systemctl start yedek.service
    

    Betiğinizi bu şekilde tetikleyip loglara bakarak her şeyin doğru çalıştığından emin olduktan sonra gerçek zamanlamaya güvenle bırakabilirsiniz. Bir birim dosyasını her değiştirdiğinizde daemon-reload çalıştırmayı unutmayın; aksi hâlde systemd eski tanımı kullanmaya devam eder. Servis birimlerini yönetmenin ayrıntılarına systemd servis yönetimi rehberimizden ulaşabilirsiniz.

    OnCalendar Sözdizimi: Zamanlamanın Kalbi#

    Timer'ların gücünün büyük kısmı OnCalendar ifadesinden gelir. Biçim şudur: haftagünü Yıl-Ay-Gün Saat:Dakika:Saniye. Yıldız (*) "her" anlamına gelir. cron'un beş alanlı diline benzese de daha okunaklı ve daha esnektir. Birkaç yaygın örnek:

    OnCalendar=*-*-* 03:30:00          # her gun 03.30
    OnCalendar=Mon *-*-* 08:00:00      # her pazartesi 08.00
    OnCalendar=*-*-01 00:00:00         # her ayin 1'i gece yarisi
    OnCalendar=*-*-* *:00:00           # her saat basi
    OnCalendar=*-*-* *:0/15:00         # her 15 dakikada bir
    OnCalendar=Mon..Fri 09..18:00:00   # hafta ici 09-18 arasi saat basi
    OnCalendar=weekly                  # her pazartesi 00.00 (kisayol)
    OnCalendar=daily                   # her gun 00.00 (kisayol)
    

    Yazdığınız bir ifadenin tam olarak ne zaman tetikleneceğini merak ediyorsanız, tahmin etmenize gerek yok. systemd-analyze calendar komutu ifadeyi çözümleyip bir sonraki çalışma zamanlarını gösterir:

    systemd-analyze calendar "Mon..Fri 09..18:00:00" --iterations=3
    

    Bu komutun çıktısı ifadenin normalize edilmiş hâlini ve gelecekteki ilk üç tetiklenme anını verir. Karmaşık bir zamanlama kuralı yazmadan önce bunu çalıştırmak, saatlerce süren "neden çalışmadı" hata ayıklamasından sizi kurtarır. weekly, daily, hourly gibi kısayolları da unutmayın; sık kullanılan aralıklar için bunlar hem kısa hem de okunaklıdır.

    Bir noktaya dikkat: OnCalendar varsayılan olarak sunucunun yerel saat dilimini kullanır. UTC istiyorsanız [Timer] bölümüne UTC sonekiyle OnCalendar=*-*-* 03:30:00 UTC yazabilir ya da Persistent ve zaman dilimi davranışını belgelemek için sunucu saatini kontrol edebilirsiniz.

    OnBootSec, OnUnitActiveSec ve Göreli Zamanlayıcılar#

    OnCalendar takvim tabanlıdır; ama bazen "sistem açıldıktan X süre sonra" ya da "bir önceki çalışmadan X süre sonra" gibi göreli zamanlamalar istersiniz. systemd bunun için ayrı yönergeler sunar. En sık kullanılanları OnBootSec (açılıştan sonra) ve OnUnitActiveSec (servisin son etkinleşmesinden sonra) yönergeleridir.

    [Timer]
    OnBootSec=5min
    OnUnitActiveSec=30min
    

    Yukarıdaki timer, sunucu açıldıktan 5 dakika sonra ilk kez, ardından her 30 dakikada bir görevi çalıştırır. Bu, cron'da yazması gerçekten zahmetli olan "açılıştan biraz sonra başla, sonra düzenli aralıklarla devam et" desenini iki satıra indirir. @reboot cron kaydının çok daha kontrollü hâli olarak düşünebilirsiniz; üstelik burada açılıştan tam olarak ne kadar sonra çalışacağını siz belirlersiniz, böylece açılış anındaki yük patlamasına katkı yapmazsınız.

    Göreli ve takvim tabanlı yönergeleri karşılaştıran kısa bir tablo:

    YönergeNe zaman tetiklenir
    OnCalendarTakvimdeki belirli an (03.30, pazartesi vb.)
    OnBootSecSistem açıldıktan sonra geçen süre
    OnStartupSecsystemd yöneticisi başladıktan sonra
    OnActiveSecTimer etkinleştikten sonra
    OnUnitActiveSecHedef servisin son etkinleşmesinden sonra
    OnUnitInactiveSecHedef servis son kez durduktan sonra

    Bir timer içinde bu yönergeleri birlikte kullanabilirsiniz; systemd hepsini değerlendirir ve en yakın tetiklenmeyi seçer. Örneğin bir izleme görevini hem açılıştan sonra hem de düzenli aralıklarla çalıştırmak için OnBootSec ile OnUnitActiveSec'i birlikte tanımlamak yaygın bir yaklaşımdır.

    Aktif Timer'ları Görüntüleme: systemctl list-timers#

    Sunucunuzda hangi timer'ların tanımlı olduğunu, bir sonraki çalışmalarının ne zaman olacağını ve en son ne zaman tetiklendiklerini tek bakışta görmek için systemctl list-timers komutunu kullanırsınız. Bu, cron'daki dağınık crontab -l çıktılarına göre çok daha bilgilendiricidir.

    systemctl list-timers --all
    

    Örnek bir çıktı şuna benzer:

    NEXT                        LEFT       LAST                        PASSED     UNIT           ACTIVATES
    Fri 2026-07-11 03:30:00 +03 8h left    Thu 2026-07-10 03:34:12 +03 19h ago    yedek.timer    yedek.service
    Fri 2026-07-11 00:00:00 +03 5h left    Thu 2026-07-10 00:00:03 +03 19h ago    logrotate.timer logrotate.service
    Fri 2026-07-11 04:12:00 +03 9h left    Thu 2026-07-10 04:09:41 +03 18h ago    certbot.timer  certbot.service
    

    NEXT bir sonraki tetiklenmeyi, LEFT o ana kalan süreyi, LAST son çalışmayı, PASSED üzerinden geçen süreyi, ACTIVATES ise hangi servisi tetiklediğini gösterir. --all bayrağı henüz çalışmamış ya da pasif timer'ları da listeler. Bir görevin neden çalışmadığını araştırırken ilk bakacağınız yer burasıdır; timer görünmüyorsa büyük ihtimalle enable etmeyi ya da daemon-reload çalıştırmayı unutmuşsunuzdur.

    Belirli bir timer'ın tüm ayarlarını, hesaplanmış tetikleme zamanları dâhil görmek isterseniz systemctl show yedek.timer komutu tüm iç değerleri döker. Hata ayıklama sırasında NextElapseUSecRealtime gibi alanlar tam olarak ne zaman çalışacağını netleştirir.

    journald ile Çıktı Takibi ve Loglama#

    Timer'ların en sevdiğim yanı burada başlıyor. Tetiklenen servis her çalıştığında standart çıktısı ve hata çıktısı otomatik olarak journald'a kaydedilir. Görevin loglarını görmek için servisin adını journalctl -u ile sorgularsınız:

    journalctl -u yedek.service
    

    Yalnızca bugünün kayıtlarını, canlı takip modunda görmek isterseniz:

    journalctl -u yedek.service --since today -f
    

    Bu komut cron'da olmayan bir netlik sağlar. Görevin ne zaman başladığını, hangi satırları yazdırdığını, hata olup olmadığını ve çıkış kodunu görürsünüz. Örneğin bir yedekleme betiği exit 1 ile çıktıysa journald bunu Failed with result 'exit-code' olarak işaretler ve list-timers ile birlikte incelediğinizde sorunu hemen fark edersiniz.

    Belirli bir zaman aralığındaki hatalara odaklanmak için önem seviyesine göre filtreleyebilirsiniz:

    journalctl -u yedek.service --since "2026-07-01" --until "2026-07-10" -p err
    

    -p err yalnızca hata ve üstü seviyesindeki kayıtları gösterir. Uzun süredir çalışan sunucularda log birikimini yönetmek için journald'ın kendi rotasyon ayarları (/etc/systemd/journald.conf içindeki SystemMaxUse) devreye girer, dolayısıyla cron'da olduğu gibi log dosyalarınızın diski doldurmasından ayrıca endişelenmezsiniz. Loglama derdi çözülmüş, üstelik merkezî bir yerde toplanmış olur. Bu düzenli çıktı, özellikle birçok görevi paralel yürüten yoğun sunucularda hata ayıklama süresini ciddi biçimde kısaltır.

    Gerçek Dünya Örneği: Sertifika Yenileme ve Bakım Görevleri#

    Teoriyi bir araya getiren pratik bir senaryoyla bitirelim. Diyelim ki WordPress çalıştıran bir sunucuda üç düzenli iş var: SSL sertifikası yenileme kontrolü, veritabanı yedeği ve geçici dosya temizliği. Her biri için bir servis-timer çifti tanımlayabilir, hepsini list-timers üzerinden tek pencereden izleyebilirsiniz. Örneğin veritabanı yedeği için:

    # /etc/systemd/system/db-yedek.service
    [Unit]
    Description=Veritabani gunluk yedegi
    After=mariadb.service
    Requires=mariadb.service
    
    [Service]
    Type=oneshot
    ExecStart=/usr/local/bin/db-yedek.sh
    
    # /etc/systemd/system/db-yedek.timer
    [Timer]
    OnCalendar=*-*-* 02:00:00
    Persistent=true
    RandomizedDelaySec=300
    
    [Install]
    WantedBy=timers.target
    

    Buradaki After=mariadb.service ve Requires=mariadb.service satırları, yedeğin veritabanı hazır olmadan başlamamasını garanti eder; cron'da bu tür bir bağımlılık için betiğin başına "veritabanı ayakta mı" kontrolü yazmanız gerekirdi. Rastgele gecikme sayesinde de birden çok sunucu aynı anda yedek almaya kalkışıp depolama sistemini boğmaz.

    Sunucunuzda kendi yedek ve bakım otomasyonlarınızı kurarken bunları güçlü bir altyapı üzerinde çalıştırmak işin yarısıdır. Yönetimli çözümler için VDS sunucu ve sunucu yönetimi hizmetlerimize, düzenli veri güvenliği için yedekleme çözümlerimize göz atabilirsiniz. WordPress tarafında düzenli bakım otomasyonu isteyenler için WordPress bakım paketlerimiz de bu tür zamanlanmış görevleri sizin yerinize üstlenir.

    Sıkça Sorulan Sorular#

    systemd timer mı cron mu kullanmalıyım?#

    Basit, tek satırlık ve taşınabilir olması gereken görevlerde cron hâlâ pratiktir. Ancak loglama, bağımlılık yönetimi, kaçırılan çalışmaları telafi ve kaynak sınırlama gibi ihtiyaçlarınız varsa systemd timer belirgin şekilde üstündür. Modern sunucularınızda kalıcı ve izlenebilir görevler için timer'ları tercih etmenizi, sadece hızlı ve geçici işler için cron'a başvurmanızı öneririm.

    Timer çalışmıyor, nereden başlamalıyım?#

    İlk olarak systemctl list-timers --all çıktısında timer'ınızın görünüp görünmediğini kontrol edin. Görünmüyorsa büyük olasılıkla systemctl enable --now adımını ya da dosyaları değiştirdikten sonra daemon-reload çalıştırmayı atlamışsınızdır. Timer listede varsa ama servis başarısızsa journalctl -u servis-adi.service ile hata çıktısını inceleyin; çıkış kodu ve hata mesajı sorunun kaynağını çoğu zaman doğrudan gösterir.

    Timer ve service dosyası aynı isimde olmak zorunda mı?#

    Varsayılan davranışta evet, yedek.timer otomatik olarak yedek.service birimini tetikler. Ancak farklı bir servisi tetiklemek isterseniz timer'ın [Timer] bölümüne Unit=baska.service satırını ekleyerek bu bağlantıyı elle belirtebilirsiniz. Genelde adları aynı tutmak yönetimi ve okunabilirliği kolaylaştırdığı için önerilen yaklaşımdır.

    Sunucu kapalıyken kaçan görev sonradan çalışır mı?#

    Timer'ın [Timer] bölümüne Persistent=true yazdıysanız evet. Bu ayar, sunucu tetiklenme anında kapalıysa açılış sonrası kaçırılan çalışmayı bir kez telafi eder. Persistent=false (varsayılan) durumunda ise kaçırılan çalışma atlanır ve yalnızca bir sonraki planlı zamanda tekrar denenir. Yedek gibi kritik görevlerde Persistent=true kullanmanızı tavsiye ederim.

    Timer'ın bir sonraki çalışma zamanını nasıl doğrularım?#

    En pratik yol systemctl list-timers çıktısındaki NEXT ve LEFT sütunlarına bakmaktır. Yazdığınız OnCalendar ifadesinin doğru çözümlendiğinden emin olmak isterseniz systemd-analyze calendar "ifadeniz" --iterations=3 komutunu çalıştırın; bu komut ifadeyi normalize eder ve gelecekteki ilk birkaç tetiklenme anını listeler. Karmaşık zamanlamaları devreye almadan önce bu doğrulamayı yapmak hata riskini büyük ölçüde azaltır.

    Bir timer'ı geçici olarak nasıl durdururum?#

    Timer'ı kalıcı olarak devre dışı bırakmak için sudo systemctl disable --now yedek.timer komutunu kullanabilirsiniz; bu hem çalışan timer'ı durdurur hem de açılışta başlamasını engeller. Yalnızca bu oturumluk durdurmak isterseniz sudo systemctl stop yedek.timer yeterlidir ve sonraki açılışta timer tekrar devreye girer. Değişikliklerden sonra durumu systemctl status yedek.timer ile teyit etmeyi unutmayın.

    Kapanış#

    systemd timer'ları, cron'un sadeliğini korurken ona loglama, bağımlılık, telafi ve yük dağıtımı gibi modern yetenekler ekleyen güçlü bir zamanlama sistemidir. .service ve .timer ikilisini bir kez kavradıktan sonra, sunucunuzdaki tüm zamanlanmış işleri tek bir yerden izlenebilir, hata ayıklanabilir ve güvenilir hâle getirirsiniz. Yedekten sertifika yenilemeye, rapor üretiminden bakım görevlerine kadar her düzenli işi journald çıktısıyla birlikte kontrol altında tutabilirsiniz.

    Bu tür otomasyonları sağlam bir altyapı üzerinde çalıştırmak isterseniz Clou.TR olarak yanınızdayız. Yüksek performanslı sanal sunucu ve VDS çözümlerimizle kök erişimli bir ortamda dilediğiniz timer'ı kurabilir, sunucu yönetimi hizmetimizle bu görevlerin bakımını bize bırakabilir, yedekleme paketlerimizle de verilerinizi güvence altına alabilirsiniz. WordPress siteniz için düzenli bakım otomasyonu arıyorsanız WordPress bakım ve hosting paketlerimizi incelemenizi öneririz. Doğru araçlarla birleştiğinde systemd timer, sunucunuzu kendi kendini yöneten bir sisteme dönüştürür.

    systemdOtomasyonLinux

    Uygulamaya geçmeye hazır mısınız?

    NVMe SSD, ücretsiz SSL ve %99.9 uptime garantisiyle Clou.TR hosting ve sunucu çözümleriyle projenizi hayata geçirin.