Apa itu stdin, stdout, dan stderr di Linux?

stdin, stdoutdan stderrmerupakan tiga aliran data yang dibuat ketika anda melancarkan perintah Linux. Anda dapat menggunakannya untuk mengetahui apakah skrip anda disalurkan atau dialihkan. Kami menunjukkan kepada anda bagaimana.

Aliran Bergabung dengan Dua Mata

Sebaik sahaja anda mula belajar tentang Linux dan Unix seperti sistem operasi, anda akan menemui istilah stdin, stdoutdan stederr. Ini adalah tiga aliran standard yang dibuat ketika perintah Linux dijalankan. Dalam pengkomputeran, aliran adalah sesuatu yang dapat memindahkan data. Dalam kes aliran ini, data tersebut adalah teks.

Aliran data, seperti aliran air, mempunyai dua hujung. Mereka mempunyai sumber dan aliran keluar. Apa sahaja arahan Linux yang anda gunakan menyediakan satu hujung setiap aliran. Hujung yang lain ditentukan oleh shell yang melancarkan perintah. Bahagian hujung itu akan dihubungkan ke tetingkap terminal, disambungkan ke paip, atau diarahkan ke fail atau arahan lain, sesuai dengan baris perintah yang melancarkan perintah.

Aliran Piawai Linux

Di Linux,  stdinadalah aliran input standard. Ini menerima teks sebagai inputnya. Output teks dari perintah ke shell dihantar melalui aliran stdout(standard out). Mesej ralat dari arahan dihantar melalui aliran stderr(ralat standard).

Jadi, anda boleh melihat bahawa terdapat dua aliran output, stdoutdan stderr, dan satu aliran input, stdin. Kerana mesej ralat dan output normal masing-masing mempunyai saluran tersendiri untuk membawanya ke tingkap terminal, ia dapat ditangani secara bebas antara satu sama lain.

Aliran Dikendalikan Seperti Fail

Aliran di Linux - seperti hampir semua perkara - diperlakukan seolah-olah fail. Anda dapat membaca teks dari fail, dan menulis teks ke dalam fail. Kedua-dua tindakan ini melibatkan aliran data. Jadi konsep mengendalikan aliran data sebagai fail tidak terlalu banyak.

Setiap fail yang dikaitkan dengan proses diperuntukkan nombor unik untuk mengenalinya. Ini dikenali sebagai deskriptor fail. Setiap kali tindakan diperlukan untuk dilakukan pada file, deskriptor file digunakan untuk mengenal pasti file tersebut.

Nilai-nilai ini selalu digunakan untuk stdin, stdout,dan stderr:

  • 0 : stdin
  • 1 : stdout
  • 2 : stderr

Memberi reaksi kepada Paip dan Pengalihan

Untuk memudahkan pengenalan seseorang terhadap subjek, teknik yang biasa dilakukan adalah mengajar versi topik yang dipermudahkan. Sebagai contoh, dengan tatabahasa, kita diberitahu bahawa aturannya adalah "Saya sebelum E, kecuali setelah C." Tetapi sebenarnya, ada lebih banyak pengecualian terhadap peraturan ini daripada ada kes yang mematuhinya.

Dalam nada yang sama, apabila bercakap tentang stdin, stdoutdan stderr ia adalah mudah untuk berlari keluar aksiom diterima bahawa proses yang tidak tahu dan tidak peduli di mana tiga aliran standard yang akan dibubarkan. Perlukah proses memperhatikan apakah outputnya menuju terminal atau diarahkan ke fail? Bolehkah ia mengetahui sama ada inputnya berasal dari keyboard atau disalurkan ke dalamnya dari proses lain?

Sebenarnya, suatu proses tahu - atau paling tidak ia dapat mengetahui, apakah harus memilih untuk diperiksa - dan ia dapat mengubah perilakunya dengan sewajarnya jika pengarang perisian memutuskan untuk menambahkan fungsi tersebut.

Kita dapat melihat perubahan tingkah laku ini dengan mudah. Cubalah dua arahan berikut:

ls

ls | kucing

Yang lsberkelakuan arahan berbeza jika output ( stdout) sedang disalurkan ke arahan lain. Ia  lsberalih ke output lajur tunggal, bukan penukaran yang dilakukan oleh cat. Dan lsmelakukan perkara yang sama jika outputnya diarahkan:

ls> tangkapan.txt

tangkapan kucing.txt

Mengalihkan stdout dan stderr

Terdapat kelebihan untuk menghantar mesej ralat melalui aliran khusus. Ini bererti kita dapat mengalihkan output perintah ( stdout) ke file dan masih melihat sebarang pesan kesalahan ( stderr) di tetingkap terminal. Anda boleh bertindak balas terhadap kesalahan jika anda perlu, semasa ia berlaku. Ini juga menghentikan mesej ralat daripada mencemarkan fail yang stdouttelah dialihkan ke.

Ketik teks berikut ke dalam editor dan simpan ke fail yang disebut error.sh.

#! / bin / bash echo "Akan cuba mengakses fail yang tidak ada" cat bad-filename.txt

Jadikan skrip boleh dilaksanakan dengan arahan ini:

chmod + x error.sh

Baris pertama skrip menggema teks ke tetingkap terminal, melalui  stdoutaliran. Baris kedua cuba mengakses fail yang tidak ada. Ini akan menghasilkan mesej ralat yang dihantar melalui stderr.

Jalankan skrip dengan arahan ini:

./error.sh

Kita dapat melihat bahawa kedua-dua aliran output, stdoutdan stderr, telah ditampilkan di tingkap terminal.

Mari cuba ubah output ke fail:

./error.sh> capture.txt

Mesej ralat yang dihantar stderrmasih dihantar ke tetingkap terminal. Kami dapat memeriksa kandungan fail untuk melihat apakah stdout output masuk ke fail.

tangkapan kucing.txt

Keluaran dari stdindiarahkan ke file seperti yang diharapkan.

The >simbol redirection berfungsi dengan stdoutsecara lalai. Anda boleh menggunakan salah satu deskriptor fail berangka untuk menunjukkan aliran output standard mana yang ingin anda ubah.

Untuk mengalihkan secara eksplisit  stdout, gunakan arahan pengalihan ini:

1>

Untuk mengalihkan secara eksplisit  stderr, gunakan arahan pengalihan ini:

2>

Mari cuba lagi ujian kami, dan kali ini kami akan menggunakan 2>:

./error.sh 2> capture.txt

Mesej ralat dialihkan dan stdoutechomesej dihantar ke tetingkap terminal:

Mari lihat apa yang ada dalam fail capture.txt.

tangkapan kucing.txt

The stderrmesej di capture.txt seperti yang diharapkan.

Mengalihkan Kedua stdout dan stderr

Tentunya, jika kita dapat mengarahkan salah satu stdoutatau stderrke fail secara bebas antara satu sama lain, kita seharusnya dapat mengarahkan kedua-duanya pada masa yang sama, ke dua fail yang berbeza?

Ya kita boleh. Perintah ini akan mengarahkan stdoutke fail yang disebut capture.txt dan stderrke fail yang disebut error.txt.

./error.sh 1> capture.txt 2> error.txt

Kerana kedua-dua aliran output-output standard dan ralat standard-dialihkan ke fail, tidak ada output yang dapat dilihat di tetingkap terminal. Kami dikembalikan ke command line seolah-olah tidak ada yang berlaku.

Mari periksa kandungan setiap fail:

tangkapan kucing.txt
kesalahan kucing.txt

Mengalihkan stdout dan stderr ke Fail yang Sama

Itu kemas, kami mempunyai setiap aliran output standard menuju ke fail khasnya sendiri. Satu-satunya kombinasi lain yang boleh kita lakukan adalah menghantar kedua stdout- duanya dan stderrke fail yang sama.

Kami dapat mencapainya dengan arahan berikut:

./error.sh> capture.txt 2> & 1

Mari memecahkannya.

  • ./error.sh : Melancarkan fail skrip error.sh.
  • > capture.txt : Mengalihkanstdout aliran ke fail capture.txt. >adalah pendek untuk 1>.
  • 2> & 1 : Ini menggunakan arahan &> redirect. Arahan ini membolehkan anda memberitahu shell untuk membuat satu aliran sampai ke destinasi yang sama dengan aliran lain. Dalam hal ini, kita mengatakan "redirect stream 2 stderr, ke tujuan yang sama dengan stream 1, stdoutsedang dialihkan ke."

Tidak ada output yang dapat dilihat. Itu memberangsangkan.

Mari periksa fail capture.txt dan lihat apa yang ada di dalamnya.

tangkapan kucing.txt

Kedua stdoutdan stderraliran telah diarahkan ke satu fail tujuan.

Agar output aliran dialihkan dan dibuang secara senyap, arahkan output ke /dev/null.

Mengesan Pengalihan Dalam Skrip

Kami membincangkan bagaimana perintah dapat mengesan jika ada aliran yang diarahkan, dan dapat memilih untuk mengubah perilakunya dengan sewajarnya. Bolehkah kita mencapainya dalam skrip kita sendiri? Ya kita boleh. Dan ini adalah teknik yang sangat mudah untuk difahami dan digunakan.

Taipkan teks berikut ke dalam editor dan simpan sebagai input.sh.

#! / bin / bash jika [-t 0]; kemudian echo stdin datang dari papan kekunci lain echo stdin berasal dari paip atau fail fi

Gunakan arahan berikut untuk membuatnya dapat dilaksanakan:

chmod + x input.sh

Bahagian yang cerdik adalah ujian dalam kurungan segi empat. Pilihan -t(terminal) mengembalikan true (0) jika fail yang berkaitan dengan deskriptor fail berakhir di tetingkap terminal. Kami telah menggunakan deskriptor fail 0 sebagai argumen untuk ujian, yang mewakili   stdin.

Sekiranya stdindisambungkan ke tetingkap terminal ujian akan terbukti benar. Sekiranya stdindisambungkan ke fail atau paip, ujian akan gagal.

Kami dapat menggunakan fail teks yang sesuai untuk menghasilkan input ke skrip. Di sini kita menggunakan satu yang dipanggil dummy.txt.

./input.sh <dummy.txt

Output menunjukkan bahawa skrip menyedari bahawa input tidak berasal dari papan kekunci, itu berasal dari file. Sekiranya anda memilih, anda boleh mengubah tingkah laku skrip anda dengan sewajarnya.

Itu dengan pengalihan fail, mari kita mencubanya dengan paip.

kucing dummy.txt | ./input.sh

Skrip menyedari bahawa inputnya disalurkan ke dalamnya. Atau lebih tepat lagi, ia menyedari sekali lagi bahawa stdinaliran tidak disambungkan ke tetingkap terminal.

Mari jalankan skrip tanpa paip atau pengalihan.

./input.sh

The stdinaliran disambungkan ke tetingkap terminal, dan skrip laporan ini dengan sewajarnya.

Untuk memeriksa perkara yang sama dengan aliran output, kita memerlukan skrip baru. Taipkan yang berikut ke dalam editor dan simpan sebagai output.sh.

#! / bin / bash jika [-t 1]; maka echo stdout akan ke tetingkap terminal yang lain echo stdout sedang diarahkan atau dialirkan fi

Gunakan arahan berikut untuk membuatnya dapat dilaksanakan:

chmod + x input.sh

Satu-satunya perubahan yang signifikan pada skrip ini adalah ujian dalam tanda kurung siku. Kami menggunakan digit 1 untuk mewakili deskriptor fail untuk stdout.

Mari mencubanya. Kami akan mengeluarkan output cat.

./keluaran | kucing

Skrip menyedari bahawa outputnya tidak akan langsung ke tetingkap terminal.

Kami juga dapat menguji skrip dengan mengalihkan output ke file.

./output.sh> capture.txt

Tidak ada output ke tetingkap terminal, kami diam-diam dikembalikan ke command prompt. Seperti yang kita jangkakan.

Kita boleh melihat ke dalam fail capture.txt untuk melihat apa yang ditangkap. Gunakan arahan berikut untuk melakukannya.

tangkapan kucing.sh

Sekali lagi, ujian mudah dalam skrip kami mengesan bahawa stdoutaliran tidak dihantar terus ke tetingkap terminal.

Sekiranya kita menjalankan skrip tanpa paip atau pengalihan, ia harus mengesan yang stdoutdihantar terus ke tetingkap terminal.

./output.sh

Dan itulah yang kita lihat.

Aliran Kesedaran

Mengetahui bagaimana untuk mengetahui apakah skrip anda disambungkan ke tetingkap terminal, atau paip, atau sedang diarahkan, membolehkan anda menyesuaikan tingkah laku mereka dengan sewajarnya.

Hasil log dan output diagnostik dapat lebih terperinci, bergantung pada apakah itu akan ke layar atau ke fail. Mesej ralat dapat masuk ke fail yang berbeza daripada output program biasa.

Seperti biasanya, lebih banyak pengetahuan membawa lebih banyak pilihan.