timeout ve timelimit Komutları ile Süreçlere Çalışma Süresi Kısıtlaması Uygulama
Bir senaryoyu düşünelim: Gece yarısı bir cron job’ınız başlıyor, bir nedenden dolayı takılıp kalıyor ve sabaha kadar sistem kaynaklarını tüketiyor. Ekibiniz sabah ofise geldiğinde sistemi yanık bulduğunuzda yapabileceğiniz pek bir şey kalmıyor. İşte tam bu noktada timeout ve timelimit komutları hayat kurtarıcı oluyor.
Bu araçları öğrenmeden önce yıllarca “işlem bitmedi mi hala?” diye kontrol eden biri olarak söyleyebilirim: Süreç süresi kısıtlaması, production ortamlarda bir lüks değil, bir zorunluluk.
timeout Komutu: Temel Kullanım
timeout, GNU coreutils paketinin bir parçası olarak neredeyse tüm modern Linux dağıtımlarında hazır gelir. Kurulum gerektirmez, hemen kullanabilirsiniz.
En basit kullanımı şu şekilde:
timeout SÜRE KOMUT [ARGÜMANLAR]
Örneğin, bir ping komutunu 5 saniye sonra sonlandırmak için:
timeout 5 ping google.com
5 saniye dolduğunda ping kendiliğinden kesilir. Burada önemli olan şu: timeout varsayılan olarak SIGTERM sinyali gönderir. Yani işleme nazikçe “artık dur” der. İşlem bunu görmezden gelirse ne olur? Orada kalır. Bu yüzden --kill-after seçeneğini de bilmek gerekiyor.
Süre Formatları
timeout komutu süreyi esnek biçimlerde kabul eder:
- 5 veya 5s: 5 saniye
- 5m: 5 dakika
- 2h: 2 saat
- 1d: 1 gün
- 1.5m: 1.5 dakika (ondalık da çalışır)
# 30 saniye
timeout 30 wget https://example.com/buyuk-dosya.zip
# 5 dakika
timeout 5m ./uzun-script.sh
# 2 saat
timeout 2h pg_dump mydb > backup.sql
# Ondalık: 90 saniye
timeout 1.5m curl -O https://example.com/dosya.tar.gz
Sinyal Kontrolü: –signal Seçeneği
Varsayılan olarak SIGTERM gönderildiğini söylemiştim. Ama bazı durumlarda bu yeterli olmaz. Özellikle sinyal yakalayan (trap kullanan) script’lerde veya inatçı süreçlerde SIGKILL göndermek gerekebilir.
# SIGKILL ile anında sonlandır
timeout --signal=SIGKILL 10 ./inatci-proses.sh
# Sinyal numarasıyla da kullanabilirsiniz
timeout --signal=9 10 ./inatci-proses.sh
# SIGINT göndermek (Ctrl+C etkisi)
timeout --signal=SIGINT 30 ./interaktif-script.sh
Burada bir gerçek dünya deneyimimi paylaşayım: Bir müşteri ortamında Java uygulaması başlatma script’i vardı, SIGTERM geldiğinde temiz kapanma (graceful shutdown) yapacak şekilde yazılmıştı. Ama bug yüzünden graceful shutdown sonsuz döngüye giriyordu. --signal=SIGTERM ile başlatıp sonrasında SIGKILL devreye sokmak sorunu çözdü.
–kill-after: İki Aşamalı Sonlandırma
İşte en güçlü kombinasyon: Önce nazikçe sor, dinlemezse zorla kapat.
timeout --kill-after=10s 30s ./script.sh
Bu komut şunu yapar:
- 30 saniye sonra SIGTERM gönderir
- İşlem hala çalışıyorsa 10 saniye daha bekler
- Sonra SIGKILL ile zorla kapatır
Production ortamlarında şu pattern’i çok kullandım:
# 5 dakikada bitmeyen backup script'ini önce nazikçe,
# 30 saniye içinde kapanmazsa zorla sonlandır
timeout --kill-after=30s 5m /opt/scripts/backup.sh
# Web scraper'ı 10 dakikada sınırla
timeout --kill-after=15s 10m python3 scraper.py --url https://example.com
Exit Code ile Durum Kontrolü
timeout komutunun dönüş kodları önemlidir, özellikle script’lerde kullanırken:
- 0: Komut zaman dolmadan başarıyla tamamlandı
- 1-125: Komutun kendi hata kodu
- 124: Zaman aşımı gerçekleşti (timeout devreye girdi)
- 125:
timeoutkomutu kendisi başarısız oldu - 126: Komut çalıştırılamadı (izin sorunu vb.)
- 127: Komut bulunamadı
- 128+n: Sinyal n ile sonlandırıldı
Bunu script’lerde nasıl kullanıyorum:
#!/bin/bash
timeout 60s /opt/scripts/veritabani-yedek.sh
EXIT_CODE=$?
if [ $EXIT_CODE -eq 124 ]; then
echo "UYARI: Yedekleme 60 saniye içinde tamamlanamadı!" |
mail -s "Backup Timeout Alarmı" [email protected]
logger -t backup "TIMEOUT: veritabani-yedek.sh 60 saniyeyi astı"
elif [ $EXIT_CODE -ne 0 ]; then
echo "HATA: Yedekleme $EXIT_CODE koduyla başarısız oldu"
logger -t backup "HATA: veritabani-yedek.sh exit code: $EXIT_CODE"
else
logger -t backup "Yedekleme başarıyla tamamlandı"
fi
–preserve-status: Orijinal Exit Code’u Koru
Bazen zaman aşımı olmasa da timeout’un 124 dönmesini istemeyebilirsiniz, özellikle mevcut monitoring sistemleriyle entegrasyon söz konusuysa. --preserve-status ile işlemin kendi exit code’u korunur:
timeout --preserve-status 30s komut
Bu seçenek özellikle nagios/icinga check script’lerinde çok işe yarıyor. Check script’iniz 2 (CRITICAL) döndürdüğünde, timeout’un bunu 124 ile ezmesini istemezsiniz.
–foreground: Terminal Kontrolü için
Script’ler içinde kullanıyorsanız ve işlemin terminale doğrudan erişmesi gerekiyorsa:
timeout --foreground 30s interaktif-komut
Bu seçenek olmadan bazı interaktif programlar düzgün çalışmayabilir çünkü timeout normalde işlemi bir alt süreç grubu oluşturarak yönetir.
Gerçek Dünya Senaryoları: timeout Kullanım Örnekleri
Cron Job Kontrolü
Cron job’ların kontrolsüz çalışması, sistemlerde gördüğüm en yaygın sorunlardan biri. Bir e-ticaret firmasında her saat başı çalışan bir stok güncelleme scripti vardı. API zaman zaman yanıt vermeyince script askıda kalıyor, bir sonraki çalışma başlıyordu. Sonunda onlarca zombie process oluşuyordu.
# /etc/cron.d/stok-guncelle
# Her saat başı, maksimum 45 dakika çalışsın
0 * * * * root timeout --kill-after=60s 45m /opt/scripts/stok-guncelle.py
# Günlük rapor scripti, 30 dakikada bitmezse alarm ver
30 2 * * * root timeout 30m /opt/scripts/gunluk-rapor.sh ||
echo "Rapor scripti zaman aşımına uğradı" | mail -s "ALARM" [email protected]
API ve Curl İstekleri
# Tek bir URL için 10 saniye
timeout 10s curl -f https://api.example.com/health
# Wget ile dosya indirme, 5 dakika yetmezse iptal
timeout 5m wget --tries=1 https://cdn.example.com/update.tar.gz
# Birden fazla API endpoint kontrolü
for endpoint in auth products orders inventory; do
echo -n "Kontrol ediliyor: $endpoint ... "
if timeout 5s curl -sf "https://api.example.com/$endpoint/health" > /dev/null; then
echo "OK"
else
echo "BAŞARISIZ (timeout veya hata)"
fi
done
Veritabanı Operasyonları
# MySQL dump, 2 saat yetmezse kesinlikle bir şeyler yanlış gidiyordur
timeout --kill-after=5m 2h mysqldump
--single-transaction
--routines
--triggers
production_db > /backup/$(date +%Y%m%d)_production.sql
# PostgreSQL vakum operasyonu
timeout 1h vacuumdb --analyze --verbose mydb
# Redis dump tetikleme ve bekleme
timeout 30s redis-cli BGSAVE
timelimit Komutu: Daha İnce Kontrol
timelimit, timeout‘un daha az bilinen ama bazı senaryolarda daha yetenekli alternatifi. Debian/Ubuntu’da timelimit paketi olarak geliyor, RHEL/CentOS’ta ise EPEL’den kurabilirsiniz.
# Debian/Ubuntu
apt install timelimit
# RHEL/CentOS (EPEL gerekli)
yum install timelimit
timelimit‘in sözdizimi farklı:
timelimit [-pq] [-S sinyal] [-s sinyal] [-T zaman_aşımı] [-t süre] komut
Seçenekler:
- -t süre: Uyarı sinyali gönderilmeden önceki süre (saniye)
- -T süre: Uyarı sinyalinden sonra zorla kapatmaya kadar geçen süre
- -s sinyal: İlk gönderilecek sinyal (varsayılan: SIGTERM, yani 15)
- -S sinyal: İkinci gönderilecek sinyal (varsayılan: SIGKILL, yani 9)
- -p: Üst sürecin PID’ini yazdır
- -q: Sessiz mod, hata mesajlarını bastır
# 30 saniye sonra SIGTERM, 10 saniye sonra SIGKILL
timelimit -t 30 -T 10 ./uzun-script.sh
# 1 dakika sonra SIGTERM, beklemeden SIGKILL (T=0 değil, küçük bir değer)
timelimit -t 60 -T 1 ./proses
# Sessiz mod ile
timelimit -q -t 120 -T 30 python3 hesaplama.py
timeout vs timelimit: Hangisini Kullanmalı?
Her ikisini de aktif kullandığım için pragmatik bir değerlendirme yapabilirim:
timeout için tercih etmeniz gereken durumlar:
- Neredeyse her sistemde hazır kurulu geliyor, taşınabilirlik önemli
- Script’lerde exit code kontrolü yapıyorsunuz
--foregroundveya--preserve-statusgibi özel seçenekler gerekiyor- Basit ve hızlı çözüm yeterli
timelimit için tercih etmeniz gereken durumlar:
- İki farklı sinyal için iki farklı zaman aralığı tanımlamak istiyorsunuz
- Sinyal numaraları üzerinde daha detaylı kontrol gerekiyor
- Legacy sistemlerde veya özel betikler içinde daha okunabilir sözdizimi istiyorsunuz
Açıkçası günümüzde timeout --kill-after kombinasyonu timelimit‘in yerini büyük ölçüde dolduruyor. Ama timelimit hala bazı özel senaryolarda tercih sebebi.
İleri Seviye: timeout’u Paralel İşlemlerle Kullanma
Birden fazla işlemi paralel çalıştırıp hepsine timeout uygulamak istediğinizde:
#!/bin/bash
SUNUCULAR="web01 web02 web03 db01 cache01"
BASARISIZ=()
for sunucu in $SUNUCULAR; do
# Her kontrol için 5 saniye timeout, arka planda çalıştır
timeout 5s ssh -o ConnectTimeout=3 "$sunucu"
"systemctl is-active nginx" &
done
# Tüm arka plan işlemlerini bekle
wait
echo "Tüm kontroller tamamlandı"
Ya da xargs ile daha temiz bir yaklaşım:
echo -e "web01nweb02nweb03" |
xargs -P 5 -I{} timeout 5s
ssh -o ConnectTimeout=3 {} "uptime"
Monitoring Entegrasyonu
timeout‘u Nagios/Zabbix benzeri monitoring sistemleriyle kullanırken dikkat edilmesi gereken bir nokta var: Bazı check komutları kendi timeout mekanizmalarına sahip. Bu durumda iç içe timeout kullanımı karışıklık yaratabilir.
#!/bin/bash
# Nagios uyumlu check script'i
KRITIK_SURE=60
UYARI_SURE=30
# --preserve-status ile timeout check'in exit code'unu ezmesin
timeout --preserve-status ${KRITIK_SURE}s /usr/lib/nagios/plugins/check_http
-H example.com
-u /api/health
-w ${UYARI_SURE}
-c ${KRITIK_SURE}
RESULT=$?
if [ $RESULT -eq 124 ]; then
echo "CRITICAL: Check komutu $KRITIK_SURE saniyede yanıt vermedi"
exit 2
fi
exit $RESULT
Systemd ile Birlikte Kullanım
Systemd servislerinde zaten TimeoutStartSec ve TimeoutStopSec direktifleri var. Ama script tabanlı servislerde iç süreçleri kontrol etmek için timeout faydalı olabilir:
# /etc/systemd/system/veri-isleme.service
[Unit]
Description=Veri İşleme Servisi
After=network.target
[Service]
Type=simple
ExecStart=/bin/bash -c 'timeout --kill-after=30s 4h /opt/scripts/veri-isle.sh'
TimeoutStartSec=60
TimeoutStopSec=120
Restart=on-failure
RestartSec=30
[Install]
WantedBy=multi-user.target
Burada hem systemd’nin kendi timeout mekanizması hem de script içindeki timeout komutu birlikte çalışıyor. Systemd daha üst seviye bir güvence sağlarken, iç timeout script’in kendi mantığını koruyor.
Dikkat Edilmesi Gereken Noktalar
Deneyimlerimden derlediğim bazı kritik notlar:
Sinyal zinciri: timeout bir alt süreç başlatır. Bu alt süreç de kendi alt süreçlerini başlatırsa, SIGTERM sadece doğrudan alt sürece gider. Süreç grubunu hedef almak için --foreground seçeneğini değerlendirin veya süreç grubuna sinyal gönderen özel bir wrapper kullanın.
Sudo ile dikkat: sudo timeout 30s komut ile timeout 30s sudo komut farklı davranır. İlkinde timeout süreci sudo yetkisiyle çalışır, ikincisinde timeout normal kullanıcı yetkisiyle komut üzerine SIGTERM göndermeye çalışır. Eğer komut root olarak çalışıyorsa sinyal gönderilemeyebilir.
Dosya kilitleri: Bir süreç dosya kilidi tutarken SIGKILL ile sonlandırılırsa kilit dosyaları temizlenmeyebilir. Bu durum bir sonraki çalışmada sorun yaratır. Script’lerinizi buna göre tasarlayın, trap kullanarak temizlik yapın.
Log kayıtları: Timeout gerçekleştiğinde bu durumu mutlaka loglayın. Sessizce ölen bir süreç, problem tespitini çok güçleştirir.
# Güvenli bir wrapper örneği
run_with_timeout() {
local SURE=$1
local KOMUT="${@:2}"
timeout --kill-after=30s "$SURE" $KOMUT
local EXIT=$?
if [ $EXIT -eq 124 ]; then
logger -t timeout-wrapper "TIMEOUT: '$KOMUT' komutu $SURE içinde tamamlanamadı"
return 124
fi
return $EXIT
}
# Kullanım
run_with_timeout 5m /opt/scripts/backup.sh
run_with_timeout 30s curl https://api.example.com/data
Sonuç
timeout ve timelimit komutları, sistem yöneticisinin araç kutusunda sessizce ama etkili biçimde yer alması gereken araçlar. Özellikle cron job’lar, API çağrıları ve uzun süren bakım scriptleri söz konusu olduğunda bu araçlar olmadan çalışmak, kontrol edilemez bir risk almak demek.
Pratikte önerim şu: Tüm otomatik görevlerinizi varsayılan olarak timeout ile sarmalayın. “Bu script asla bu kadar uzun sürmez” diye düşündüğünüz şeyler için de bir güvenlik süresi belirleyin. Paranoyak davranmak değil bu, üretim deneyiminin gerektirdiği bir önlem.
timeout --kill-after kombinasyonu çoğu senaryo için yeterli. timelimit ise ikincil sinyal kontrolüne ihtiyaç duyduğunuzda güzel bir alternatif sunuyor. Her iki aracı da tanıyın, hangisinin hangi durumda daha temiz çözüm ürettiğini anlayın ve buna göre tercih yapın.
Son olarak: Bu araçları kullanmaya başladıktan sonra fark edeceğiniz şey, sistemlerinizin ne kadar öngörülemeyen şekillerde davrandığı. Zaman aşımı loglarınızı düzenli inceleyin; neyin ne zaman takıldığı size altyapınız hakkında çok değerli bilgiler verecek.
