---
title: 'Hata Yönetimi'
source: 'https://academia.sh/tr/kurslar/kabuk-programlama/hata-yonetimi'
course: 'Kabuk Programlama'
language: tr
updated: '2026-08-17T18:10:00+00:00'
license: 'CC BY-SA 4.0'
---

# Hata Yönetimi

Katı kip seçenekleri, erken çıkışın kapsamı ve istisnaları, tanımsız değişken denetimi, boru hattı kodu ve hata yakalama kancası.

Betik doğru çıktı üretiyor, ama yalnızca her şey yolunda gittiğinde. Bir komut başarısız
olduğunda rapor yarım kalıyor ve betiğin çıkış kodu bunu bildirmiyor. Tanımsız bir
değişken sessizce boş dizgiye genişliyor. Boru hattının ortasındaki hata görünmüyor.

Kabuğun öntanımlı davranışı hataya karşı hoşgörülüdür: bir komut başarısız olsa da
sonraki komut çalışır. Bu, etkileşimli kullanımda doğru bir seçimdir — yanlış yazılmış bir
komut oturumu kapatmamalıdır. Betikte ise ters etki yapar.

**Katı kip (strict mode)**, kabuğun bu hoşgörüsünü kısan seçenekler kümesidir. Bu ders
seçenekleri tek tek ele alır; her birinin ne yakaladığını ve — daha önemlisi — ne
yakalamadığını gösterir.

## Erken Çıkış

`set -e` seçeneği, çıkış kodu sıfırdan farklı olan bir komuttan sonra kabuğu sonlandırır.

```sh
#!/usr/bin/env bash
set -e
echo "1: baslangic"
false
echo "2: BU SATIR YAZILMAZ"
```

```
1: baslangic
```

```sh
echo $?
```

```
1
```

Betik ikinci satıra ulaşmadan durdu ve başarısızlık kodunu dışarı taşıdı. Kazanç
yalnızca kolaylık değildir: bir betiğin yarım çıktı üretip başarı bildirmesi, onu
çağıran her sistemi yanıltır.

## Erken Çıkışın İstisnaları

`set -e` bir komutun başarısızlığını her yerde ölümcül saymaz. İstisnalar mantıklıdır ama
sayıları çoktur ve bilinmezse yanlış güven verir.

```sh
#!/usr/bin/env bash
set -e
if false; then echo "a"; fi
echo "1: kosulda basarisizlik betigi durdurmaz"
false || echo "2: || solunda basarisizlik durdurmaz"
false && echo "buraya gelinmez"
echo "3: && solunda basarisizlik da durdurmaz"
false | true
echo "4: boru hattinin son komutu basarili ise durdurmaz"
! false
echo "5: degillenmis komut durdurmaz"
f() { false; echo "f devam etti"; }
if f; then :; fi
echo "6: kosulda cagrilan fonksiyon icinde set -e askiya alinir"
```

```
1: kosulda basarisizlik betigi durdurmaz
2: || solunda basarisizlik durdurmaz
3: && solunda basarisizlik da durdurmaz
4: boru hattinin son komutu basarili ise durdurmaz
5: degillenmis komut durdurmaz
f devam etti
6: kosulda cagrilan fonksiyon icinde set -e askiya alinir
```

Altı istisnanın ilk beşi tasarım gereğidir: koşul olarak kullanılan bir komutun
başarısızlığı bilgi taşır, hata değildir. Altıncısı en tehlikelisidir — bir koşulda
çağrılan fonksiyonun **tüm gövdesi** boyunca erken çıkış askıya alınır ve gövdedeki gerçek
hatalar görünmez olur.

Bu yüzden `set -e` tek başına bir güvence değildir. Kritik komutların kodları ayrıca
sınanmalı ya da bir hata kancası kurulmalıdır.

## Tanımsız Değişken Denetimi

`set -u` seçeneği, tanımsız bir değişkenin genişletilmesini hata sayar.

```sh
#!/usr/bin/env bash
set -u
echo "kutuk: ${KUTUK}"
```

```
./u.sh: line 3: KUTUK: unbound variable
```

Bu seçenek, kabuk betiklerinde en yıkıcı hata sınıfını yakalar. `rm -rf "$DIZIN/"` satırı,
`DIZIN` tanımsızken `rm -rf /` hâline gelir — seçenek etkinken betik o satıra hiç
ulaşmaz.

Seçenek, öntanımlı değer gösterimlerini kullanmayı zorunlu kılar:

```sh
#!/usr/bin/env bash
set -u
echo "kutuk: ${KUTUK:-erisim.log}"
echo "ilk arguman: ${1-yok}"
echo "arguman sayisi: $#"
```

```
kutuk: erisim.log
ilk arguman: yok
arguman sayisi: 0
```

Değişkenler ve Tırnak Kuralları dersinde tanıtılan `${v-yedek}` ve `${v:-yedek}`
gösterimleri burada zorunluluğa dönüşür: verilmemiş bir konumsal parametre okunacaksa
öntanımlı değer yazılmalıdır. Bu, betiğin arayüzünü belgeleyen bir yan etki de üretir.

## Boru Hattı Kodu

`set -o pipefail`, boru hattının kodunu sıfırdan farklı kod döndüren en sağdaki komutun
koduna eşitler. Boru Hattı dersinde tanıtılmıştı; katı kipin ayrılmaz parçasıdır.

```sh
#!/usr/bin/env bash
set -eo pipefail
grep '999' erisim.log | wc -l
echo "BU SATIR YAZILMAZ"
```

```
       0
```

```sh
echo $?
```

```
1
```

`pipefail` olmadan bu betik `0` yazıp başarıyla biterdi: `wc` sorunsuz çalıştı ve hattın
kodu onunkiydi.

`pipefail` ve `set -e` ile birlikte, `SIGPIPE` ile kesilen hatların da başarısız
sayılacağı unutulmamalıdır. `komut | head -5` biçimindeki hatlar bilinçli olarak
bastırılmalıdır.

## Alan Ayırıcısını Daraltmak

`IFS=$'\n\t'` ataması, kelime bölmeden boşluğu çıkarır: bölme yalnızca satır sonu ve
sekmede yapılır.

```sh
IFS=$'\n\t'
d="a b:c"
printf '<%s>\n' $d
```

```
<a b:c>
```

Tırnaksız genişletme bile bölünmedi. Bu, boşluk içeren dosya adlarının yol açtığı hata
sınıfına karşı ek bir savunmadır.

Uyarı gerekiyor: bu ayar geneldir ve boşluğa göre bölmeye dayanan her kodu etkiler. Bir
değişkeni sözcüklerine ayırmak isteyen bir döngü, ayardan sonra tek tur döner. Katı kipin
diğer üç seçeneği koşulsuz önerilirken bu seçenek, betiğin ne yaptığına bakılarak
kararlaştırılmalıdır.

## Aritmetik Tuzağı

Aritmetik ve Komut Yerine Koyma dersinde `(( ))` komutunun çıkış kodunun değerin tersi
olduğu gösterilmişti. Katı kip altında bu, betiği durduran bir hataya dönüşür:

```sh
#!/usr/bin/env bash
set -e
sayac=0
(( sayac++ ))
echo "BU SATIR YAZILMAZ (sayac=$sayac)"
```

```
```

```sh
echo $?
```

```
1
```

`sayac++` son ek biçimi **eski değeri** — yani sıfırı — döndürdü ve `(( ))` bunu
başarısızlık saydı. Güvenli yazım aritmetik genişletmedir:

```sh
#!/usr/bin/env bash
set -e
sayac=0
sayac=$(( sayac + 1 ))
echo "sayac=$sayac"
```

```
sayac=1
```

Bu tuzak, katı kipin neden dikkatle uygulandığını gösterir: seçenekler betiğin anlamını
değiştirmez, ama hangi durumların "hata" sayılacağını değiştirir ve bazı deyimler bu yeni
tanımla uyumsuzdur.

## Beklenen Başarısızlıkları Bastırmak

Bazı komutların sıfırdan farklı kod döndürmesi normaldir; süzgeç aracının "eşleşme yok"
bildirimi bunun tipik örneğidir. Katı kip altında bu durumlar açıkça bastırılır.

```sh
#!/usr/bin/env bash
set -euo pipefail
adet=$(grep -c 'YOKBOYLE' erisim.log || true)
echo "eslesme sayisi: $adet"
if grep -q 'YOKBOYLE' erisim.log; then echo "var"; else echo "yok"; fi
```

```
eslesme sayisi: 0
yok
```

İki yöntem kullanıldı. `|| true`, kodu koşulsuz sıfırlar; sayının kendisi anlamlıysa
uygundur. `if` içinde çağırmak ise başarısızlığı zaten koşul olarak yorumlar; varlık
sorusunda doğru biçim budur.

`|| true` ölçülü kullanılmalıdır. Her satıra eklendiğinde katı kip anlamını yitirir ve
betik, hataları yutan eski hâline döner. Kural: **bastırma, o komutun başarısızlığının
neden beklenen olduğunu bilerek yapılır ve gerekiyorsa bir yorumla belgelenir.**

## Hata Kancası

`trap ... ERR`, erken çıkışı tetikleyen her komut için bir işleyici çalıştırır. Hatanın
nerede oluştuğunu bildirmek, katı kipin ürettiği sessiz çıkışları izlenebilir kılar.

`set -E` seçeneği bu kancanın fonksiyonlar ve alt kabuklar içinde de geçerli olmasını
sağlar; onsuz kanca yalnızca üst düzeyde çalışır.

```sh
#!/usr/bin/env bash
set -Eeuo pipefail
IFS=$'\n\t'

hata_yakala() {
  local kod=$? satir=$1
  printf 'rapor.sh: %d. satirda hata, cikis kodu %d\n' "$satir" "$kod" >&2
  exit "$kod"
}
trap 'hata_yakala "$LINENO"' ERR

echo "1: baslangic"
grep -q 'YOKBOYLE' erisim.log
echo "2: BU SATIR YAZILMAZ"
```

```
1: baslangic
rapor.sh: 13. satirda hata, cikis kodu 1
```

Kanca gövdesindeki ilk satır `local kod=$?` biçiminde yazılmıştır; `$?` başka bir komut
çalıştırılmadan okunmalıdır, yoksa değeri değişir. `$LINENO`, kancanın **kurulduğu** yerde
değil **tetiklendiği** yerde genişlemesi için tek tırnak içinde bırakılmıştır.

`trap` komutunun kendisi ve sinyal işleme, sonraki dersin konusudur.

## Katı Kip Başlığı

Bu dersin sonucu, betiklerin başına konan sabit bir başlıktır:

```sh
#!/usr/bin/env bash
set -Eeuo pipefail
```

Dört seçenek dört ayrı hata sınıfını kapatır: başarısız komut, tanımsız değişken, boru
hattında kaybolan kod ve fonksiyon içinde kaybolan hata kancası. Beşincisi — `IFS`
daraltması — betiğe göre kararlaştırılır.

Başlık bir güvence değil, bir taban çizgisidir. `set -e` istisnaları göz önünde
tutulduğunda, kritik komutların kodları hâlâ elle sınanmalıdır. Katı kip, gözden kaçanları
yakalar; gözden kaçmaması gerekenlerin yerini tutmaz.

## Özet

- `set -e` sıfırdan farklı kod döndüren komuttan sonra kabuğu sonlandırır; koşul
  bağlamlarında, zincir işleçlerinin solunda ve koşulda çağrılan fonksiyonların gövdesinde
  askıya alınır.
- `set -u` tanımsız değişken genişletmesini hata sayar ve öntanımlı değer gösterimlerini
  zorunlu kılar.
- `set -o pipefail` boru hattının kodunu ilk başarısız halkanın koduna bağlar.
- `(( sayac++ ))` sıfır değerinde başarısızlık bildirir; katı kip altında
  `sayac=$(( sayac + 1 ))` yazılır.
- Beklenen başarısızlıklar `|| true` ya da koşul bağlamıyla bilinçli olarak bastırılır.
- `set -E` ile birlikte `trap ... ERR`, hatanın satır numarasını bildiren bir kanca kurar.

## Sonraki Adım

Katı kip betiği hata anında durduruyor — ama durduğu yerde ne bırakıyor? Yarım yazılmış bir
çıktı dosyası, temizlenmemiş geçici dosyalar, başka bir sürecin beklediği bir kilit.
Sonraki ders sinyalleri ve çıkışta çalışan temizlik kancalarını ele alır; geçici dosyanın
güvenli biçimde yaratılması ve her çıkış yolunda silinmesi de orada kurulacak.
