Apa itu stdin, stdout, dan stderr di Linux?
stdin
, stdout
dan stderr
merupakan 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
, stdout
dan 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, stdin
adalah 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, stdout
dan 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
, stdout
dan 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 ls
berkelakuan arahan berbeza jika output ( stdout
) sedang disalurkan ke arahan lain. Ia ls
beralih ke output lajur tunggal, bukan penukaran yang dilakukan oleh cat
. Dan ls
melakukan 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 stdout
telah 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 stdout
aliran. 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, stdout
dan stderr
, telah ditampilkan di tingkap terminal.
Mari cuba ubah output ke fail:
./error.sh> capture.txt
Mesej ralat yang dihantar stderr
masih dihantar ke tetingkap terminal. Kami dapat memeriksa kandungan fail untuk melihat apakah stdout
output masuk ke fail.
tangkapan kucing.txt
Keluaran dari stdin
diarahkan ke file seperti yang diharapkan.
The >
simbol redirection berfungsi dengan stdout
secara 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 stdout
echo
mesej dihantar ke tetingkap terminal:
Mari lihat apa yang ada dalam fail capture.txt.
tangkapan kucing.txt
The stderr
mesej di capture.txt seperti yang diharapkan.
Mengalihkan Kedua stdout dan stderr
Tentunya, jika kita dapat mengarahkan salah satu stdout
atau stderr
ke 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 stdout
ke fail yang disebut capture.txt dan stderr
ke 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 stderr
ke 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 : Mengalihkan
stdout
aliran ke fail capture.txt.>
adalah pendek untuk1>
. - 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,stdout
sedang 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 stdout
dan stderr
aliran 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 stdin
disambungkan ke tetingkap terminal ujian akan terbukti benar. Sekiranya stdin
disambungkan 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 stdin
aliran tidak disambungkan ke tetingkap terminal.
Mari jalankan skrip tanpa paip atau pengalihan.
./input.sh
The stdin
aliran 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 stdout
aliran tidak dihantar terus ke tetingkap terminal.
Sekiranya kita menjalankan skrip tanpa paip atau pengalihan, ia harus mengesan yang stdout
dihantar 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.