Linux'ta stdin, stdout ve stderr nedir?
Yayınlanan: 2022-01-29 stdin
, stdout
ve stderr
, bir Linux komutu başlattığınızda oluşturulan üç veri akışıdır. Komut dosyalarınızın yönlendirilip yönlendirilmediğini anlamak için bunları kullanabilirsiniz. Size nasıl olduğunu gösteriyoruz.
Akışlar İki Noktayı Birleştiriyor
Linux ve Unix benzeri işletim sistemleri hakkında bilgi edinmeye başlar başlamaz stdin
, stdout
ve stederr
terimleriyle karşılaşacaksınız. Bunlar, bir Linux komutu yürütüldüğünde oluşturulan üç standart akıştır. Bilgi işlemde akış, veri aktarabilen bir şeydir. Bu akışlar söz konusu olduğunda, bu veriler metindir.
Su akışları gibi veri akışlarının iki ucu vardır. Bir kaynağı ve bir çıkışı var. Hangi Linux komutunu kullanırsanız kullanın, her akışın bir ucunu sağlar. Diğer uç, komutu başlatan kabuk tarafından belirlenir. Bu uç, komutu başlatan komut satırına göre terminal penceresine bağlanacak, bir boruya bağlanacak veya bir dosyaya veya başka bir komuta yönlendirilecektir.
Linux Standart Akışları
Linux'ta stdin
, standart girdi akışıdır. Bu, metni girdi olarak kabul eder. Komuttan kabuğa metin çıktısı, stdout
(standart çıkış) akışı aracılığıyla iletilir. Komuttan gelen hata mesajları, stderr
(standart hata) akışı aracılığıyla gönderilir.
Böylece, stdout
ve stderr
olmak üzere iki çıkış akışı ve bir giriş akışı, stdin
olduğunu görebilirsiniz. Hata mesajları ve normal çıktıların her birinin onları terminal penceresine taşımak için kendi kanalı olduğundan, birbirlerinden bağımsız olarak işlenebilirler.
Akışlar Dosyalar Gibi İşlenir
Linux'taki akışlar - hemen hemen her şey gibi - dosyalar gibi ele alınır. Bir dosyadan metin okuyabilir ve bir dosyaya metin yazabilirsiniz. Bu eylemlerin her ikisi de bir veri akışı içerir. Bu nedenle, bir veri akışını dosya olarak işleme kavramı o kadar da esneme değildir.
Bir işlemle ilişkili her dosyaya, onu tanımlamak için benzersiz bir numara atanır. Bu, dosya tanımlayıcı olarak bilinir. Bir dosya üzerinde bir eylemin gerçekleştirilmesi gerektiğinde, dosyayı tanımlamak için dosya tanımlayıcısı kullanılır.
Bu değerler her zaman stdin
, stdout,
ve stderr
için kullanılır:
- 0 : standart
- 1 : standart
- 2 : standart
Borulara ve Yönlendirmelere Tepki Verme
Birinin bir konuya girişini kolaylaştırmak için yaygın bir teknik, konunun basitleştirilmiş bir versiyonunu öğretmektir. Örneğin, dilbilgisi ile kuralın "C'den sonra E'den önce I" olduğu söylenir. Ama aslında, bu kuralın, ona uyan durumlardan daha fazla istisnası vardır.
Benzer bir şekilde, stdin
, stdout
ve stderr
hakkında konuşurken, bir işlemin üç standart akışının nerede sonlandırıldığını bilmediği veya umursamadığı kabul edilen aksiyomu ortaya çıkarmak uygundur. Bir süreç çıktısının uçbirime mi yoksa bir dosyaya mı yönlendirildiğine mi dikkat etmeli? Girişinin klavyeden mi geldiğini yoksa başka bir işlemden mi aktarıldığını bile söyleyebilir mi?
Aslında, bir süreç bilir - veya en azından kontrol etmeyi seçerse öğrenebilir - ve yazılım yazarı bu işlevi eklemeye karar verirse davranışını buna göre değiştirebilir.
Davranıştaki bu değişikliği çok kolay görebiliriz. Bu iki komutu deneyin:
ls
l | kedi
ls
komutu, çıktısı ( stdout
) başka bir komuta aktarılıyorsa farklı davranır. Tek sütun çıktısına geçiş yapan ls
, cat
tarafından gerçekleştirilen bir dönüştürme değildir. Ve çıktısı yönlendiriliyorsa ls
aynı şeyi yapar:
ls > yakalama.txt
kedi yakalama.txt
stdout ve stderr'yi yeniden yönlendirme
Özel bir akış tarafından iletilen hata mesajlarına sahip olmanın bir avantajı vardır. Bu, bir komutun çıktısını ( stdout
) bir dosyaya yeniden yönlendirebileceğimiz ve yine de terminal penceresinde herhangi bir hata mesajı ( stderr
) görebileceğimiz anlamına gelir. Gerektiğinde hatalara oluştukları anda tepki verebilirsiniz. Ayrıca, stdout
yeniden yönlendirildiği dosyayı kirleten hata mesajlarını da durdurur.
Aşağıdaki metni bir düzenleyiciye yazın ve error.sh adlı bir dosyaya kaydedin.
#!/bin/bash echo "Var olmayan bir dosyaya erişmeye çalışmak üzere" cat kötü dosyaadı.txt
Komut dosyasını bu komutla yürütülebilir yapın:
chmod +x hatası.sh
Komut dosyasının ilk satırı, metni stdout
akışı aracılığıyla terminal penceresine yansıtır. İkinci satır, var olmayan bir dosyaya erişmeye çalışır. Bu, stderr
aracılığıyla iletilen bir hata mesajı oluşturacaktır.
Komut dosyasını şu komutla çalıştırın:
./hata.sh
Terminal pencerelerinde her iki çıktı akışının ( stdout
ve stderr
) görüntülendiğini görebiliriz.
Çıktıyı bir dosyaya yönlendirmeyi deneyelim:
./error.sh > yakalama.txt
stderr
aracılığıyla iletilen hata mesajı hala terminal penceresine gönderilir. stdout
çıktısının dosyaya gidip gitmediğini görmek için dosyanın içeriğini kontrol edebiliriz.
kedi yakalama.txt
stdin
gelen çıktı, beklendiği gibi dosyaya yönlendirildi.
>
yeniden yönlendirme sembolü, varsayılan olarak stdout
ile çalışır. Hangi standart çıktı akışını yeniden yönlendirmek istediğinizi belirtmek için sayısal dosya tanımlayıcılarından birini kullanabilirsiniz.
stdout
açıkça yeniden yönlendirmek için bu yeniden yönlendirme talimatını kullanın:
1>
stderr
açıkça yeniden yönlendirmek için bu yeniden yönlendirme talimatını kullanın:
2>
Testimizi tekrar deneyelim ve bu sefer 2>
kullanacağız:
./error.sh 2> yakalama.txt
Hata mesajı yeniden yönlendirilir ve stdout
echo
mesajı terminal penceresine gönderilir:
Capture.txt dosyasında neler varmış bir bakalım.
kedi yakalama.txt
stderr
mesajı, beklendiği gibi yakalama.txt dosyasında.
Hem stdout hem de stderr Yönlendirme
Elbette, stdout
veya stderr
birbirinden bağımsız olarak bir dosyaya yönlendirebilirsek, ikisini de aynı anda iki farklı dosyaya yönlendirebilmemiz gerekir mi?
Evet yapabiliriz. Bu komut, stdout
yakalama.txt adlı bir dosyaya ve stderr
error.txt adlı bir dosyaya yönlendirecektir.
./error.sh 1> yakalama.txt 2> error.txt
Standart çıktı ve standart hata çıktılarının her iki akışı da dosyalara yönlendirildiğinden, terminal penceresinde görünür çıktı yoktur. Hiçbir şey olmamış gibi komut satırı istemine geri dönüyoruz.
Her dosyanın içeriğini kontrol edelim:
kedi yakalama.txt
kedi hatası.txt
Stdout ve stderr'i Aynı Dosyaya Yönlendirme
Çok güzel, standart çıktı akışlarının her birinin kendi özel dosyasına gitmesine sahibiz. Yapabileceğimiz diğer kombinasyon, hem stdout
hem de stderr
aynı dosyaya göndermektir.
Bunu aşağıdaki komutla başarabiliriz:
./error.sh > yakalama.txt 2>&1
Bunu parçalayalım.
- ./error.sh : error.sh komut dosyasını başlatır.
- > yakalama.txt :
stdout
akışını yakalama.txt dosyasına yönlendirir.>
1>
'in kısaltmasıdır. - 2>&1 : Bu, &> yönlendirme talimatını kullanır. Bu talimat, kabuğa bir akışın başka bir akışla aynı hedefe ulaşmasını söylemenizi sağlar. Bu durumda, "akım 2'yi,
stderr
, akış 1'in,stdout
yönlendirildiği aynı hedefe yönlendirin" diyoruz.
Görünür bir çıktı yok. Bu cesaret verici.
Capture.txt dosyasını kontrol edelim ve içinde ne olduğunu görelim.
kedi yakalama.txt
Hem stdout
hem de stderr
akışları tek bir hedef dosyaya yönlendirildi.
Bir akışın çıktısının yeniden yönlendirilmesini ve sessizce atılmasını sağlamak için çıktıyı /dev/null
yönlendirin.
Bir Komut Dosyasında Yeniden Yönlendirmeyi Algılama
Bir komutun, akışlardan herhangi birinin yeniden yönlendirilip yönlendirilmediğini nasıl algılayabileceğini ve davranışını buna göre değiştirmeyi seçebileceğini tartıştık. Bunu kendi senaryolarımızda başarabilir miyiz? Evet yapabiliriz. Ve anlaşılması ve uygulanması çok kolay bir tekniktir.
Aşağıdaki metni bir düzenleyiciye yazın ve input.sh olarak kaydedin.
#!/bin/bash eğer [ -t 0 ]; sonra klavyeden gelen yankı stdin Başka bir borudan veya bir dosyadan gelen yankı stdin fi
Yürütülebilir hale getirmek için aşağıdaki komutu kullanın:
chmod +x girdi.sh
Akıllı kısım, köşeli parantez içindeki testtir. -t
(uçbirim) seçeneği, dosya tanıtıcıyla ilişkili dosya uçbirim penceresinde sonlanırsa doğru (0) değerini döndürür. Testin argümanı olarak stdin
temsil eden dosya tanıtıcı 0'ı kullandık.
Eğer stdin
bir terminal penceresine bağlıysa, test doğru olacaktır. stdin
bir dosyaya veya boruya bağlanırsa, test başarısız olur.
Komut dosyasına girdi oluşturmak için herhangi bir uygun metin dosyasını kullanabiliriz. Burada dummy.txt adında bir tane kullanıyoruz.
./input.sh < kukla.txt
Çıktı, komut dosyasının girdinin klavyeden değil, bir dosyadan geldiğini tanıdığını gösterir. Seçtiyseniz, komut dosyanızın davranışını buna göre değiştirebilirsiniz.
Bu bir dosya yönlendirmesi ile oldu, hadi bir boru ile deneyelim.
kedi kukla.txt | ./input.sh
Komut dosyası, girdisinin kendisine aktarıldığını tanır. Veya daha doğrusu, stdin
akışının bir terminal penceresine bağlı olmadığını bir kez daha tanır.
Komut dosyasını ne borular ne de yönlendirmeler olmadan çalıştıralım.
./input.sh
stdin
akışı, terminal penceresine bağlanır ve komut dosyası bunu buna göre bildirir.
Aynı şeyi çıktı akışıyla kontrol etmek için yeni bir komut dosyasına ihtiyacımız var. Aşağıdakini bir düzenleyiciye yazın ve output.sh olarak kaydedin.
#!/bin/bash eğer [ -t 1 ]; sonra echo stdout terminal penceresine gidiyor Başka echo stdout yeniden yönlendiriliyor veya yönlendiriliyor fi
Yürütülebilir hale getirmek için aşağıdaki komutu kullanın:
chmod +x girdi.sh
Bu komut dosyasındaki tek önemli değişiklik, köşeli parantez içindeki testte. stdout
dosya tanımlayıcısını temsil etmek için 1 rakamını kullanıyoruz.
Deneyelim. Çıktıyı cat
aracılığıyla ileteceğiz.
./çıktı | kedi
Komut dosyası, çıktısının doğrudan bir terminal penceresine gitmediğini tanır.
Çıktıyı bir dosyaya yönlendirerek de betiği test edebiliriz.
./output.sh > yakalama.txt
Terminal penceresine çıkış yok, sessizce komut istemine dönüyoruz. Beklediğimiz gibi.
Neyin yakalandığını görmek için yakalama.txt dosyasının içine bakabiliriz. Bunu yapmak için aşağıdaki komutu kullanın.
kedi yakalama.sh
Yine, betiğimizdeki basit test, stdout
akışının doğrudan bir terminal penceresine gönderilmediğini tespit ediyor.
Komut dosyasını herhangi bir yönlendirme veya yönlendirme olmadan çalıştırırsak, stdout
doğrudan terminal penceresine teslim edildiğini algılaması gerekir.
./output.sh
Ve tam olarak gördüğümüz şey bu.
Bilinç Akışları
Komut dosyalarınızın terminal penceresine mi yoksa bir boruya mı bağlı olduğunu veya yeniden yönlendirildiğini nasıl anlayacağınızı bilmek, davranışlarını buna göre ayarlamanıza olanak tanır.
Günlüğe kaydetme ve tanılama çıktısı, ekrana mı yoksa bir dosyaya mı gittiğine bağlı olarak az çok ayrıntılı olabilir. Hata mesajları, normal program çıktısından farklı bir dosyaya kaydedilebilir.
Genelde olduğu gibi, daha fazla bilgi daha fazla seçeneği beraberinde getirir.
Linux Komutları | ||
Dosyalar | tar · pv · kedi · tac · chmod · grep · diff · sed · ar · adam · pushd · popd · fsck · testdisk · seq · fd · pandoc · cd · $PATH · awk · birleştirme · jq · katlama · uniq · dergictl · kuyruk · stat · ls · fstab · yankı · daha az · chgrp · chown · rev · bak · diziler · tür · yeniden adlandır · zip · unzip · mount · umount · yükle · fdisk · mkfs · rm · rmdir · rsync · df · gpg · vi · nano · mkdir · du · ln · yama · dönüştürmek · rclone · parçalamak · srm | |
süreçler | takma ad · ekran · üst · güzel · renice · ilerleme · strace · systemd · tmux · chsh · geçmiş · at · toplu · ücretsiz · hangi · dmesg · chfn · usermod · ps · chroot · xargs · tty · pembemsi · lsof · vmstat · zaman aşımı · duvar · evet · öldür · uyku · sudo · su · zaman · groupadd · usermod · gruplar · lshw · kapatma · yeniden başlatma · durdurma · güç kapatma · passwd · lscpu · crontab · tarih · bg · fg | |
ağ | netstat · ping · traceroute · ip · ss · whois · fail2ban · bmon · kazmak · parmak · nmap · ftp · curl · wget · kim · whoami · w · iptables · ssh-keygen · ufw |
İLGİLİ: Geliştiriciler ve Meraklılar için En İyi Linux Dizüstü Bilgisayarlar