Bingung tentang stdin, stdout dan stderr?

230

Saya agak bingung dengan tujuan dari ketiga file ini. Jika pemahaman saya benar, stdinadalah file di mana suatu program menulis permintaannya untuk menjalankan tugas dalam proses, stdoutadalah file yang digunakan kernel untuk menulis outputnya dan proses yang dimintanya mengakses informasi dari, dan stderrmerupakan file ke dalam dimana semua pengecualian dimasukkan. Saat membuka file-file ini untuk memeriksa apakah ini benar-benar terjadi, saya menemukan tidak ada yang menyarankan begitu!

Apa yang ingin saya ketahui adalah apa sebenarnya tujuan dari file-file ini, benar-benar membodohi jawaban dengan jargon teknologi yang sangat sedikit!

Shouvik
sumber
36
Pengamatan: Pertanyaan ini dapat diterima kembali pada tahun 2010, tetapi akan turun cepat sekarang.
byxor
3
@Brandon Bisakah Anda memberikan alasan? Saya pikir ini akan berharga untuk komentar Anda.
Independen
3
@byxor agar adil, saya akan bertanya: Apakah posting op meminta orang untuk membantunya men-debug kode-kodenya? sepertinya Shouvik mengajukan pertanyaan mengenai tujuan stdin, stdout, dan stderr. posting op tampaknya keluar dari rasa ingin tahu, bukan? (Saya sebenarnya belajar tentang hal ini sendiri. Terima kasih, SO, karena tidak menghapus posting ini)
sansae
2
@ user123456 Anda benar. Saya belajar menjadi pengembang perangkat lunak dan S / O saat itu adalah tempat yang tepat untuk belajar tentang pemrograman. Kami awalnya bermaksud untuk menjadi layanan wiki semacam untuk semua pertanyaan ilmu komputasi. #juniorDevForLife
Shouvik
3
@Shouvik terima kasih atas sedikit sejarahnya. Saya belajar bagaimana menjadi pengembang perangkat lunak juga (baru saja diterima di kamp keren di sf). Saya masih cukup baru untuk S / O dan masih tidak yakin tentang apa yang saya bisa dan tidak bisa posting. Saya menemukan bahwa moderasi di sini bisa sangat ketat. Saya suka tag hash itu. #juniorDevForLife. Saya lebih suka Anda daripada berkomentar di sini karena ini tidak menambah apa-apa untuk diskusi, tapi saya tidak percaya S / O memiliki sistem pm. Semoga hari mu menyenangkan.
sansae

Jawaban:

251

Input standar - ini adalah pegangan file yang dibaca proses Anda untuk mendapatkan informasi dari Anda.

Output standar - proses Anda menulis informasi normal ke pegangan file ini.

Kesalahan standar - proses Anda menulis informasi kesalahan ke pegangan file ini.

Itu hampir sama bodohnya dengan yang saya bisa lakukan :-)

Tentu saja, itu kebanyakan berdasarkan konvensi. Tidak ada yang menghentikan Anda dari menulis informasi kesalahan Anda ke output standar jika Anda mau. Anda bahkan dapat menutup ketiga pegangan file sepenuhnya dan membuka file Anda sendiri untuk I / O.

Ketika proses Anda dimulai, itu seharusnya sudah memiliki pegangan ini terbuka dan itu hanya bisa membaca dari dan / atau menulis kepada mereka.

Secara default, mereka mungkin terhubung ke perangkat terminal Anda (misalnya, /dev/tty) tetapi shell akan memungkinkan Anda untuk mengatur koneksi antara ini menangani dan file tertentu dan / atau perangkat (atau bahkan pipa ke proses lain) sebelum proses Anda dimulai (beberapa dari manipulasi yang mungkin agak pintar).

Contohnya adalah:

my_prog <inputfile 2>errorfile | grep XYZ

yang mana akan:

  • buat proses untuk my_prog.
  • buka inputfilesebagai input standar Anda (pegangan file 0).
  • buka errorfilesebagai kesalahan standar Anda (pegangan file 2).
  • buat proses lain untuk grep.
  • melampirkan output standar my_progke input standar grep.

Berikan komentar Anda:

Ketika saya membuka file-file ini di folder / dev, kenapa saya tidak pernah melihat output dari proses yang berjalan?

Itu karena mereka bukan file normal. Sementara UNIX menyajikan semuanya sebagai file dalam sistem file di suatu tempat, itu tidak membuatnya jadi pada level terendah. Sebagian besar file dalam /devhierarki adalah perangkat karakter atau blokir, yang secara efektif merupakan driver perangkat. Mereka tidak memiliki ukuran tetapi mereka memiliki nomor perangkat utama dan kecil.

Saat Anda membukanya, Anda terhubung ke driver perangkat daripada file fisik, dan driver perangkat cukup pintar untuk mengetahui bahwa proses terpisah harus ditangani secara terpisah.

Hal yang sama berlaku untuk sistem /procfile Linux . Itu bukan file asli, hanya gateway yang dikontrol ketat untuk informasi kernel.

paxdiablo
sumber
1
Itulah tanggapan Anda. Sementara saya dapat memahami tujuan file dari apa yang Anda gambarkan, saya ingin naik level lebih lanjut. ketika saya membuka file-file ini di folder / dev, kenapa saya tidak pernah melihat output dari proses yang berjalan. Katakanlah saya mengeksekusi atas pada terminal, apakah itu tidak seharusnya menampilkan hasilnya ke file stdout secara berkala, maka ketika sedang diperbarui saya harus dapat melihat contoh dari output yang dicetak ke file ini. Tapi ini tidak begitu .. Begitu juga file-file ini tidak sama (yang ada di direktori / dev).
Shouvik
7
Karena itu bukan file secara teknis. Mereka adalah node perangkat, menunjukkan perangkat tertentu untuk menulis. UNIX dapat menyajikan segala sesuatu kepada Anda sebagai abstraksi file tetapi itu tidak membuatnya begitu pada tingkat terdalam.
paxdiablo
1
Gunakan kemampuan pengalihan shell. xyz >xyz.outakan menulis output standar Anda ke file fisik yang dapat dibaca oleh proses lain. xyz | grep somethingakan menghubungkan xyzstdout ke grepstdin lebih langsung. Jika Anda ingin akses tanpa batas ke proses yang tidak Anda kontrol dengan cara itu, Anda perlu melihat sesuatu seperti /procatau menulis kode untuk memfilter output dengan cara menghubungkannya ke kernel. Mungkin ada solusi lain tetapi mereka semua mungkin sama berbahayanya dengan yang lain :-)
paxdiablo
20
@ Shouvik, perhatikan bahwa /dev/stdinini adalah symlink ke /proc/self/fd/0- deskriptor file pertama yang dibuka oleh program yang sedang berjalan. Jadi, apa yang ditunjukkan oleh /dev/stdinakan berubah dari program ke program, karena /proc/self/selalu menunjuk ke 'program yang sedang berjalan'. (Program mana pun yang melakukan openpanggilan.) /dev/stdinDan teman-teman diletakkan di sana untuk membuat skrip shell setuid lebih aman, dan memungkinkan Anda meneruskan nama file /dev/stdinke program yang hanya bekerja dengan file, tetapi Anda ingin mengontrol lebih interaktif. (Suatu hari nanti ini akan menjadi trik yang berguna untuk Anda ketahui. :)
sarnold
1
@ CarlosW.Mercado, file adalah manifestasi fisik dari data. Misalnya, bit yang disimpan di hard disk. Menangani file adalah (biasanya) token kecil yang digunakan untuk merujuk ke file itu, setelah Anda membukanya.
paxdiablo
62

Akan lebih benar untuk mengatakan bahwa stdin, stdout, dan stderradalah "I / O stream" bukan file. Seperti yang Anda perhatikan, entitas ini tidak hidup di sistem file. Tetapi filosofi Unix, sejauh menyangkut I / O, adalah "semuanya adalah file". Dalam praktiknya, itu benar-benar berarti bahwa Anda dapat menggunakan fungsi dan antarmuka pustaka yang sama ( printf, scanf , read, write, select, dll) tanpa perlu khawatir apakah aliran I / O terhubung ke keyboard, file disk, socket, pipa, atau abstraksi I / O lainnya.

Kebanyakan program perlu membaca input, menulis output, dan kesalahan log, sehingga stdin, stdout, dan stderryang telah ditetapkan untuk Anda, sebagai kenyamanan pemrograman. Ini hanya konvensi, dan tidak diberlakukan oleh sistem operasi.

Jim Lewis
sumber
Terima kasih atas masukan Anda. Apakah Anda tahu bagaimana saya bisa mencegat aliran data output dari suatu proses dan output ke file saya sendiri?
Shouvik
51

Sebagai pelengkap dari jawaban di atas, berikut adalah ringkasan tentang Pengalihan: Lembar balik pengalihan

EDIT: Grafik ini tidak sepenuhnya benar tetapi saya tidak yakin mengapa ...

Grafik mengatakan 2> & 1 memiliki efek yang sama dengan &>

ls Documents ABC > dirlist 2>&1
#does not give the same output as 
ls Documents ABC > dirlist &>
Leopold Gault
sumber
4
Komentar Anda yang dikombinasikan dengan jawaban yang diterima masuk akal dan menjelaskan banyak hal! Terima kasih!
Mykola
1
Sebuah gambar bernilai ribuan kata!
tauseef_CuriousGuy
22

Saya khawatir pengertian Anda sepenuhnya mundur. :)

Pikirkan "standar dalam", "keluar standar", dan "kesalahan standar" dari perspektif program , bukan dari perspektif kernel.

Ketika suatu program perlu mencetak keluaran, biasanya ia mencetak ke "out standar". Suatu program biasanya mencetak output ke standar dengan printf, yang mencetak HANYA ke standar keluar.

Ketika suatu program perlu mencetak informasi kesalahan (tidak harus pengecualian, itu adalah konstruksi bahasa pemrograman, dikenakan pada tingkat yang jauh lebih tinggi), itu biasanya dicetak ke "kesalahan standar". Ini biasanya dilakukan dengan fprintf, yang menerima aliran file untuk digunakan saat mencetak. Aliran file dapat berupa file apa saja yang dibuka untuk ditulis: standar keluar, kesalahan standar, atau file lain apa pun yang telah dibuka dengan fopenataufdopen .

"standar dalam" digunakan ketika file perlu membaca input, menggunakan freadatau fgets, atau getchar.

File-file ini dapat dengan mudah dialihkan dari shell, seperti ini:

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

Atau, seluruh enchilada:

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

Ada dua peringatan penting: Pertama, "standar dalam", "standar keluar", dan "kesalahan standar" hanyalah sebuah konvensi. Mereka adalah konvensi yang sangat kuat , tetapi itu semua hanya kesepakatan bahwa sangat bagus untuk dapat menjalankan program seperti ini:grep echo /etc/services | awk '{print $2;}' | sort dan memiliki output standar dari setiap program yang terhubung ke input standar dari program berikutnya di dalam pipa.

Kedua, saya telah memberikan fungsi standar ISO C untuk bekerja dengan aliran file ( FILE *objek) - pada level kernel, semuanya adalah deskriptor file ( intreferensi ke tabel file) dan banyak operasi level yang lebih rendah seperti readdan write, yang tidak lakukan penyanggaan senang fungsi ISO C. Saya pikir untuk membuatnya tetap sederhana dan menggunakan fungsi yang lebih mudah, tapi saya pikir semua yang sama Anda harus tahu alternatifnya. :)

sarnold
sumber
Begitu juga ketika proses sedang dieksekusi yang menulis kesalahan ke file stderr ini atau ketika program sedang dikompilasi dari sumbernya. Juga ketika kita berbicara tentang file-file ini dari perspektif kompiler itu berbeda dari ketika dibandingkan dengan katakanlah sebuah program?
Shouvik
1
@ Shouvik, kompiler hanyalah program lain, dengan stdin, stdout, dan stderr sendiri. Ketika kompiler perlu menulis peringatan atau kesalahan, ia akan menulisnya ke stderr. Ketika front-end kompiler mengeluarkan kode perantara untuk assembler, kompiler tersebut mungkin menulis kode perantara di stdout dan assembler mungkin menerima inputnya pada stdin, tetapi semua itu akan berada di belakang layar dari sudut pandang Anda sebagai pengguna.) Setelah Anda memiliki sebuah program yang dikompilasi, program itu dapat menulis kesalahan ke kesalahan standar juga, tetapi tidak ada hubungannya dengan dikompilasi.
sarnold
Terima kasih atas token informasi itu. Saya kira itu sangat bodoh bagi saya untuk tidak melihatnya dalam perspektif itu ...: P
Shouvik
1
Jadi Anda mengatakan bahwa standar membantu kami untuk mencetak program
babygame0ver
9

stdin

Membaca input melalui konsol (mis. Input Keyboard). Digunakan dalam C dengan scanf

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

stdout

Menghasilkan output ke konsol. Digunakan dalam C dengan printf

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

stderr

Menghasilkan output 'error' ke konsol. Digunakan dalam C dengan fprintf

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

Pengalihan

Sumber untuk stdin dapat dialihkan. Misalnya, alih-alih berasal dari input keyboard, ini dapat berasal dari file ( echo < file.txt), atau program lain ( ps | grep <userid>).

Tujuan untuk stdout, stderr juga dapat diarahkan. Misalnya stdout dapat diarahkan ke file:, ls . > ls-output.txtdalam hal ini output ditulis ke file ls-output.txt. Stderr dapat dialihkan dengan 2>.

mikek3332002
sumber
8

Saya pikir orang-orang mengatakan stderrhanya boleh digunakan untuk pesan kesalahan menyesatkan.

Ini juga harus digunakan untuk pesan informatif yang dimaksudkan untuk pengguna yang menjalankan perintah dan bukan untuk konsumen hilir potensial dari data (yaitu jika Anda menjalankan pipa shell chaining beberapa perintah Anda tidak ingin pesan informatif seperti "mendapatkan item 30 dari 42424 "muncul stdoutkarena mereka akan membingungkan konsumen, tetapi Anda mungkin masih ingin pengguna melihatnya.

Lihat ini untuk alasan historis:

"Semua program menempatkan diagnostik pada output standar. Ini selalu menyebabkan masalah ketika output diarahkan ke file, tetapi menjadi tidak dapat ditoleransi ketika output dikirim ke proses yang tidak curiga. Meskipun demikian, tidak mau melanggar kesederhanaan input-standar- model output-standar, orang mentolerir keadaan ini melalui v6. Tak lama kemudian Dennis Ritchie memotong simpul Gordian dengan memperkenalkan file kesalahan standar. Itu tidak cukup memadai. Dengan pipeline, diagnostik dapat berasal dari beberapa program yang berjalan secara bersamaan. untuk mengidentifikasi diri mereka sendiri. "

dee
sumber
3

Menggunakan ps -aux mengungkapkan proses saat ini, yang semuanya terdaftar di / proc / as / proc / (pid) /, dengan memanggil cat / proc / (pid) / fd / 0 itu mencetak apa pun yang ditemukan dalam output standar dari proses itu saya pikir. Jadi mungkin,

/ proc / (pid) / fd / 0 - File Output Standar
/ proc / (pid) / fd / 1 - File Input Standar
/ proc / (pid) / fd / 2 - File Kesalahan Standar

sebagai contohjendela terminal saya

Tetapi hanya bekerja dengan baik untuk / bin / bash proses lain umumnya tidak ada dalam 0 tetapi banyak kesalahan ditulis dalam 2

Sam
sumber
3

Untuk informasi otoritatif tentang file-file ini, periksa halaman manual, jalankan perintah pada terminal Anda.

$ man stdout 

Tetapi untuk jawaban sederhana, setiap file adalah untuk:

stdout untuk streaming

stdin untuk input aliran

stderr untuk kesalahan pencetakan atau pesan log.

Setiap program unix memiliki masing-masing aliran tersebut.

Margach Chris
sumber
2

stderr tidak akan melakukan buffering IO Cache jadi jika aplikasi kita perlu mencetak info pesan penting (beberapa kesalahan, pengecualian) untuk menghibur atau file menggunakannya di mana seperti menggunakan stdout untuk mencetak info log umum karena menggunakan buffering IO Cache ada kemungkinan bahwa sebelum menulis pesan kami ke aplikasi file mungkin ditutup, meninggalkan kompleks debugging

geekanil
sumber
0

File dengan buffering terkait disebut stream dan dinyatakan sebagai pointer ke jenis FILE yang ditentukan. Fungsi fopen () membuat data deskriptif tertentu untuk streaming dan mengembalikan pointer untuk menunjuk aliran dalam semua transaksi lebih lanjut. Biasanya ada tiga stream terbuka dengan pointer konstan yang dideklarasikan di header dan dikaitkan dengan file open standar. Pada startup program tiga aliran sudah ditentukan sebelumnya dan tidak perlu dibuka secara eksplisit: input standar (untuk membaca input konvensional), output standar (untuk menulis output konvensional), dan standard error (untuk menulis output diagnostik). Ketika dibuka, aliran kesalahan standar tidak sepenuhnya buffer; input standar dan output stream standar sepenuhnya buffered jika dan hanya jika aliran dapat ditentukan untuk tidak merujuk ke perangkat interaktif

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

Bahruz Balabayov
sumber