---
title: 'Standart Girdi, Çıktı ve Hata'
source: 'https://academia.sh/tr/kurslar/kabuk-programlama/standart-girdi-cikti-ve-hata'
course: 'Kabuk Programlama'
language: tr
updated: '2026-08-17T18:10:03+00:00'
license: 'CC BY-SA 4.0'
---

# Standart Girdi, Çıktı ve Hata

Üç standart akış, dosya tanıtıcı numaraları, veriyle tanı iletisinin ayrılması ve süzgeç modeli.

Linux'a Giriş kursunda komutlar tek tek çalıştırıldı: dizin listelendi, dosya kopyalandı,
izin değiştirildi. Her komutun bir çıktısı oldu ve o çıktı ekrana yazıldı. Ekran, işin
bittiği yerdi.

Bu kurs o varsayımı kaldırır. Kabuğun asıl gücü, bir komutun ürettiği veriyi başka bir
komuta yem yapabilmesinden gelir; bunun için de çıktının nereye gittiğinin komut
tarafından değil, komutu çağıran tarafından belirlenmesi gerekir. İlk soru şudur: bir
komut yazdığı veriyi tam olarak nereye yazar?

## Üç Akış

Bir süreç (process) başlatıldığında, kabuk ona üç adet açık **akış (stream)** devreder.
Her akış bir tam sayıyla, **dosya tanıtıcısı (file descriptor)** ile anılır:

| Numara | Ad | Yön | Varsayılan bağlantı |
|---|---|---|---|
| 0 | standart girdi (stdin) | okuma | klavye |
| 1 | standart çıktı (stdout) | yazma | ekran |
| 2 | standart hata (stderr) | yazma | ekran |

Bu numaralar sözleşmedir, keşif değil: her program çalışmaya başladığında 0, 1 ve 2
numaralı tanıtıcıların açık olduğunu varsayar. Program bu tanıtıcıların ucunda ne
olduğunu bilmez ve bilmemelidir. Uç, bir terminal olabilir; bir dosya, bir boru veya
bir ağ bağlantısı da olabilir.

Bu bilgisizlik bir eksiklik değil, tasarımın kendisidir. Komut "ekrana yaz" demez,
"1 numaralı tanıtıcıya yaz" der. Nereye gideceğine çağıran karar verir.

## Neden İki Ayrı Çıkış Akışı

Yazma yönünde iki akış olması ilk bakışta gereksiz görünür. Gerekçesi şudur: bir komutun
ürettiği iki tür metin vardır ve bunlar farklı yerlere gitmelidir.

- **Veri**, komutun asıl ürünüdür: dosya listesi, satır sayısı, süzülmüş metin. Başka
  bir komuda girdi olabilecek olan budur. Standart çıktıya gider.
- **Tanı iletisi (diagnostic message)**, insan içindir: hata bildirimi, uyarı, ilerleme
  bilgisi. Bir sonraki komuda girdi olarak kullanılmamalıdır. Standart hataya gider.

Ayrım pratikte hemen görülür. Aşağıdaki komut var olan bir dosya ile var olmayan bir adı
birlikte listeler:

```sh
ls erisim.log yok.txt
```

```
ls: yok.txt: No such file or directory
erisim.log
```

İki satır aynı ekranda göründü, ama aynı akıştan gelmediler. Bunu doğrulamak için
akışlardan birini ıskartaya çıkarmak yeterlidir. `/dev/null`, kendisine yazılan her şeyi
yutan özel bir aygıt dosyasıdır:

```sh
ls erisim.log yok.txt 2>/dev/null
```

```
erisim.log
```

```sh
ls erisim.log yok.txt 1>/dev/null
```

```
ls: yok.txt: No such file or directory
```

`2>` ve `1>` gösterimlerinin ayrıntısı sonraki dersin konusudur; burada önemli olan
sonuçtur. İlk çağrıda yalnızca veri, ikincisinde yalnızca tanı iletisi kaldı. Demek ki
`ls`, bulamadığı dosya için ürettiği iletiyi bilerek ikinci akışa yazmıştır.

Bu davranış bir gelenek değil, uyulması beklenen bir kuraldır. Kendi betiklerinizde
uyarıları standart çıktıya yazarsanız, betiğinizin çıktısını işleyen bir sonraki komut
uyarı metnini veri sanır ve bozulur.

## Kendi İletinizi Doğru Akışa Yazmak

`>&2` eki, bir komutun standart çıktısını standart hataya bağlar. Bir betikte uyarı
üretmenin doğru yolu budur:

```sh
uyar() { printf 'uyari: %s\n' "$1" >&2; }
uyar "kutuk bulunamadi"
echo "rapor gövdesi"
```

Bu iki satırın çıktısı, hangi akışa baktığınıza göre değişir. Yalnızca veriyi
istediğinizde:

```sh
{ uyar "kutuk bulunamadi"; echo "rapor gövdesi"; } 2>/dev/null
```

```
rapor gövdesi
```

Yalnızca tanı iletisini istediğinizde:

```sh
{ uyar "kutuk bulunamadi"; echo "rapor gövdesi"; } 1>/dev/null
```

```
uyari: kutuk bulunamadi
```

Kurs boyunca yazılacak betikte bu kural değişmeyecek: raporun kendisi standart çıktıya,
raporla ilgili her açıklama standart hataya gider.

## Akışlar Bağımsız Tamponlanır

İki akışın ekranda göründüğü sıra, komutun onları yazdığı sıra olmayabilir. Yukarıdaki
`ls` çağrısında hata iletisi, veri satırından **önce** göründü. Bunun nedeni
**tamponlama (buffering)** farkıdır: standart hata genellikle tamponsuz veya satır
tamponludur, standart çıktı ise bir dosyaya ya da boruya bağlıyken blok tamponludur.
Blok tamponlu akış, tamponu dolana veya süreç bitene kadar bekletilir.

İki akışı aynı dosyaya toplayınca sonuç görülebilir:

```sh
ls erisim.log yok.txt > hepsi.txt 2>&1
cat hepsi.txt
```

```
ls: yok.txt: No such file or directory
erisim.log
```

Buradan çıkan kural: **iki akışın birbirine göre sırasına güvenmeyin.** Bir betiğin
çıktısını hata iletileriyle birlikte kütüğe yazıyorsanız, satırların kronolojik sırada
olacağını varsaymayın; sıra gerekiyorsa her satıra kendi zaman damgasını yazın.

## Süzgeç Modeli

Standart girdi, akışların en az göze çarpanıdır çünkü etkileşimli kullanımda çoğu komut
onu kullanmaz. Oysa kabuğun bileşim gücü tam olarak buradan gelir.

**Süzgeç (filter)**, standart girdisinden okuyup standart çıktısına yazan komuttur.
Süzgeçler dosya adı bilmez, konum bilmez; yalnızca kendilerine akan metni dönüştürür.
`sort`, `tr`, `wc`, `head`, `grep` bu sınıftadır.

```sh
tr 'a-z' 'A-Z' <<< 'kabuk programlama'
```

```
KABUK PROGRAMLAMA
```

Komutlar girdi kaynağı bakımından üç öbeğe ayrılır:

1. **Yalnızca argümandan çalışanlar.** `mkdir`, `chmod`, `rm` gibi komutlar iş için
   dosya adına ihtiyaç duyar; standart girdiyi okumazlar.
2. **Yalnızca standart girdiden çalışanlar.** `tr` bunun tipik örneğidir; dosya adı
   argümanı almaz.
3. **İkisini de kabul edenler.** `sort`, `wc`, `grep`, `cat` gibi komutlar dosya adı
   verilirse onu, verilmezse standart girdiyi okur.

Üçüncü öbek en yaygınıdır ve iki farklı yazımı vardır:

```sh
wc -l erisim.log
```

```
      30 erisim.log
```

```sh
wc -l < erisim.log
```

```
      30
```

Fark yalnızca biçimsel değildir. İlk çağrıda `wc` dosyayı kendisi açar; adını bildiği
için çıktısına yazar. İkincisinde `wc` yalnızca bir akış görür; dosyanın adını bilmez,
dolayısıyla yazamaz. Ne zaman hangisinin istendiği duruma bağlıdır: çok dosyalı raporda
ad gerekir, sayıyı bir değişkene almak istediğinizde ad engeldir.

Satır sayısını hizalayarak yazan gerçekleştirimler sayının önüne boşluk koyar; GNU
coreutils sürümü koymaz. Sayıyı doğrudan karşılaştırmada kullanacaksanız bu boşluk
sorun çıkarır — ilerleyen derslerde aritmetik genişletme bu farkı soğurur.

Üçüncü öbekteki komutların çoğu, dosya adı yerine tek bir tire (`-`) kabul eder ve bunu
"standart girdi" diye yorumlar. Dosya listesinin ortasına akış sokmak gerektiğinde
kullanılır:

```sh
head -2 erisim.log | cat -n -
```

```
     1	10.0.0.12 - - [07/Feb/2024:09:12:44 +0000] "GET /index.html HTTP/1.1" 200 5120
     2	10.0.0.31 - - [07/Feb/2024:09:12:51 +0000] "GET /statik/stil.css HTTP/1.1" 200 2048
```

Tirenin bu anlamı çekirdek düzeyinde değil, her komutun kendi içinde tanımlıdır; genel
bir kural değil yaygın bir sözleşmedir.

## Kursun Çalışma Dosyası

Bu kurs boyunca tek bir veri kümesi kullanılacak: bir web sunucusunun erişim **kütüğü
(log)**. Aşağıdaki otuz satırı `erisim.log` adıyla kaydedin; sonraki her ders bu dosya
üzerinde ilerleyecek.

```
10.0.0.12 - - [07/Feb/2024:09:12:44 +0000] "GET /index.html HTTP/1.1" 200 5120
10.0.0.31 - - [07/Feb/2024:09:12:51 +0000] "GET /statik/stil.css HTTP/1.1" 200 2048
10.0.0.12 - - [07/Feb/2024:09:13:02 +0000] "GET /urun/12 HTTP/1.1" 200 8410
172.16.0.9 - - [07/Feb/2024:09:14:19 +0000] "GET /yok.html HTTP/1.1" 404 512
10.0.2.7 - - [07/Feb/2024:09:15:30 +0000] "POST /giris HTTP/1.1" 302 0
10.0.2.7 - - [07/Feb/2024:09:15:31 +0000] "GET /panel HTTP/1.1" 200 12040
10.0.0.31 - - [07/Feb/2024:09:16:04 +0000] "GET /urun/45 HTTP/1.1" 200 7330
192.168.1.5 - - [07/Feb/2024:09:17:22 +0000] "GET /api/veri HTTP/1.1" 500 180
10.0.0.12 - - [07/Feb/2024:09:18:00 +0000] "GET /api/veri HTTP/1.1" 200 3300
172.16.0.9 - - [07/Feb/2024:09:18:47 +0000] "GET /gizli HTTP/1.1" 403 290
10.0.0.31 - - [07/Feb/2024:09:19:12 +0000] "GET /index.html HTTP/1.1" 200 5120
10.0.2.7 - - [07/Feb/2024:09:20:05 +0000] "GET /urun/12 HTTP/1.1" 200 8410
192.168.1.5 - - [07/Feb/2024:09:21:38 +0000] "GET /api/veri HTTP/1.1" 500 180
10.0.0.12 - - [07/Feb/2024:09:22:10 +0000] "GET /statik/stil.css HTTP/1.1" 304 0
172.16.0.9 - - [07/Feb/2024:09:23:55 +0000] "GET /yok.html HTTP/1.1" 404 512
10.0.0.31 - - [07/Feb/2024:09:24:41 +0000] "POST /api/veri HTTP/1.1" 201 96
10.0.2.7 - - [07/Feb/2024:09:25:19 +0000] "GET /index.html HTTP/1.1" 200 5120
192.168.1.5 - - [07/Feb/2024:09:26:33 +0000] "GET /urun/45 HTTP/1.1" 200 7330
10.0.0.12 - - [07/Feb/2024:09:27:02 +0000] "GET /panel HTTP/1.1" 200 12040
172.16.0.9 - - [07/Feb/2024:09:28:14 +0000] "GET /eski-sayfa HTTP/1.1" 301 0
10.0.0.31 - - [07/Feb/2024:09:29:48 +0000] "GET /api/veri HTTP/1.1" 200 3300
10.0.2.7 - - [07/Feb/2024:09:30:26 +0000] "GET /statik/stil.css HTTP/1.1" 200 2048
192.168.1.5 - - [07/Feb/2024:09:31:07 +0000] "GET /yok.html HTTP/1.1" 404 512
10.0.0.12 - - [07/Feb/2024:09:32:53 +0000] "GET /urun/12 HTTP/1.1" 200 8410
10.0.0.31 - - [07/Feb/2024:09:33:39 +0000] "GET /gizli HTTP/1.1" 403 290
172.16.0.9 - - [07/Feb/2024:09:34:11 +0000] "GET /index.html HTTP/1.1" 200 5120
10.0.2.7 - - [07/Feb/2024:09:35:44 +0000] "POST /api/veri HTTP/1.1" 500 180
192.168.1.5 - - [07/Feb/2024:09:36:58 +0000] "GET /panel HTTP/1.1" 200 12040
10.0.0.12 - - [07/Feb/2024:09:37:20 +0000] "GET /urun/45 HTTP/1.1" 200 7330
10.0.0.31 - - [07/Feb/2024:09:38:05 +0000] "GET /yok.html HTTP/1.1" 404 512
```

Her satırın alanları boşlukla ayrılmıştır: istemci adresi, iki kullanılmayan alan, köşeli
ayraç içinde zaman damgası, tırnak içinde istek satırı (yöntem, yol, protokol), yanıt
durum kodu ve gönderilen bayt sayısı. Kursun sonunda bu dosyayı okuyup özet rapor üreten,
hataya dayanıklı ve zamanlanmış olarak çalışan bir betik yazılmış olacak.

## Özet

- Her sürece üç akış devredilir: 0 numaralı standart girdi, 1 numaralı standart çıktı,
  2 numaralı standart hata. Program bu tanıtıcıların ucunda ne olduğunu bilmez.
- Komutun asıl ürünü olan veri 1'e, insana yönelik tanı iletileri 2'ye yazılır; kendi
  betiklerinizde uyarıları `>&2` ile ikinci akışa göndermek bu sözleşmeyi sürdürür.
- İki akış bağımsız tamponlandığı için birbirlerine göre sıraları güvence altında
  değildir.
- Süzgeç, standart girdisinden okuyup standart çıktısına yazan ve dosya adı bilmeyen
  komuttur; kabuğun bileşim gücü bu modelden gelir.
- Bir komuta dosya adı vermekle akış bağlamak eşdeğer değildir: adı bilen komut onu
  çıktısına da yazabilir.

## Sonraki Adım

Bu derste akışların uçlarını `2>/dev/null` gibi gösterimlerle değiştirdik ama gösterimin
kendisini açıklamadık. Sonraki ders yönlendirme işleçlerini kuralıyla ele alır: dosyaya
yazma ile ekleme arasındaki fark, iki akışı tek dosyada toplamanın doğru sırası ve
yönlendirmelerin neden soldan sağa değerlendirildiği.
