Temizleme ve Sinyaller için Trap İşleyicileri
Geçici dosyaları kaldırmak ve kısmen tamamlanan işleri güvenilir biçimde geri almak için EXIT, ERR ve INT trap'lerini kaydedin.
Temizleme ve Sinyaller için Trap İşleyicileri, CoddyKit'te ücretsiz bir Linux Command Line & Bash Scripting Mastery dersidir. Bu, 4 dersinin 2. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, Linux Command Line & Bash Scripting Mastery öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. Linux Command Line & Bash Scripting Mastery kursu toplamda 4 dersten oluşur.
Tuzak İşleyicileri Neden Önemlidir
Bir Bash betiği normal olarak, bir hata nedeniyle veya kullanıcının Ctrl+C tuşlarına basması sonucunda çıktığında geride geçici dosyalar, yarım yazılmış veriler ya da bozulmuş durum bırakabilir. Temizleme yapılmazsa bu kalıntılar birikir ve hata ayıklaması zor sorunlara yol açar.
Tuzak işleyicileri, Bash'in belirli bir sinyal veya sözde sinyal alındığında otomatik olarak çalıştırdığı bir işlevi ya da komutu kaydederek bu sorunu çözer.
- EXIT — betik herhangi bir nedenle her çıktığında çalışır
- ERR — herhangi bir komut sıfır olmayan bir çıkış durumu döndürdükten sonra çalışır
- INT — kullanıcı SIGINT (Ctrl+C) gönderdiğinde çalışır
- TERM — SIGTERM geldiğinde çalışır (örneğin
killkomutundan)
İyi yazılmış bir betik, bu tuzakları riskli işlemler başlamadan önce en üstte kaydeder.
trap Yerleşik Komutunun Sözdizimi
trap yerleşik komutu, bir veya daha fazla sinyal ya da sözde sinyal için bir işleyici kaydeder. Genel sözdizimi şöyledir:
trap 'command_or_function' SIGNAL [SIGNAL...]
Temel kurallar:
- İlk bağımsız değişken, sinyal çalıştığında yürütülecek kabuk kodunu (veya bir işlev adını) içeren tırnak içine alınmış bir dizedir.
- İşleyiciden sonra birden fazla sinyal listeleyebilirsiniz.
trap '' SIGNAL, ilgili sinyali yok sayar (boş işleyici).trap - SIGNAL, sinyali varsayılan davranışına sıfırlar.
Tuzaklar aynı kabukta çağrılan işlevler tarafından devralınır; ancak ( ) veya & ile oluşturulan alt kabuklar tarafından devralınmaz.
#!/usr/bin/env bash
# Syntax examples — not a full script
# Register a cleanup function on EXIT
trap cleanup EXIT
# Inline handler for INT and TERM
trap 'echo "Interrupted!"; exit 1' INT TERM
# Ignore SIGHUP
trap '' HUP
# Reset SIGPIPE to default
trap - PIPEEXIT Tuzağı — Güvenlik Ağınız
EXIT sözde sinyali, kaydedilmesi gereken en önemli tuzaktır. Kabuk herhangi bir nedenle çıktığında çalışır: normal tamamlanma, exit N, işlenmeyen bir hata veya bir sinyal. Bu nedenle geçici dosyaları kaldırmak için idealdir.
En iyi uygulama:
- Adı benzersiz ve öngörülemez olsun diye geçici dosyaları
mktempile oluşturun. - Yolu hemen bir değişkende saklayın.
- Temizlemenin her zaman çalışması için oluşturma işleminden hemen sonra EXIT tuzağını kaydedin.
Betiğin çıkış kodu korunur; işleyicinin çıkış kodu, içinde açıkça exit çağırmadığınız sürece yok sayılır.
#!/usr/bin/env bash
set -euo pipefail
TMPFILE=$(mktemp /tmp/myapp.XXXXXX)
cleanup() {
echo "Removing temp file: $TMPFILE" >&2
rm -f "$TMPFILE"
}
trap cleanup EXIT
# Do real work
echo "Processing..." > "$TMPFILE"
sort "$TMPFILE" -o "$TMPFILE"
cp "$TMPFILE" /tmp/myapp_result.txt
echo "Done. Result saved."Birden Fazla Geçici Dosya ve Dizinle Çalışma
Gerçek betikler çoğu zaman birden fazla geçici kaynak oluşturur: dosyalar, dizinler, FIFO'lar ve kilit dosyaları. Her birini ayrı ayrı izlemek yerine hepsini bir dizi içinde toplayıp tek bir temizleme işlevinde kaldırın.
Bu yaklaşım kolayca ölçeklenir: her yeni geçici kaynak oluşturduğunuzda onu diziye ekleyin. EXIT tuzağı, betik nerede çıkarsa çıksın listenin tamamını işler.
#!/usr/bin/env bash
set -euo pipefail
CLEANUP_TARGETS=()
add_cleanup() {
CLEANUP_TARGETS+=("$1")
}
cleanup() {
echo "Running cleanup..." >&2
for target in "${CLEANUP_TARGETS[@]:-}"; do
rm -rf "$target"
echo "Removed: $target" >&2
done
}
trap cleanup EXIT
# Create and track temp resources
TMPDIR_WORK=$(mktemp -d /tmp/work.XXXXXX)
add_cleanup "$TMPDIR_WORK"
TMPFILE_LOG=$(mktemp /tmp/run.XXXXXX.log)
add_cleanup "$TMPFILE_LOG"
echo "Working in $TMPDIR_WORK" | tee "$TMPFILE_LOG"
touch "$TMPDIR_WORK/output.txt"
echo "Step complete."ERR Tuzağı — Başarısızlıkları Yakalama
ERR sözde sinyali, herhangi bir basit komut sıfır olmayan bir çıkış durumu döndürdükten sonra çalışır; bunun için kabuk seçeneği set -e (errexit) etkin olmalı veya komut bir if, while ya da ||/&& bileşiğinin içinde olmamalıdır.
ERR tuzağını şu amaçlarla kullanın:
$LINENOve$BASH_COMMANDkullanarak hangi satırın başarısız olduğunu günlüğe kaydetmek.- EXIT tuzağı çalışmadan önce geri alma mantığını tetiklemek.
- Yapılandırılmış hata iletilerini standart hata akışına göndermek.
Önemli: İşlevlerin çağıran kabuktaki ERR tuzağını devralması için açıkça set -E (errtrace) çalıştırmadığınız sürece ERR tuzakları işlevlerin içinde çalışmaz.
#!/usr/bin/env bash
set -eEuo pipefail
on_error() {
local exit_code=$?
local line=$1
echo "ERROR: command failed with exit code $exit_code at line $line" >&2
echo " Command: $BASH_COMMAND" >&2
}
trap 'on_error $LINENO' ERR
echo "Starting task..."
cp /nonexistent/file /tmp/ # This will fail
echo "This line is never reached."INT Tuzağı — Ctrl+C'yi Uyumlu Biçimde İşleme
Ctrl+C tuşlarına basmak, ön plandaki işlem grubuna SIGINT gönderir. Bir tuzak olmadan Bash hemen çıkar ve geride kısmen tamamlanmış işlemler bırakabilir.
Bir INT tuzağı kaydetmek şunları yapmanızı sağlar:
- Kullanıcı dostu bir iptal iletisi yazdırmak.
- EXIT tuzağına devretmeden önce gerekli ara geri alma işlemlerini gerçekleştirmek.
- Anlamlı bir durum koduyla çıkmak (
130, SIGINT için geleneksel koddur:128 + 2).
INT işleyiciniz tamamlandıktan sonra doğru çıkış kodunu aktarmak için exit 130 çağrısını yapın. Bunun ardından EXIT tuzağı otomatik olarak çalışır.
#!/usr/bin/env bash
set -euo pipefail
TMPFILE=$(mktemp /tmp/demo.XXXXXX)
cleanup() {
rm -f "$TMPFILE"
echo "Temp file removed." >&2
}
on_interrupt() {
echo "" >&2
echo "Caught SIGINT — cancelling gracefully." >&2
exit 130 # EXIT trap (cleanup) runs automatically after this
}
trap cleanup EXIT
trap on_interrupt INT
echo "Running long task. Press Ctrl+C to cancel."
for i in $(seq 1 10); do
echo "Step $i/10..."
sleep 1
done
echo "All steps complete."EXIT, ERR ve INT Tuzaklarını Birleştirme
Üretim betiklerinde, her çıkış yolunu kapsamak için genellikle üç tuzağın tümünü birlikte kaydedersiniz:
- EXIT — her zaman çalışır; dosya temizleme işlemini yürütür.
- ERR — başarısız olan komutu ve satır numarasını günlüğe kaydeder.
- INT — bir iptal iletisi yazdırır ve 130 koduyla çıkar.
EXIT her zaman son çalıştığından, temizleme mantığınızın yalnızca tek bir yerde bulunması yeterlidir. ERR ve INT işleyicileri günlüğe kaydetmeye ve durumu ayarlamaya odaklanabilir, ardından exit çağrısı yaparak gerçek temizleme işlemini EXIT'e devredebilir.
İşlevlerdeki hataların da ERR'yi tetiklemesi ve pipefail seçeneğinin işlem hatlarındaki başarısızlıkları yakalaması için en üstte set -eEuo pipefail kullanın.
#!/usr/bin/env bash
set -eEuo pipefail
TMPFILE=$(mktemp /tmp/combined.XXXXXX)
ROLLBACK_NEEDED=false
cleanup() {
if [[ "$ROLLBACK_NEEDED" == true ]]; then
echo "Rolling back partial changes..." >&2
fi
rm -f "$TMPFILE"
echo "Cleanup done." >&2
}
on_error() {
ROLLBACK_NEEDED=true
echo "ERR at line $1: $BASH_COMMAND" >&2
}
on_interrupt() {
echo "Interrupted by user." >&2
exit 130
}
trap cleanup EXIT
trap 'on_error $LINENO' ERR
trap on_interrupt INT
echo "hello" > "$TMPFILE"
echo "Script finished successfully."Tuzakları Dinamik Olarak Sıfırlama ve Devre Dışı Bırakma
Bazen betiğin ortasında bir tuzağı değiştirmeniz gerekir; örneğin kritik bölüm tamamlandıktan sonra yalnızca bir kez çalışacak bir temizleme işlemi uygulamak ve sonraki normal işlemlerin gereksiz geri alma işlemlerini tetiklemesini önlemek isteyebilirsiniz.
trap - SIGNAL, sinyali yerleşik varsayılan davranışına sıfırlar.trap '' SIGNAL, sinyali tamamen yok sayar (işlem bu sinyalle sonlandırılamaz).- Herhangi bir noktada yeni bir işleyici kaydedebilirsiniz; son
trapçağrısı geçerli olur.
Yaygın bir yaklaşım, riskli bir işlem başarıyla tamamlandıktan sonra EXIT tuzağını geri alma işleyicisinden basit bir temizleme işleyicisine geçirerek güncellemektir.
#!/usr/bin/env bash
set -euo pipefail
TMPFILE=$(mktemp /tmp/staged.XXXXXX)
rollback() {
echo "ROLLBACK: removing $TMPFILE" >&2
rm -f "$TMPFILE"
}
cleanup_only() {
echo "CLEANUP: removing $TMPFILE" >&2
rm -f "$TMPFILE"
}
# Start with rollback in case something fails during the risky phase
trap rollback EXIT
echo "Performing risky operation..."
echo "critical data" > "$TMPFILE"
# ... imagine more risky steps here ...
# Risky phase succeeded — switch to simple cleanup
trap cleanup_only EXIT
echo "Risky phase done. Now doing safe finalization."
cp "$TMPFILE" /tmp/staged_result.txt
echo "All done."Çıkış Kodlarını Tuzaklar Aracılığıyla Aktarma
İnce bir sorun şudur: temizleme işleviniz başarısız olabilecek komutlar içeriyorsa betiğin son çıkış kodunun üzerine yazılabilir. Özgün çıkış kodunu açıkça koruyun.
Bir tuzak işleyicisinin içinde $?, tuzağı tetikleyen çıkış kodunu içerir. Başka herhangi bir komut bu değeri değiştirmeden önce, işleyicinin ilk satırında bu kodu yakalayın.
#!/usr/bin/env bash
set -euo pipefail
TMPFILE=$(mktemp /tmp/exitcode.XXXXXX)
cleanup() {
local original_exit=$? # capture BEFORE any other command
echo "Cleaning up (original exit: $original_exit)" >&2
rm -f "$TMPFILE"
# Exit with the original code so callers see the real result
exit "$original_exit"
}
trap cleanup EXIT
echo "Doing work..."
echo "data" > "$TMPFILE"
# Simulate failure
if [[ ! -f /tmp/required_marker ]]; then
echo "Required marker missing!" >&2
exit 2
fi
echo "Done."İşlevlerde ve Alt Kabuklarda Tuzaklar
Doğru betikler yazmak için tuzakların devralınmasını anlamak kritik öneme sahiptir:
- İşlevler aynı kabukta çalışır ve tuzakları devralır; ancak ERR, yalnızca
set -E(errtrace) etkin olduğunda işlevlere yayılır. - Alt kabuklar (
( ... )), üst kabuğun tuzaklarının bir kopyasıyla başlar; ancak alt kabuktaki değişiklikler üst kabuğu etkilemez. - Arka plan işleri (
cmd &) alt kabuklardır ve üst kabuğun INT/TERM tuzaklarını devralmaz (varsayılan sinyal davranışını kullanırlar).
Pratik kural: tuzak kayıtlarını ana betik gövdesinde tutun, ERR'nin işlevlere yayılması gerektiğinde set -E kullanın ve & üzerinden tuzak devralınmasına asla güvenmeyin.
#!/usr/bin/env bash
set -eEuo pipefail # -E = errtrace: ERR propagates into functions
on_error() {
echo "ERR in function or main at line $1" >&2
}
trap 'on_error $LINENO' ERR
risky_function() {
echo "Inside risky_function"
ls /nonexistent_path # triggers ERR — works because of set -E
}
# Subshell: has its own copy; changes don't affect parent
(
trap '' ERR # disable ERR only inside subshell
ls /nonexistent_path 2>/dev/null || true
echo "Subshell completed without triggering parent ERR"
)
risky_functionGerçek Dünya Yaklaşımı: Atomik Dosya Değiştirme
Klasik bir savunmacı Bash yaklaşımı atomik dosya değiştirmedir: geçici bir dosyaya yazıp ardından dosyayı hedef konumuna yeniden adlandırırsınız. Yeniden adlandırmadan önce herhangi bir şey başarısız olursa özgün dosyaya dokunulmaz. Tuzaklar bu yaklaşımı son derece güvenilir kılar.
Adımlar:
- Geçici dosyayı hedefle aynı dosya sisteminde oluşturun (
mvişleminin atomik olması için). - Erken çıkmamız durumunda geçici dosyayı kaldırmak için EXIT tuzağını kaydedin.
- Yeni içeriği yazın ve doğrulayın.
- Atomik olarak yeniden adlandırın (
mv); özgün dosya yalnızca bu aşamada değiştirilir. - EXIT tuzağı, yalnızca geçici dosya hâlâ varsa onu kaldırır (
mvbaşarıyla tamamlandıktan sonra dosya artık yoktur).
#!/usr/bin/env bash
set -euo pipefail
DEST="/tmp/important_config.conf"
TMPFILE=$(mktemp "$(dirname "$DEST")/.tmp.XXXXXX")
cleanup() {
rm -f "$TMPFILE" # no-op if mv already moved it
}
trap cleanup EXIT
# Write new content to temp file
cat > "$TMPFILE" <<'EOF'
[settings]
version=2
mode=production
EOF
# Validate before replacing
if ! grep -q 'version=' "$TMPFILE"; then
echo "Validation failed — aborting replacement" >&2
exit 1
fi
# Atomic rename — DEST is replaced only here
mv "$TMPFILE" "$DEST"
echo "Config updated atomically: $DEST"Bilgi Kontrolü: ERR Tuzağının Devralınması
ERR tuzağının Bash'teki işlevlerle nasıl davrandığını anlayıp anlamadığınızı test edin.
Özet: Temizleme ve Sinyaller için Tuzak İşleyicileri
Bu derste, tuzak işleyicileri aracılığıyla Bash betiklerini nasıl dayanıklı hâle getireceğinizi öğrendiniz:
- EXIT evrensel güvenlik ağınızdır; herhangi bir geçici kaynak oluşturduktan hemen sonra kaydedin ve özgün çıkış kodunu korumak için her zaman önce
$?değerini yakalayın. - ERR,
$LINENOve$BASH_COMMANDile başarısızlıkları günlüğe kaydetmenizi sağlar; işlevlerin bunu devralması içinset -Ekullanın. - INT, Ctrl+C'yi uyumlu biçimde işler; bir ileti yazdırın ve EXIT'in temizleme yapabilmesi için 130 koduyla çıkın.
- Geçici kaynakları bir dizide toplayın ve hepsini tek bir temizleme işlevinde kaldırın.
- Tuzakları sıfırlamak için
trap - SIGNAL, sinyalleri dinamik olarak yok saymak içintrap '' SIGNALkullanın. - Atomik yeniden adlandırma yaklaşımı (
mktemp→ yazma → doğrulama →mv), EXIT tuzağıyla birlikte kullanıldığında kısmi yazmaların hedef dosyayı hiçbir zaman bozmayacağını garanti eder.
set -eEuo pipefail ile doğru yerlere yerleştirilmiş tuzakları birleştirmek, her üretim Bash betiği için sağlam bir savunmacı temel oluşturur.
Sıkça Sorulan Sorular
“Temizleme ve Sinyaller için Trap İşleyicileri” dersi ücretsiz mi?
Evet — “Temizleme ve Sinyaller için Trap İşleyicileri” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve Linux Command Line & Bash Scripting Mastery kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. Linux Command Line & Bash Scripting Mastery kursu toplamda 4 dersten oluşur.
“Temizleme ve Sinyaller için Trap İşleyicileri” dersinde ne öğreneceğim?
Geçici dosyaları kaldırmak ve kısmen tamamlanan işleri güvenilir biçimde geri almak için EXIT, ERR ve INT trap'lerini kaydedin. Linux Command Line & Bash Scripting Mastery ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.
Linux Command Line & Bash Scripting Mastery öğrenmeye başlamak için deneyim gerekli mi?
Önceden deneyim gerekmez. CoddyKit'te Linux Command Line & Bash Scripting Mastery, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 2. dersidir.
“Temizleme ve Sinyaller için Trap İşleyicileri” dersi ne kadar sürer?
Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.
Bu Linux Command Line & Bash Scripting Mastery dersinde kod yazıp çalıştırabilir miyim?
Evet. Her Linux Command Line & Bash Scripting Mastery dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.
Bu kursun tüm dersleri
- set -euo pipefail ile Katı Mod
- Temizleme ve Sinyaller için Trap İşleyicileri
- Güvenli Geçici Dosyalar ve Kilit Dizinleri
- İdempotent Betikler ve Geri Çekilmeli Yeniden Deneme Mantığı