Cron Job Timezone (Zaman Dilimi) Sorunları ve Çözümleri

TimezoneYayın: Güncellendi: 10 dk okumaHazırlayan: cronjob.com.tr Editörleri

Linux sunucularda zamanlanmış görev tanımlarken en sık karşılaşılan can sıkıcı hatalardan biri saat dilimi (timezone) uyuşmazlığıdır. Sabah saat 09:00'da müşterilerinize göndermek istediğiniz bir bülten e-postası sabaha karşı 06:00'da gidebilir ya da gece yarısı çalışması gereken kritik veritabanı yedeğiniz gündüz trafiğinin tam ortasında tetiklenebilir. Bunun temel sebebi, crontab içindeki zaman planının sizin yerel saatiniz ile sunucunun sistem saati arasındaki farkı kendiliğinden bilememesidir.

Klasik bir Linux cron job mekanizması, arka planda çalışan cron arka plan programının (cron daemon - crond) okuduğu sistem saati üzerinden dakikaları sayar. AWS, DigitalOcean, Hetzner veya Linode gibi bulut sağlayıcılarından açılan sanal sunucuların neredeyse tamamı varsayılan olarak UTC (Coordinated Universal Time) saat dilimiyle kurulur. Türkiye yerel saati (TSİ) ise tüm yıl boyunca UTC+3 sabit diliminde yer alır. Bu 3 saatlik fark hesaba katılmadığında UTC sunucuda 09:00 olarak tanımlanan görev Türkiye saatiyle 12:00'de, yani 3 saat geç tetiklenir.

Bu rehberde; cron daemon'un saat dilimini nasıl yorumladığını, timedatectl ile sistem saatinin doğrulanmasını, crontab dosyalarında CRON_TZ ve TZ değişkenlerinin inceliklerini, Docker konteynerlerindeki saat izolasyonunu, yaz saati (DST) risklerini ve saat karmaşasından tamamen kurtulmanın yollarını kapsamlı olarak inceliyoruz.

Cron Zaman Dilimi (Timezone) Mantığı: Sunucu Saati mi, Yerel Saat mi?

Cron arka plan servisi bağımsız bir takvim veya coğrafi konum bilgisine sahip değildir. Sistem her dakikanın 0. saniyesine ulaştığında cron servisi uyanır, geçerli sistem saatini alır ve yüklü crontab dosyalarındaki zaman kalıplarıyla eşleştirir. Eğer bir eşleşme varsa ilgili görevi alt kabukta çalıştırır.

Burada kritik ayrım şudur: Crontab dosyasına yazdığınız 0 9 * * * ifadesi mutlak bir dünya saati değildir; o ifade sadece "sistem saati 09:00 olduğunda çalıştır" anlamına gelir. Sunucunuz UTC saatiyle çalışıyorsa sistem saat 09:00 olduğunda Türkiye'de saat 12:00 olmuştur. Tersine siz Türkiye saatiyle 09:00'da çalışmasını istiyorsanız UTC çalışan bir sunucuda crontab ifadesini 0 6 * * * olarak yazmanız gerekir. İfadelerin doğru kurgulanması için crontab sözdizimi kurallarını iyi bilmek gerekir.

Bu UTC varsayımı yalnızca sunucu cron'una özgü değildir. GitHub Actions'taki schedule bloğundaki cron ifadeleri de varsayılan olarak UTC olarak yorumlanır; bu yüzden Türkiye saatiyle 09:00 hedefleyen bir workflow için UTC karşılığı olan 0 6 * * * yazılır. Tetiklemenin gecikmeye açık olması dahil davranış ayrıntıları GitHub Actions schedule rehberinde anlatılır.

Sunucu ve Donanım Saatini Denetleme (timedatectl)

Zamanlama sorunlarını çözmenin ilk adımı sunucunun o an hangi saat diliminde olduğunu ve zaman senkronizasyonunun (NTP) çalışıp çalışmadığını doğrulamaktır. Modern systemd tabanlı Linux dağıtımlarında bunun için timedatectl aracı kullanılır:

timedatectl

Komutun çıktısı aşağıdaki gibi ayrıntılı bir özet sunar:

               Local time: Thu 2026-10-15 15:30:20 +03
           Universal time: Thu 2026-10-15 12:30:20 UTC
                 RTC time: Thu 2026-10-15 12:30:20
                Time zone: Europe/Istanbul (+03, +0300)
System clock synchronized: yes
              NTP service: active
          RTC in local TZ: no

Bu raporda dört ana satıra dikkat edilmelidir:

Adım Adım Çözüm 1: Crontab İçinde CRON_TZ ve TZ Tanımlama

Sunucunuzun genel sistem saatini UTC olarak bırakmak isteyebilirsiniz; nitekim uluslararası çalışan sunucularda ve mikroservis mimarilerinde sunucu saatini UTC tutmak en iyi güvenlik ve log tutarlılığı pratiğidir. Bu durumda tüm sunucuyu değiştirmeden Cronie gibi bu özelliği destekleyen uygulamalarda belirli bir crontab tablosuna özel saat dilimi tanımlayabilirsiniz; Debian/Ubuntu'nun klasik cron paketinde bu destek bulunmaz.

  1. Crontab Dosyasını Açın: Düzenlemek istediğiniz kullanıcının tablosunu açın:
    crontab -e
  2. CRON_TZ Değişkenini En Başa Ekleyin: Crontab dosyasının ilk satırına hedef saat dilimini yazın.
    CRON_TZ=Europe/Istanbul
    # Artık aşağıdaki tüm satırlar Türkiye saatine göre çalışır
    0 9 * * * /usr/bin/php /var/www/site/artisan bulten:gonder
  3. TZ Ortam Değişkenini Tanımlayın: CRON_TZ zamanlamayı, TZ ise onu kullanan alt süreçlerin saat gösterimini belirler. PHP gibi uygulamaların kendi saat dilimi ayarları da olabilir. Cronie üzerinde iki değişken birlikte tanımlanabilir:
    CRON_TZ=Europe/Istanbul
    TZ=Europe/Istanbul
    0 9 * * * /usr/bin/php /var/www/site/artisan bulten:gonder
  4. Crontab Kaydını Doğrulayın: Debian/Ubuntu ve RHEL sistemlerinde kaydedilen crontab otomatik algılanır; servis yeniden yükleme komutu gerekmez. Kaydı crontab -l ile kontrol edin.

Aynı ayrım Java tarafında da geçerlidir: Spring'in @Scheduled(cron = "0 0 9 * * *") ifadesi (Spring saniye dahil 6 alan bekler) varsayılan olarak JVM'in çalıştığı saat dilimini kullanır; tetikleme saatini sunucudan bağımsız sabitlemek isterseniz zone = "Europe/Istanbul" özniteliğiyle IANA adını açıkça vermelisiniz. Bu davranışın JRE sürümlerine göre incelikleri Java Spring @Scheduled zamanlaması rehberinde örnekleriyle işlenir.

Adım Adım Çözüm 2: Sistem Saat Dilimini Kalıcı Değiştirme

Eğer sunucunuz yalnızca Türkiye lokasyonundaki kullanıcılara hizmet veriyorsa ve tüm sistem loglarının, web sunucusunun ve veritabanının yerel saatle çalışmasını istiyorsanız doğrudan sunucunun saat dilimini değiştirebilirsiniz.

Linux sistemlerde saat dilimi ayarı, /etc/localtime dosyasının /usr/share/zoneinfo/ dizinindeki ilgili bölge dosyasına sembolik bağ (symlink) yapılmasıyla belirlenir. Bu işlemi tek bir komutla güvenli şekilde gerçekleştirebilirsiniz:

sudo timedatectl set-timezone Europe/Istanbul

Bu komut arka planda şu işlemi yapar: Eski /etc/localtime dosyasını siler ve yerine /usr/share/zoneinfo/Europe/Istanbul hedefini gösteren yeni bir sembolik bağ oluşturur. Değişikliğin uygulandığını doğrulamak için:

ls -l /etc/localtime
# Çıktı: /etc/localtime -> /usr/share/zoneinfo/Europe/Istanbul

Sistem saat dilimi değiştikten sonra cron daemon'un yeni zaman dilimini hemen algılaması için servisi yeniden başlatmanız gerekir:

# Ubuntu / Debian
sudo systemctl restart cron

# RHEL / CentOS / Rocky Linux
sudo systemctl restart crond

Docker Konteynerlerinde Cron Timezone Çözümü

Mikroservis mimarilerinde veya Docker cron job yapılarında en sık düşülen tuzak, ana sunucunun saati doğru olsa bile konteynerin varsayılan UTC olarak ayağa kalkmasıdır. Docker container'ları host işletim sisteminin saat dilimini otomatik olarak devralmaz.

Dockerfile içinde Debian/Ubuntu tabanlı bir imaj hazırlarken tzdata paketini kurarak saat dilimini kalıcı hale getirebilirsiniz:

FROM debian:bullseye-slim

ENV DEBIAN_FRONTEND=noninteractive
ENV TZ=Europe/Istanbul

RUN apt-get update && apt-get install -y tzdata cron \
    && ln -snf /usr/share/zoneinfo/$TZ /etc/localtime \
    && echo $TZ > /etc/timezone \
    && dpkg-reconfigure --frontend noninteractive tzdata \
    && apt-get clean

Eğer mevcut bir imajı yeniden derlemeden docker run veya docker-compose ile çalıştırıyorsanız, host makinenin saat dilimini konteyner içine salt okunur (read-only) cilt (volume) olarak bağlayabilirsiniz:

docker run -d \
  -v /etc/localtime:/etc/localtime:ro \
  -v /etc/timezone:/etc/timezone:ro \
  my-cron-app

Konteyner dünyasındaki bu UTC varsayılanı, bulut platformlarının zamanlayıcılarında da karşınıza çıkar: Vercel cron job tanımları da ifadeleri UTC değerlendirir; Türkiye saatiyle 09:00 hedefliyorsanız saati 3 saat geri yazmanız gerekir.

Yaz Saati (DST) Geçişlerinde Yaşanan Saat Sapmaları ve Önlemler

Türkiye 2016 yılından itibaren sabit GMT+3 (yaz saati) uygulamasına geçmiş ve kış saati uygulamasını kaldırmıştır. Ancak Avrupa Birliği, ABD ve İngiltere gibi coğrafyalarda Daylight Saving Time (DST) uygulanmaya devam etmektedir.

Eğer sunucunuz Avrupa veya Amerika saat dilimine (örneğin Europe/London veya America/New_York) ayarlıysa ilkbahar ve sonbahar aylarında iki kritik anomali yaşanır:

Bu sebeple finansal raporlama, faturalama veya veri yedekleme gibi mükerrer çalışmayı kabul etmeyen kritik görevlerde sunucunun UTC olarak yapılandırılması ve zamanlamanın UTC tabanlı yapılması hayati bir mühendislik kuralıdır.

Gerçek Kod Örnekleri

Pratikte kullanabileceğiniz doğrulanmış yapılandırma örnekleri aşağıdadır:

Örnek 1: Cronie Üzerinde CRON_TZ ile Türkiye Saatine Göre Çalışan Crontab Dosyası

# /etc/cron.d/eticaret-gorevleri
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
CRON_TZ=Europe/Istanbul

# Log dosyası www-data tarafından yazılabilir olmalıdır
# Her iş günü Türkiye saatiyle sabah 08:30'da stok güncellemesi yap
30 8 * * 1-5 www-data /usr/bin/php /var/www/site/cron/stok.php >> /var/www/site/stok.log 2>&1

# Her pazar gecesi 23:45'te haftalık rapor oluştur
45 23 * * 0 www-data /usr/bin/python3 /var/www/site/scripts/rapor.py

Örnek 2: Betik İçin Saat Dilimi Tanımlama (Inline TZ)

Eğer kullandığınız cron daemon CRON_TZ değişkenini satır başında desteklemiyorsa, komut önündeki TZ=... yalnızca betiğin saat gösterimini etkiler, tetikleme saatini değiştirmez. Aşağıdaki 06:00 kaydı UTC sunucuda Türkiye saatiyle 09:00'a karşılık gelir:

0 6 * * * TZ=Europe/Istanbul /usr/bin/php /var/www/site/gorev.php

Sık Karşılaşılan Hatalar ve Çözümleri

Saat dilimi uyumsuzluğundan kaynaklanan en popüler problemler ve çözüm yöntemleri:

Hata 1: Cron jobs running 3 hours early/late
Nedeni: Sunucu BIOS/OS saati UTC zaman diliminde kalmıştır ve crontab kullanıcısı yerel saat dilimini belirtmeden görevi planlamıştır.
Çözümü: Sunucu genelinde kalıcı düzeltme için sudo timedatectl set-timezone Europe/Istanbul çalıştırın ya da Cronie gibi destekleyen bir uygulamada crontab başına CRON_TZ=Europe/Istanbul ekleyin.
Hata 2: CRON_TZ not recognized / ignored
Nedeni: Kullanılan cron uygulaması CRON_TZ ile ayrı zamanlamayı desteklemiyor olabilir; Debian/Ubuntu klasik cron paketi bu değişkeni zamanlama için kullanmaz.
Çözümü: Sistem saat dilimini değiştirin veya saat alanını sunucunun saat dilimine göre dönüştürün. Komut önüne TZ=Europe/Istanbul eklemek tetikleme zamanını değiştirmez.
Hata 3: Job skipped during Daylight Saving Time transition
Nedeni: DST kullanan ülkelerde saatlerin 02:00'den 03:00'e alınması sırasında aradaki 60 dakikalık zaman dilimi sistem saatinde hiç yaşanmamıştır.
Çözümü: Kritik görevlerinizi 02:00-03:00 aralığı yerine saat 01:30 veya 03:30'a planlayın ya da zamanlamayı UTC'ye taşıyın; CRON_TZ=UTC yalnızca destekleyen cron uygulamalarında geçerlidir. Görevleriniz hiç tetiklenmiyorsa cron job çalışmıyor rehberimizdeki temel adımları izleyin.
Hata 4: Docker cron container time mismatch
Nedeni: Host makinenin saati yerel olarak ayarlanmışken Docker container'ı izole edilmiş UTC saat diliminde çalışmaktadır.
Çözümü: Konteyneri başlatırken -v /etc/localtime:/etc/localtime:ro parametresini ekleyin veya container ortamına -e TZ=Europe/Istanbul çevre değişkenini tanımlayın.

cronjob.com.tr ile HTTP Tabanlı Alternatif Kurulum (İş Bazında Saat Dilimi)

Farklı sunucularda saat dilimlerini yönetmek, NTP sapmalarını takip etmek ve Docker konteynerlerinde tzdata paketleriyle uğraşmak hem zaman alıcıdır hem de operasyonel hata riskini artırır. Özellikle dağıtık sunucu ortamlarında her makinenin saati birkaç saniye kayabilir veya farklı yapılandırılmış olabilir.

cronjob.com.tr bulut tabanlı zamanlama servisi, tüm saat dilimi karmaşasını ortadan kaldıran modern bir HTTP tetikleme alternatifidir. Platformumuz üzerinde oluşturduğunuz her zamanlanmış görev için doğrudan panelden istediğiniz saat dilimini (varsayılan olarak Europe/Istanbul) seçebilirsiniz. Sunucunuz ister Frankfurt'ta UTC olarak çalışsın, ister Amerika'da EST diliminde olsun; cronjob.com.tr görevinizin zamanlamasını seçtiğiniz saat dilimine göre değerlendirir.

Kayıt olmak tamamen ücretsizdir ve kredi kartı bilgisi talep edilmez. Bir web servisini zamanlamak için şu adımları uygulayabilirsiniz:

Sıkça Sorulan Sorular (SSS)

Crontab varsayılan olarak hangi saat dilimini kullanır?

Cron daemon (crond), crontab dosyası içinde özel bir zaman dilimi belirtilmediği sürece doğrudan sunucu işletim sisteminin geçerli sistem saat dilimini (system timezone) baz alır.

CRON_TZ tüm Linux dağıtımlarında geçerli midir?

Hayır. CRON_TZ, Red Hat, CentOS ve Rocky Linux sistemlerindeki Cronie tarafından desteklenir; Debian/Ubuntu klasik cron paketinde desteklenmez. TZ değişkeni alt sürecin saat gösterimini etkiler, tetikleme saatini değiştirmez.

Sunucu saatini UTC tutmak neden önerilir?

Sunucu saatini UTC olarak yapılandırmak, yaz ve kış saati (DST) geçişlerinde görevlerin mükerrer çalışmasını veya atlanmasını engeller ve dağıtık sunucu mimarilerinde log tutarlılığı sağlar.

Türkiye'de sabit GMT+3 nasıl ayarlanır?

Linux terminalinde sudo timedatectl set-timezone Europe/Istanbul komutunu çalıştırarak sistem saatinizi Türkiye'nin sabit UTC+3 saat dilimine kalıcı olarak ayarlayabilirsiniz.

Hemen Ücretsiz Cron Job Oluşturun

Frankfurt'taki UTC sunucunuzda çalışan bir uç noktayı, cronjob.com.tr panelinde işin saat dilimini Europe/Istanbul seçerek Türkiye saatiyle tetikleyebilirsiniz; her iş için saat dilimi ayrıca belirlenir.

Ücretsiz Başla →

İlgili Rehberler