Stdin, stdout ve stderr hakkında kafanız mı karıştı?


230

Bu üç dosyanın amacı ile kafam karıştı. Anlayışım doğruysa, stdinbir programın işlemdeki bir görevi yürütmek için isteklerine yazdığı stdoutdosya, çekirdeğin çıktısını yazdığı dosya ve bilginin erişmesini isteyen işlemdir stderrve dosya tüm istisnalar girilir. Bunlar gerçekten olup olmadığını kontrol etmek için bu dosyaları açarken, ben böyle bir şey önermek gibi görünüyor!

Ne bilmek istiyorum bu dosyaların amacı tam olarak nedir, kesinlikle çok az teknoloji jargon ile cevap aşağı aptal!


36
Gözlem: Bu soru 2010'da kabul edilebilirdi, ancak bugünlerde çok hızlı bir şekilde reddedilecekti.
byxor

3
@Brandon Bir sebep verebilir misiniz? Bence yorumunuz için değerli olur.
Bağımsız

3
@byxor dürüst olmak gerekirse, ben soracağım: op sonrası millet onun kodunu hata ayıklamak yardımcı olmak istiyordu? Shouvik, stdin, stdout ve stderr'in amacı hakkında bir soru sordu. op'un görevi meraksız gibi görünüyor, değil mi? (Ben aslında bu kendim atm öğreniyorum. teşekkürler, SO, bu yazı kaldırmak için değil)
sansae

2
@ user123456 haklısınız. Bir yazılım geliştiricisi olmayı öğreniyordum ve S / O o zamanlar programlama hakkında bilgi edinmek için harika bir yerdi. Başlangıçta bilişim bilimleriyle ilgili tüm sorular için bir tür wiki hizmeti olmayı amaçladık. #juniorDevForLife
Shouvik

3
@Shouvik bu tarih biraz için teşekkürler. Ben de bir yazılım geliştirici olmayı öğreniyorum (sadece sf serin bir kampa kabul edildi). S / O için hala oldukça yeniyim ve hala gönderebileceğim ve gönderemediğimden emin değilim. Buradaki ılımlılığın oldukça katı olabileceğini düşünüyorum. Bu karma etiketi beğendim. #juniorDevForLife. Tartışmaya hiçbir şey katmadığı için buraya yorum yapmak yerine sizi beklerim, ancak S / O'nun pm sistemi olduğuna inanmıyorum. İyi günler.
sansae

Yanıtlar:


251

Standart giriş - bu, işleminizin sizden bilgi almak için okuduğu dosya tanıtıcısıdır .

Standart çıktı - işleminiz bu dosya tanıtıcısına normal bilgiler yazar.

Standart hata - işleminiz hata bilgilerini bu dosya tanıtıcısına yazar.

Bu yapabildiğim kadar aptal :-)

Tabii ki, çoğunlukla konvansiyonla. İsterseniz hata bilgilerinizi standart çıktıya yazmanızı engelleyen hiçbir şey yoktur. Hatta üç dosya tanıtıcısını tamamen kapatabilir ve G / Ç için kendi dosyalarınızı açabilirsiniz.

İşleminiz başladığında, bu tutamaçların açık olması gerekir ve bunlardan okuyabilir ve / veya yazabilir.

Varsayılan olarak, muhtemelen terminal aygıtınıza bağlanırlar (örn. /dev/tty), Ancak kabuklar işleminiz başlamadan önce bu tutamaçlar ve belirli dosyalar ve / veya aygıtlar (veya hatta diğer işlemlere giden boru hatları) arasında bağlantılar kurmanıza olanak tanır. olası manipülasyonlar oldukça zekidir).

Bir örnek:

my_prog <inputfile 2>errorfile | grep XYZ

hangisi:

  • işlem yapmak my_prog.
  • açmak inputfilestandart girdi (dosya tanıtıcısı 0) olarak.
  • açmak errorfileiçin standart hata (dosya tanıtıcı 2) olarak.
  • başka bir işlem yarat grep.
  • standart çıkışını my_progstandart girişine bağlayın grep.

Yorumunuz:

Bu dosyaları / dev klasöründe açtığımda, çalışan bir işlemin çıktısını asla göremiyorum.

Çünkü normal dosyalar değiller. UNIX her şeyi bir yerde bir dosya sisteminde bir dosya olarak sunarken , bu onu en düşük seviyelerde yapmaz. /devHiyerarşideki dosyaların çoğu karakter veya blok aygıtlardır, etkin bir aygıt sürücüsüdür. Boyutları yok ama büyük ve küçük bir cihaz numarası var.

Bunları açtığınızda, fiziksel bir dosya yerine aygıt sürücüsüne bağlanırsınız ve aygıt sürücüsü, ayrı işlemlerin ayrı ayrı ele alınması gerektiğini bilecek kadar akıllıdır.

Aynı şey Linux /procdosya sistemi için de geçerlidir . Bunlar gerçek dosyalar değil, sadece çekirdek bilgilerine sıkıca kontrol edilen ağ geçitleri.


1
Bu senin cevabın için. Dosyaların amacını açıkladığınız şeyden anlayabilsem de, bir seviye daha ileri gitmek istiyorum. Bu dosyaları / dev klasöründe açtığımda, işlemin çıktısını asla göremiyorum. Diyelim ki terminalde üst yürütüyorum, sonuçlarını düzenli olarak stdout dosyasına vermesi gerekmiyor mu, bu nedenle güncellenirken çıkışın bir örneğinin bu dosyaya yazdırıldığını görebilmeliyim. Ama bu öyle değil .. Yani bu dosyalar aynı değil (/ dev dizinindekiler).
Shouvik

7
Çünkü bunlar teknik olarak dosyalar değil. Bunlar, yazılacak belirli bir cihazı gösteren cihaz düğümleridir. UNIX size her şeyi bir dosya soyutlaması olarak sunabilir, ancak bu onu en derin seviyelerde yapmaz.
paxdiablo

1
Kabuk yeniden yönlendirme özelliğini kullanın. xyz >xyz.outstandart çıktınızı diğer işlemler tarafından okunabilen fiziksel bir dosyaya yazacaktır. stdout'u stdin'e daha doğrudan xyz | grep somethingbağlar . Bu şekilde kontrol etmediğiniz bir prosedüre kayıtsız erişim istiyorsanız, bir şekilde çekirdeğe asarak çıktıyı filtrelemek için kod gibi bir şeye bakmanız veya kod yazmanız gerekir . Başka çözümler de olabilir ama muhtemelen birbirleri kadar tehlikelidir :-)xyzgrep/proc
paxdiablo

20
@Shouvik, şu anda çalışan programın açtığı ilk dosya tanıtıcısı /dev/stdiniçin bir sembolik bağlantı olduğunu unutmayın /proc/self/fd/0. Bu nedenle, işaret /dev/stdinedilen şey programdan programa değişecektir, çünkü /proc/self/her zaman 'şu anda çalışan programı' işaret eder. (Hangi program opençağrıyı yapıyorsa .) /dev/stdinVe arkadaşlar setuid kabuk komut dosyalarını daha güvenli hale getirmek için oraya konuldu ve dosya adını /dev/stdinyalnızca dosyalarla çalışan programlara geçirmenize izin verin , ancak daha etkileşimli olarak kontrol etmek istiyorsunuz. (Bir gün bu bilmeniz için yararlı bir numara olacaktır. :)
sarnold

1
@ CarlosW.Mercado, bir dosya verilerin fiziksel bir tezahürüdür. Örneğin, sabit diskte depolanan bitler. Dosya tanıtıcısı (genellikle), açıldıktan sonra o dosyaya başvurmak için kullanılan küçük bir simgedir.
paxdiablo

62

O söylemek daha doğru olur stdin, stdoutve stderrdosyalardan çok "G / Ç akışları" dir. Fark ettiğiniz gibi, bu varlıklar dosya sisteminde yaşamıyor. Ancak Unix felsefesi, I / O söz konusu olduğunda, "her şey bir dosyadır". Uygulamada, aynı kütüphane fonksiyonları ve arayüzleri (kullanabileceği gerçekten araçlar printf, scanf, read, write, selectG / Ç akışı bir klavye, disk dosyası, soket, bir boru bağlı olup olmadığını önemsemeden, vs.), veya başka bir G / Ç soyutlaması.

Çoğu program böylece girdi, yazma çıkışı ve günlük hataları, okumaya gerek stdin, stdoutve stderrbir programlama kolaylık olarak, sizin için önceden tanımlanmıştır. Bu sadece bir sözleşmedir ve işletim sistemi tarafından uygulanmamaktadır.


Girdileriniz için teşekkürler. Bir sürecin çıktı veri akışını nasıl ele geçirebileceğimi ve bunu kendi dosyama nasıl gönderebileceğimi biliyor muydunuz?
Shouvik

51

Yukarıdaki cevapların bir tamamlayıcısı olarak, Yönlendirmeler hakkında bir özet: Yönlendirmeler hile sayfası

EDIT: Bu grafik tamamen doğru değil ama neden emin değilim ...

Grafikte 2> & 1, &> ile aynı etkiye sahiptir diyor

ls Documents ABC > dirlist 2>&1
#does not give the same output as 
ls Documents ABC > dirlist &>

4
Kabul edilen cevapla birleştirdiğiniz yorumunuz çok mantıklı ve her şeyi net bir şekilde açıklıyor! Teşekkürler!
Mykola

1
Bir resim bin kelime değerinde bir olup !
tauseef_CuriousGuy

22

Korkarım ki anlayışınız tamamen geri. :)

"Standart giriş", "standart çıkış" ve "standart hata" değerlerini çekirdeğin perspektifinden değil , program perspektifinden düşünün .

Bir programın çıktı yazdırması gerektiğinde, normalde "standart çıkış" a yazdırır. Bir program genellikle çıktıyı standart çıkışa printfyazdırır, SADECE standart çıkışa yazdırır.

Bir programın hata bilgilerini yazdırması gerektiğinde (istisnalar olması gerekmez, bunlar çok daha yüksek bir seviyeye yerleştirilmiş bir programlama dili yapısıdır), normalde "standart hataya" yazdırır. Normalde bunu yapar fprintf, bu da yazdırma sırasında kullanılacak bir dosya akışını kabul eder. Standart dışı, standart hata, veya açılmış başka dosyada: Dosya akışı yazma için açılan herhangi bir dosya olabilir fopenveya fdopen.

dosya kullanarak giriş okumaya gerektiğinde "standart" kullanılır freadya fgetsya getchar.

Bu dosyalardan herhangi biri kabuktan kolayca şu şekilde yönlendirilebilir :

cat /etc/passwd > /tmp/out     # redirect cat's standard out to /tmp/foo
cat /nonexistant 2> /tmp/err   # redirect cat's standard error to /tmp/error
cat < /etc/passwd              # redirect cat's standard input to /etc/passwd

Veya tüm enchilada:

cat < /etc/passwd > /tmp/out 2> /tmp/err

İki önemli uyarı vardır: Birincisi, "standart giriş", "standart çıkış" ve "standart hata" sadece bir konudur. Bunlar çok güçlü bir konvansiyon, ama hepsi böyle programları çalıştırabilmenin çok hoş olduğu konusunda hemfikirdir: grep echo /etc/services | awk '{print $2;}' | sortve her programın standart çıktılarının boru hattındaki bir sonraki programın standart girdisine bağlanmasını sağlamaktır.

İkinci olarak, dosya akışları (çalışmak için standart ISO C işlevleri verdik FILE *nesneler) - çekirdek düzeyinde, tüm dosya tanımlayıcıları (olduğu intdosya masaya referanslar) ve çok düşük seviyeli gibi işlemler readve writedo not, ISO C fonksiyonlarının mutlu tamponlamasını yapın. Basit tutmayı ve daha kolay fonksiyonları kullanmayı düşündüm, ama alternatifleri bilmeniz gerektiğini düşündüm. :)


İşlem yürütülürken bu stderr dosyasına hatalar yazıyor veya program kaynağından derleniyor. Ayrıca bu dosyalar hakkında derleyicinin bakış açısıyla konuştuğumuzda, bir program söylemekle kıyaslandığında farklı mıdır?
Shouvik

1
@Shouvik, derleyici kendi stdin, stdout ve stderr ile başka bir program. Derleyicinin uyarı veya hata yazması gerektiğinde bunları stderr'e yazar. Derleyici ön ucu, montajcı için ara kod çıktısı verdiğinde, ara kodu stdout'a yazabilir ve montajcı, stdin'deki girdisini kabul edebilir, ancak kullanıcı olarak perspektifinizden perde arkasındaki her şey.) derlenmiş bir program, bu program da standart hatasında hatalar yazabilirsiniz, ancak derlenmesi ile ilgisi yoktur.
sarnold

Bu bilgi jetonu için teşekkürler. Sanırım yine de bu açıdan görmemek benim için çok aptalca ...: P
Shouvik

1
Yani standardın programı yazdırmamıza yardımcı olduğunu söylüyorsunuz
babygame0ver

9

stdin

Konsoldan girişi okur (örn. Klavye girişi). Scanf ile C'de kullanılır

scanf(<formatstring>,<pointer to storage> ...);

stdout'u

Konsola çıktı üretir. Printf ile C'de kullanılır

printf(<string>, <values to print> ...);

stderr

Konsola 'hata' çıktısı üretir. Fprintf ile C'de kullanılır

fprintf(stderr, <string>, <values to print> ...);

Yönlendirme

Stdin kaynağı yeniden yönlendirilebilir. Örneğin, klavye girişinden gelmek yerine bir dosyadan ( echo < file.txt) veya başka bir programdan ( ps | grep <userid>) gelebilir .

Stdout, stderr hedefleri de yeniden yönlendirilebilir. Örneğin stdout bir dosyaya yeniden yönlendirilebilir: ls . > ls-output.txtbu durumda çıktı dosyaya yazılır ls-output.txt. Stderr yönlendirilebilir ile 2>.


8

Bence stderrsadece hata mesajları için kullanılması gerektiğini söyleyen insanlar yanıltıcıdır.

Ayrıca, komutu çalıştıran kullanıcı için olan ve verilerin potansiyel aşağı akım tüketicileri için olmayan bilgilendirici mesajlar için de kullanılmalıdır (örneğin, birkaç komutu zincirleyen bir kabuk borusu çalıştırırsanız " 42424 " stdout Ancak, kullanıcının bunları görmesini isteyebilirsiniz.

Bkz bu tarihsel gerekçe için:

"Tüm programlar standart çıktıya tanı koydu. Bu, çıktı dosyaya yönlendirildiğinde her zaman soruna yol açtı, ancak çıktı şüpheli olmayan bir sürece gönderildiğinde dayanılmaz hale geldi. Bununla birlikte, standart girdinin sadeliğini ihlal etmek istemiyor Standart çıktı modelinde, insanlar bu durumu v6 ile tolere ettiler Kısa bir süre sonra Dennis Ritchie, standart hata dosyasını tanıtarak Gordian düğümünü kesti. Bu yeterli değildi. kendilerini tanımlamak için. "


3

Ps -aux kullanımı, tümü / proc / as / proc / (pid) / içinde listelenen geçerli işlemleri ortaya çıkarır, cat / proc / (pid) / fd / 0'ı çağırarak standart çıktısında bulunan her şeyi yazdırır. sanırım bu süreç. Belkide,

/ proc / (pid) / fd / 0 - Standart Çıktı Dosyası
/ proc / (pid) / fd / 1 - Standart Giriş Dosyası
/ proc / (pid) / fd / 2 - Standart Hata Dosyası

Örneğinterminal pencerem

Ancak / bin / bash için sadece bu iyi çalıştı, diğer işlemler genellikle 0'da hiçbir şeye sahip değildi, ancak çoğunda 2'de yazılmış hatalar vardı


3

Bu dosyalar hakkında yetkili bilgiler için man sayfalarına bakın, terminalinizdeki komutu çalıştırın.

$ man stdout 

Ancak basit bir cevap için, her dosya şöyledir:

dışarı akış için stdout

akış girişi için stdin

baskı hataları veya günlük mesajları için stderr .

Her unix programı bu akışların her birine sahiptir.


2

stderr, GÇ Önbellek arabelleğe almaz, bu nedenle uygulamamızın kritik ileti bilgilerini (bazı hatalar, istisnalar) konsola veya dosyaya yazdırması gerekiyorsa, GÇ Önbellek arabelleğe almayı kullanırken genel günlük bilgilerini yazdırmak için stdout'u kullandığınız yerlerde kullanmak için bir şans vardır. mesajlarımızı dosya uygulamasına yazmadan önce hata ayıklama karmaşıklığı bırakarak kapanabilir


0

İlişkilendirilmiş arabelleğe alma içeren bir dosyaya akış adı verilir ve tanımlı bir DOSYA türüne işaretçi olarak bildirilir. Fopen () işlevi, bir akış için belirli açıklayıcı veriler oluşturur ve diğer tüm işlemlerde akışı belirtmek için bir işaretçi döndürür. Normalde, başlıkta bildirilen ve standart açık dosyalarla ilişkili sabit işaretçiler içeren üç açık akış vardır. Program başlangıcında üç akış önceden tanımlanmıştır ve açıkça açılması gerekmez: standart giriş (geleneksel girişi okumak için), standart çıkış (geleneksel çıkışı yazmak için) ve standart hata (tanı çıktısını yazmak için). Açıldığında standart hata akışı tam olarak arabelleğe alınmaz; standart giriş ve standart çıkış akışları, yalnızca akışın etkileşimli bir aygıta başvurmayacağı belirlenebiliyorsa tamamen arabelleğe alınır

https://www.mkssoftware.com/docs/man5/stdio.5.asp

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.