Her deploy betiğinin derinliklerinde, bir gün patlamayı bekleyen sessiz bir sh dosyası yaşar. Sorun genellikle eksik hata yönetimidir: bir komut sessizce düşer, betik neşeyle devam eder, sonunda herkes yedeklemenin neden boş olduğunu tartışır. Kaliteli shell betiği, hata yönetimini politika hâline getirir; her satırı bir öncekinin sonucuna güvenerek yazan bir dille çalışır. Bu yazı, o disiplini dört başlıkta toplar.

Sıkılaştırmanın üç satırı

#!/usr/bin/env bash
set -euo pipefail   # hata, tanimsiz degisken, kirik pipeline -> dur
IFS=$'\n\t'         # kelime bolmesini sikilastir

readonly TARGET="/var/backups/app-$(date +%F).tar.gz"
tar -czf "$TARGET" /srv/app

set -e ilk başarısız komutta durur ama kör noktaları vardır: if koşulu içindeki komutları yok sayar, pipeline'da yalnız son halkaya bakar. pipefail bu deliği kapatır; nounset, yazılmamış $DEPLOY_DIR değişkenini boş dizgi yerine hataya çevirir ve en klasik yedekleme felaketini önler. IFS sıkılaştırması ise boşluklu dosya adlarının kelime bölmesini bitirir. Dört satırın her biri, yıllar içinde yüzlerce kazaya yol açmış kalıpları hedef alır.

Temizlik: trap ile çıkışta

Kritik desen temizliktir: betik yarı yolda düşerse geride yarım dosya, kilit dosyası, geçici dizin kalmamalıdır. Yarım kalan yedek, tam yedeksizlikten tehlikelidir; biri onu sağlam sanır.

tmp="$(mktemp -d)"
trap 'rm -rf "$tmp"' EXIT     # normal ya da hatali cikista temizle
readonly LOG="$tmp/run.log"

# Kritik adimlari logla, sonucta durumu raporla
log() { printf '%s %s\n' "$(date +%T)" "$*" >> "$LOG"; }
log "yedekleme basladi: $TARGET"

trap EXIT'te çalışır; hangi yolla çıkarsanız çıkın temizlik garantiye alınır. Sabitlerin readonly yapılması, kritik yolların yanlışlıkla ezilmesini engeller; betik başına cd "$(dirname "$0")" eklemek ise yanlış dizinden çalıştırma sürprizini bitirir. mktemp ile oluşturulan geçici dizin, sabit /tmp isimleriyle yarışan eski kalıbı bitirir. Bir de hata mesajı disiplini vardır: başarısızlıkta yalnız "hata oluştu" yazan bir betik, gece çağrısının süresini uzatır; hangi adımın, hangi girdiyle, neden düştüğünü söyleyen tek satır, saatler kazandırır.

Okunabilirlik de bir güvenlik önlemi

Okunamayan betik incelenemez, incelenmeyen betik güvenilmez. Tek harfli değişkenler, açıklamasız regexp'ler ve iki işi birden yapan satırlar, gözden kaçan rm -rf çağrısının besleyicisidir. Uzun betikleri fonksiyonlara bölün; her fonksiyon tek işi yapsın, adı ne yaptığını söylesin. Her kritik adımın sonucunu zaman damgalı loglayın; üretimde hata ayıklarken log satırları, betiği yeniden çalıştırmaktan değerlidir. Kullanım da bir okunabilirlik meselesidir: betiğin başına usage bloğu koymak, altı ay sonra betiği unutan ilk kişiye (siz) iyi gelir.

Değişkenleri her kullanımda tırnaklayın: tırnaksız $VAR, boşluklu yolları birden çok argümana böler ve word splitting kalıntısı hatalar üretir. shellcheck, bu hataların tamamını derlemesiz yakalar; uyarıları stil önerisi değil, hata adayı olarak okuyun.

Betiğin kendisi de bir üretim varlığıdır; ona göre sürümleyin ve inceleme akışına dahil edin. Deploy betiklerindeki değişiklikler kod kadar ciddi gözden geçirme istemelidir: kritik olmayan bir echo düzenlemesi bile yanlış dizine yazmayı değiştirebilir. Kural basit: üretimi etkileyen her betik, depoda, incelenmiş, sürümlü ve CI'dan geçmiş olmalıdır. Masanızdaki deploy.sh dosyası depoya girmemişse, o betik aslında yoktur — bir gün kaybolacak ya da patlayacaktır.

Özet geçersek kalite standartları soyut bir iddia değil, birkaç satırlık disiplindir: sıkılaştırma bayrakları, trap ile temizlik, readonly sabitler, okunabilir yapı ve CI'da shellcheck. Bu dördü, betiklerinizi "çalışıyor ama kimse nasıl çalıştığını bilmiyor" sınıfından güvenle değiştirilebilir kod sınıfına taşır.