Linux’ta Bash Betiklerinde `sleep` Komutunun Kullanımı
Linux’ta `sleep` komutu, `sleep [NUMBER][SUFFIX]` sözdizimini kullanarak saniye, dakika, saat veya gün cinsinden belirtilen kesin bir süre boyunca betik yürütmesini askıya alır. Harici zamanlayıcılar gerektirmeden hız sınırlama, yeniden deneme mantığı, süreç senkronizasyonu ve zamanlanmış otomasyon sağlayan Bash betik yazımındaki en kritik temel işlemlerden biridir.
Cron veya `at`’ın aksine, `sleep` tamamen betiğin kendi süreç bağlamında çalışır; bu da gecikmenin mutlak bir duvar saati zamanına değil, önceki komutun tamamlanmasına göre göreli olması gerektiğinde doğru araç olmasını sağlar.
Sözdizimi ve Zaman Birimi Referansı
“`bash
sleep NUMBER[SUFFIX]
“`
| Son Ek | Birim | Örnek | Saniye Cinsinden Karşılığı |
|---|
| ——– | ——— | —————- | ———————– |
|---|
| `s` | Saniye | `sleep 30s` | 30 |
|---|
| `m` | Dakika | `sleep 5m` | 300 |
|---|
| `h` | Saat | `sleep 2h` | 7200 |
|---|
| `d` | Gün | `sleep 1d` | 86400 |
|---|
| (yok) | Saniye | `sleep 10` | 10 |
|---|
Son ek isteğe bağlıdır. Belirtilmediğinde birim varsayılan olarak saniyeye döner. GNU/Linux sistemlerinde (GNU coreutils), `sleep` ayrıca ondalıklı değerleri ve birden fazla argümanı kabul eder — GNU coreutils Homebrew aracılığıyla kurulmadıkça BSD ve macOS uygulamalarında bulunmayan bir özelliktir.
“`bash
GNU coreutils: both of these are valid
sleep 1.5
sleep 1m 30s # Equivalent to 90 seconds
“`
Kritik taşınabilirlik notu: POSIX yalnızca son ek olmaksızın tam sayı saniyelerini zorunlu kılar. Betiğinizin Alpine Linux (BusyBox), macOS veya AIX üzerinde çalışması gerekiyorsa kendinizi `sleep INTEGER` ile sınırlayın ve birden fazla argüman zincirlemeyi önleyin.
Bash Betiklerinde Temel Kullanım Senaryoları
1. Komutlar Arasında Sıralı Gecikme
En basit uygulama — ikinci komutun gerçek dünya koşulunun yerleşmesi için zaman geçmeden başlamaması gereken iki işlem arasına duraklama eklemek:
“`bash
#!/bin/bash
echo "Restarting nginx…"
systemctl restart nginx
sleep 3
systemctl status nginx
“`
Buradaki 3 saniyelik duraklama, servis yöneticisinin asenkron başlatma dizisini hesaba katar. Bu olmadan, `status` süreç tam olarak başlatılmadan önce yakalanan eski bir durumu raporlayabilir.
2. Üstel Geri Çekilmeli Yoklama Döngüsü
Sabit aralıklı naif bir yeniden deneme döngüsü kaynakları boşa harcar ve zorlanan bir aşağı akış servisindeki yükü artırabilir. Doğru kalıp titreme ile üstel geri çekilmedir:
“`bash
#!/bin/bash
MAX_RETRIES=6
DELAY=2
for (( attempt=1; attempt<=MAX_RETRIES; attempt++ )); do
if curl -sf https://api.example.com/health > /dev/null; then
echo "Service healthy on attempt $attempt."
exit 0
fi
echo "Attempt $attempt failed. Retrying in ${DELAY}s…"
sleep "$DELAY"
DELAY=$(( DELAY * 2 ))
done
echo "Service unreachable after $MAX_RETRIES attempts." >&2
exit 1
“`
Bu, her başarısızlıkta bekleme süresini iki katına çıkarır: 2s, 4s, 8s, 16s, 32s, 64s. Vazgeçmeden önceki toplam maksimum bekleme süresi 126 saniyedir. Bu kalıp, üretim dağıtım betiklerinde, sağlık kontrollerinde ve CI/CD boru hatlarında standarttır.
3. Hız Sınırlı API Çağrıları
İstek kotaları uygulayan API’lerle etkileşim kurarken, `sleep` gerekli istekler arası aralığı zorlar:
“`bash
#!/bin/bash
API_KEY="your_key_here"
ENDPOINTS=("users" "orders" "products" "inventory")
for endpoint in "${ENDPOINTS[@]}"; do
curl -s -H "Authorization: Bearer $API_KEY"
"https://api.example.com/v1/${endpoint}"
-o "${endpoint}.json"
echo "Fetched: $endpoint"
sleep 1 # Respect 1 req/sec rate limit
done
“`
4. Zamanlanmış Arka Plan Görev Yürütme
Mevcut kabuk oturumunu engellemeden gecikmeli bir komut çalıştırmak, `sleep`’ı alt kabuk arka planlamasıyla birleştirmeyi gerektirir:
“`bash
Trigger a cache flush 60 seconds after deployment completes
( sleep 60 && redis-cli FLUSHDB ) &
echo "Cache flush scheduled. PID: $!"
“`
`$!` değişkeni, arka plan alt kabuğunun PID’ini yakalar; görevin iptal edilmesi gerekirse daha sonra `wait` veya `kill` ile kullanabilirsiniz.
5. Bekçi ve Süreç İzleme Döngüsü
“`bash
#!/bin/bash
SERVICE="mysqld"
CHECK_INTERVAL=30
while true; do
if ! pgrep -x "$SERVICE" > /dev/null; then
echo "$(date '+%Y-%m-%d %H:%M:%S') $SERVICE not running. Restarting…"
>> /var/log/watchdog.log
systemctl start "$SERVICE"
fi
sleep "$CHECK_INTERVAL"
done
“`
Bu kalıp, tam bir denetleyici arka plan programının (systemd, supervisord, s6) mevcut olmadığı veya uygun olmadığı durumlarda hafif süreç denetiminde kullanılır — konteynerleştirilmiş ortamlarda veya minimal VPS Hosting örneklerinde yaygındır.
6. Kullanıcı Geri Bildirimiyle Geri Sayım Zamanlayıcısı
Operatörün kalan bekleme süresini görmesi gereken etkileşimli betikler için:
“`bash
#!/bin/bash
COUNTDOWN=10
echo "Starting in:"
for (( i=COUNTDOWN; i>=1; i– )); do
printf "r%2d seconds remaining…" "$i"
sleep 1
done
printf "rGo! n"
“`
`printf "r"` yeni satırlar eklemek yerine mevcut satırın üzerine yazar ve temiz bir terminal geri sayımı üretir.
`sleep` ile Alternatif Zamanlama Mekanizmaları Karşılaştırması
| Mekanizma | Ayrıntı Düzeyi | Kabuğu Engeller | Mutlak Zaman | Kullanım Senaryosu |
|---|
| —————– | —————– | ————– | ————— | ———————————————– |
|---|
| `sleep` | Saniyenin altı (GNU) | Evet (`&` olmadıkça) | Hayır | Betikler içinde göreli gecikmeler |
|---|
| `cron` | 1 dakika | Hayır | Evet | Yinelenen zamanlanmış işler |
|---|
| `at` | 1 dakika | Hayır | Evet | Tek seferlik gelecek yürütme |
|---|
| `systemd timer` | 1 saniye | Hayır | Evet | Kalıcı, günlüklü, bağımlılık farkında işler |
|---|
| `usleep` (C) | Mikrosaniye | Evet | Hayır | Çekirdek/C düzeyinde hassasiyet (Bash’e özgü değil) |
|---|
| `read -t` | Saniyenin altı | Evet | Hayır | İsteğe bağlı kullanıcı girişiyle zaman aşımı |
|---|
`read -t` yerine `sleep` ne zaman kullanılmalı: Betiğinizin duraklaması ancak kullanıcının bekleme sırasında kesintiye uğramasına veya yanıt vermesine izin vermesi gerekiyorsa, `read -t SECONDS` doğru temel işlemdir. Zaman aşımında çıkış kodu 1, kullanıcı Enter’a basarsa 0 döndürür; ayrı bir süreç olmadan koşullu mantık sağlar.
“`bash
echo "Press Enter to skip the 10-second wait, or wait for automatic continuation."
read -t 10 -r || true
echo "Continuing…"
“`
Hassasiyet, Ondalıklı Sayılar ve Platform Davranışı
GNU `sleep` ondalık kesirleri kabul eder; bu, animasyonları yönlendiren, günlük izlemeyi kısıtlayan veya gerçek zamanlı veri akışlarını simüle eden betikler için önemlidir:
“`bash
Tail a log file and print one line per 0.2 seconds (5 lines/sec)
while IFS= read -r line; do
echo "$line"
sleep 0.2
done < /var/log/app.log
“`
Gerçek uyku süresi bir minimum değerdir, garanti değildir. Çekirdek zamanlayıcısı, sistem yüküne ve zamanlayıcı çözünürlüğüne (`CONFIG_HZ`) bağlı olarak süreci biraz geç uyandırabilir. Düzinelerce eşzamanlı süreç çalıştıran yoğuk yüklü bir Dedicated Server‘da, `sleep 0.1` aslında 0,11–0,15 saniye duraklatabilir. Bu kaymanın kabul edilemez olduğu betikler için monoton saat referansı kullanın:
“`bash
#!/bin/bash
INTERVAL=5
NEXT=$(date +%s%N) # Current time in nanoseconds
while true; do
NEXT=$(( NEXT + INTERVAL * 1000000000 ))
do_work
NOW=$(date +%s%N)
REMAINING=$(( (NEXT – NOW) / 1000000 )) # Convert to milliseconds
[ "$REMAINING" -gt 0 ] && sleep "$(echo "scale=3; $REMAINING/1000" | bc)"
done
“`
Bu kayma telafi eden döngü, `do_work`’ın ne kadar sürdüğünden bağımsız olarak tutarlı bir aralık korur.
Sinyal İşleme ve `sleep`’ı Kesintiye Uğratma
Çalışan bir `sleep` süreci sinyallere yanıt verir. Sleep sürecine `SIGALRM` göndermek onu hemen uyandırır. Daha pratik olarak, `Ctrl+C` tuşuna basmak tüm süreç grubuna `SIGINT` gönderir ve hem betiği hem de ön plandaki `sleep`’ı sonlandırır.
Bir betiğin uyku sırasında kesintileri temiz bir şekilde işlemesi için:
“`bash
#!/bin/bash
cleanup() {
echo "Interrupted. Cleaning up…"
exit 1
}
trap cleanup SIGINT SIGTERM
echo "Waiting 60 seconds…"
sleep 60 &
SLEEP_PID=$!
wait "$SLEEP_PID"
echo "Wait complete."
“`
`sleep`’ı arka plana alarak ve `wait` kullanarak, `trap` uyku tamamlanana kadar ertelenmek yerine `SIGINT` üzerine hemen tetiklenir. Bu, üretim sunucularındaki uzun süreli otomasyon betikleri için doğru kalıptır.
Pratik Tuzaklar ve Uç Durumlar
Tuzak 1: `sleep`’ı sonlanma koşulu olmayan sıkı döngülerde kullanmak. Çıkış yolu olmayan `while true; do sleep 1; done` döngüsü süresiz çalışır, bir süreç yuvası tüketir ve `ps` çıktısında birikir. Her zaman maksimum yineleme sayısı veya bir sentinel koşulu tanımlayın.
Tuzak 2: `sleep`’ın alt kabuklar ile senkron olduğunu varsaymak. `&` ile bir alt kabuk çatalladığınızda, açıkça `wait` çağırmadıkça üst betik alt kabuğun `sleep`’ının tamamlanmasını beklemez. Bu, paralel dağıtım betiklerinde yarış koşullarına neden olur.
Tuzak 3: Servis hazırlığı için gecikmeleri sabit kodlamak. Bir servisi başlattıktan sonra `sleep 5` kullanmak kırılgandır. Servis 1 saniyede hazır olabilir veya yük altında 30 saniye alabilir. Sağlam alternatif bir hazırlık yoklamasıdır:
“`bash
#!/bin/bash
wait_for_port() {
local host="$1" port="$2" timeout="${3:-30}"
local elapsed=0
until nc -z "$host" "$port" 2>/dev/null; do
[ "$elapsed" -ge "$timeout" ] && return 1
sleep 1
(( elapsed++ ))
done
}
systemctl start postgresql
wait_for_port localhost 5432 30 && echo "PostgreSQL ready."
“`
Tuzak 4: BusyBox sistemlerinde ondalıklı sleep. Alpine Linux konteynerleri, ondalık sayıları desteklemeyen BusyBox’ın `sleep` uygulamasını kullanır. `sleep 0.5` denemesi hata verecektir. Saniyenin altı hassasiyete dayanan betikleri dağıtmadan önce ortamınızı doğrulayın.
`sleep`’ı Otomatik Sunucu İş Akışlarına Entegre Etme
Yönetilen bir cPanel’li VPS‘te, otomatik bakım betikleri dakika altı zamanlama uygulamak için sıklıkla `sleep`’ı cron ile birleştirir. Cron’un minimum çözünürlüğü bir dakika olduğundan, 15 saniyelik aralıkları şu şekilde elde edebilirsiniz:
“`bash
crontab entry — runs the script 4 times per minute
- * * * * /usr/local/bin/check_queue.sh
- * * * * sleep 15 && /usr/local/bin/check_queue.sh
- * * * * sleep 30 && /usr/local/bin/check_queue.sh
- * * * * sleep 45 && /usr/local/bin/check_queue.sh
“`
Bu teknik, özel bir iş zamanlayıcısı kurmanın izin verilmediği paylaşımlı altyapıda kuyruk işlemcileri, sağlık kontrolleri ve metrik toplayıcılar için yaygın olarak kullanılır.
SSL sertifika yenileme betikleri için, ACME zorluğu yayılımının CA’nın sahipliği doğrulayabilmesi için DNS TTL’nin sona ermesini gerektirdiğinde `sleep` denemeler arası gecikmeyi sağlar. Sertifikaları kendi altyapınızda yönetiyorsanız, otomatik yenileme boru hatlarına sahip SSL Sertifikaları hassas şekilde ayarlanmış yeniden deneme aralıklarından yararlanır.
Benzer şekilde, Domain Kaydı aracılığıyla kayıtları güncelledikten sonra kullanışlı olan alan adı yayılım doğrulama betikleri, beklenen TTL değerleriyle hizalanmış aralıklarla DNS çözümleyicilerini yoklamak için `sleep` döngülerini kullanır.
Karar Matrisi: Doğru Gecikme Stratejisini Seçme
| Senaryo | Önerilen Yaklaşım |
|---|
| ———————————————– | ————————————————— |
|---|
| İki sıralı komut arasında sabit duraklama | `sleep N` |
|---|
| Başarıya kadar yeniden dene, sürü etkisini önle | `sleep` ile üstel geri çekilme |
|---|
| Her N dakikada bir yinelenen görev | `cron` (`sleep` değil) |
|---|
| Dakika altı yinelenen görev | `cron` + `sleep` ofset hilesi |
|---|
| Terminali engellemeden gecikme | `( sleep N && command ) &` |
|---|
| Kullanıcı kesme özelliğiyle duraklama | `sleep N &` + `wait $!` + `trap` |
|---|
| Servis hazırlık kontrolü | Her deneme için `sleep 1` ile port/sağlık yoklama döngüsü |
|---|
| Yüksek hassasiyetli aralık (kayma telafili) | Hesaplanmış `sleep` ile monoton saat referansı |
|---|
| Alpine/BusyBox’ta saniyenin altı gecikme | Kaçının; tam sayı saniyeler kullanın veya temel imajı değiştirin |
|---|
Temel Teknik Çıkarımlar
- Değişken ondalık içerdiğinde sözcük bölme hatalarını önlemek için `sleep "$VARIABLE"`’ı her zaman çift tırnak içinde kullanın.
- Uzun süreli bakım betiklerinde okunabilirlik için `sleep 90` yerine `sleep 1m 30s` tercih edin.
- Betiğinizin duraklama sırasında sinyallere yanıt vermesi gerektiğinde `sleep`’ı `wait` ve `trap` ile arka plana alın.
- Uygun bir hazırlık kontrolünün yerine asla sabit kodlanmış `sleep` kullanmayın — zaman aşımlı bir yoklama döngüsü kullanın.
- Ondalıklı veya çok argümanlı sözdizimi kullanan betikleri dağıtmadan önce hedef işletim sisteminde `sleep` davranışını doğrulayın.
- Üretim sunucularında, olay sonrası analizde zamanlayıcı kaymasını tespit etmek için uzun `sleep` çağrılarından önce ve sonra zaman damgasını günlüğe kaydedin.
- VPS Kontrol Panelleri üzerinde otomasyon oluştururken, `sleep` mantığını manuel olarak eklemeden önce panelin görev zamanlayıcısının zaten aralık kontrolü sağlayıp sağlamadığını doğrulayın.
SSS
`sleep` beklerken CPU tüketir mi?
Hayır. `sleep`, çekirdek düzeyinde `nanosleep()` (veya eşdeğerini) çağırarak süreci kesintiye uğratılabilir uyku durumuna (`ps` çıktısında `S`) alır. Bekleme sırasında CPU döngüsü tüketmez — yalnızca süreç tablosundaki süreç girişi için küçük miktarda bellek kullanır.
`sleep` tarafından kabul edilen maksimum değer nedir?
GNU/Linux’ta `sleep`, pratik amaçlar için etkin biçimde sınırsız olan `double` kayan noktalı sayının sınırlarına kadar değerleri kabul eder. `sleep 1d` (86400 saniye) yaygındır; `sleep 365d` geçerlidir. Pratik sınır sistem çalışma süresidir.
Docker konteynerimde `sleep 0.5` neden başarısız oluyor?
Alpine Linux, yalnızca tam sayı saniyelerini kabul eden BusyBox’ı kullanır ve `sleep` uygulaması ondalık desteği sunmaz. Debian veya Ubuntu temel imajına geçin ya da ondalık desteği etkinleştirmek için GNU coreutils (`apk add coreutils`) kurun.
Arka planda çalışan bir `sleep` sürecini iptal edebilir miyim?
Evet. Arka plana aldıktan hemen sonra PID’ini `SLEEP_PID=$!` ile yakalayın, ardından sonlandırmak için `kill "$SLEEP_PID"` kullanın. `( sleep N && command ) &` kullandıysanız, alt kabuk PID’ini öldürmek sonraki komutun çalışmasını da engelleyecektir.
`sleep`, bir `systemd` servis biriminin `ExecStart` betiğinde kullanmak güvenli midir?
Evet, ancak uyarılarla birlikte. Servis biriminde `TimeoutStartSec` ayarlanmışsa, başlatma sırasında uzun bir `sleep` systemd’nin servisi başarısız başlatma olarak öldürmesine neden olur. Başlatma sonrası gecikmeler için hazırlık yoklamasıyla `ExecStartPost` kullanın ya da başlatmayı ertelemek için `sleep`’a güvenmek yerine uygun PID dosyası yönetimiyle `Type=forking`’ı yapılandırın.
