Какво представляват stdin, stdout и stderr в Linux?

stdin, stdoutи stderrса три потока от данни, създадени при стартиране на Linux команда. Можете да ги използвате, за да разберете дали вашите скриптове се пренасочват или пренасочват. Ние ви показваме как.

Потоците се присъединяват към две точки

Веднага след като започне да се запознаят с Linux и Unix-подобни операционни системи, които ще срещнете на условията stdin, stdoutи stederr. Това са три стандартни потока, които се установяват при изпълнение на команда на Linux. При изчисленията потокът е нещо, което може да прехвърля данни. В случая на тези потоци тези данни са текст.

Потоците от данни, като водните потоци, имат два края. Те имат източник и отлив. Която и Linux команда да използвате, предоставя единия край на всеки поток. Другият край се определя от черупката, която е стартирала командата. Този край ще бъде свързан с прозореца на терминала, свързан към тръба или пренасочен към файл или друга команда, в съответствие с командния ред, стартирал командата.

Стандартните потоци на Linux

В Linux  stdinе стандартният входен поток. Това приема текста като свой вход. Текстовият изход от командата към черупката се доставя чрез stdoutпотока (стандартен изход). Съобщенията за грешки от командата се изпращат през stderrпотока (стандартна грешка).

Така че можете да видите, че има два изходни потока, stdoutи stderr, и един входен поток stdin,. Тъй като съобщенията за грешки и нормалният изход имат собствен канал, който да ги пренася до прозореца на терминала, те могат да се обработват независимо един от друг.

Потоците се обработват като файлове

Потоците в Linux - както почти всичко останало - се третират така, сякаш са файлове. Можете да четете текст от файл и можете да пишете текст във файл. И двете действия включват поток от данни. Така че концепцията за обработка на поток от данни като файл не е толкова голяма.

Всеки файл, свързан с процес, получава уникален номер, за да го идентифицира. Това е известно като дескриптор на файла. Винаги, когато се изисква да се извърши действие върху файл, дескрипторът на файла се използва за идентифициране на файла.

Тези стойности винаги се използват за stdin, stdout,и stderr:

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

Реагиране на тръби и пренасочвания

За да се улесни въвеждането на някой в ​​дадена тема, обща техника е да се преподава опростена версия на темата. Например, при граматиката ни се казва, че правилото е „I преди E, с изключение на C.“ Но всъщност има повече изключения от това правило, отколкото случаите, които му се подчиняват.

В подобен смисъл, когато се говори за stdin, stdoutи stderr е удобно да се изведе приетата аксиома, че процесът нито знае, нито се интересува къде са прекратени трите му стандартни потока. Трябва ли процесът да се грижи дали изходът му отива към терминала или ще бъде пренасочен към файл? Може ли дори да разбере дали входът му идва от клавиатурата или се вкарва в него от друг процес?

Всъщност процесът знае - или поне може да разбере, ако реши да провери - и може да промени съответно поведението си, ако авторът на софтуера реши да добави тази функционалност.

Можем да видим тази промяна в поведението много лесно. Опитайте тези две команди:

ls

ls | котка

На lsдържи командните различно, ако резултатите от дейността си ( stdout) е канал към друга команда. Това е,  lsче превключва към изход на една колона, това не е преобразуване, извършено от cat. И lsправи същото нещо, ако изходът му се пренасочва:

ls> capture.txt

cat capture.txt

Пренасочване на stdout и stderr

Има предимство съобщенията за грешки да се доставят от специален поток. Това означава, че можем да пренасочим изхода на команда ( stdout) към файл и все пак да виждаме всички съобщения за грешка ( stderr) в прозореца на терминала. Можете да реагирате на грешките, ако е необходимо, тъй като те възникват. Той също така спира съобщенията за грешки да замърсяват файла, в който stdoutе бил пренасочен.

Въведете следния текст в редактор и го запазете във файл, наречен error.sh.

#! / bin / bash echo "Опит за опит за достъп до файл, който не съществува" cat bad-filename.txt

Направете скрипта изпълним с тази команда:

chmod + x грешка.sh

Първият ред на скрипта излъчва текст към прозореца на терминала чрез  stdoutпотока. Вторият ред се опитва да осъществи достъп до файл, който не съществува. Това ще генерира съобщение за грешка, което се доставя чрез stderr.

Стартирайте скрипта с тази команда:

./error.sh

Можем да видим, че и двата потока на изход stdoutи stderrса показани в терминалните прозорци.

Нека се опитаме да пренасочим изхода към файл:

./error.sh> capture.txt

Съобщението за грешка, което се доставя чрез, stderrвсе още се изпраща до прозореца на терминала. Можем да проверим съдържанието на файла, за да видим дали stdout изходът е отишъл във файла.

cat capture.txt

Изходът от stdinбеше пренасочен към файла, както се очакваше.

Символът за >пренасочване работи stdoutпо подразбиране. Можете да използвате един от числовите файлови дескриптори, за да посочите кой стандартен изходен поток искате да пренасочите.

За изрично пренасочване  stdoutизползвайте тази инструкция за пренасочване:

1>

За изрично пренасочване  stderrизползвайте тази инструкция за пренасочване:

2>

Нека опитаме отново да тестваме и този път ще използваме 2>:

./error.sh 2> capture.txt

Съобщението за грешка се пренасочва и stdoutechoсъобщението се изпраща до прозореца на терминала:

Нека да видим какво има във файла capture.txt.

cat capture.txt

В stderrсъобщението е в capture.txt както се очаква.

Пренасочване както на stdout, така и на stderr

Със сигурност, ако можем да пренасочим един stdoutили stderrдруг файл независимо един от друг, би трябвало да можем да ги пренасочим едновременно към два различни файла?

Да, можем. Тази команда ще насочи stdoutкъм файл, наречен capture.txt и stderrкъм файл, наречен error.txt.

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

Тъй като и двата потока изход - стандартен изход и стандартна грешка - са пренасочени към файлове, няма видим изход в прозореца на терминала. Връщаме се в командния ред, сякаш нищо не се е случило.

Нека проверим съдържанието на всеки файл:

cat capture.txt
cat error.txt

Пренасочване на stdout и stderr към същия файл

Това е добре, имаме всеки от стандартните изходни потоци, който отива в свой собствен специален файл. Единствената друга комбинация, която можем да направим, е да изпратим и двете, stdoutи stderrкъм един и същ файл.

Можем да постигнем това със следната команда:

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

Нека разбием това.

  • ./error.sh : Стартира файла на скрипта error.sh.
  • > capture.txt : Пренасочва stdoutпотока към файла capture.txt. >е стенография за 1>.
  • 2> & 1 : Това използва инструкцията за пренасочване &>. Тази инструкция ви позволява да кажете на черупката да накара един поток да стигне до същата дестинация като друг поток. В този случай казваме, че „пренасочвам поток 2, stderrкъм същата дестинация, към който поток 1, stdoutсе пренасочва“.

Няма видим изход. Това е обнадеждаващо.

Нека проверим файла capture.txt и да видим какво има в него.

cat capture.txt

Както потоците, така stdoutи stderrпотоците са пренасочени към отделен целеви файл.

За да бъде изходът на поток пренасочен и безшумно изхвърлен, насочете изхода към /dev/null.

Откриване на пренасочване в скрипт

Обсъдихме как една команда може да открие дали някой от потоците се пренасочва и можем да изберем да променя поведението си съответно. Можем ли да постигнем това със собствените си скриптове? Да, можем. И това е много лесна техника за разбиране и използване.

Въведете следния текст в редактор и го запазете като input.sh.

#! / bin / bash ако [-t 0]; след това echo stdin идва от клавиатурата else echo stdin идва от тръба или файл fi

Използвайте следната команда, за да го направите изпълним:

chmod + x input.sh

Умната част е тестът в квадратните скоби. Опцията -t(терминал) връща true (0), ако файлът, свързан с дескриптора на файла, завършва в прозореца на терминала. Използвахме файловия дескриптор 0 като аргумент на теста, който представлява   stdin.

Ако stdinе свързан към терминален прозорец, тестът ще се окаже верен. Ако stdinе свързан с файл или тръба, тестът ще се провали.

Можем да използваме всеки удобен текстов файл, за да генерираме вход към скрипта. Тук използваме един, наречен dummy.txt.

./input.sh <dummy.txt

Резултатът показва, че скриптът разпознава, че входът не идва от клавиатура, а идва от файл. Ако решите, можете да промените съответно поведението на вашия скрипт.

Това беше с пренасочване на файл, нека опитаме с тръба.

cat dummy.txt | ./input.sh

Сценарият разпознава, че неговият вход се вкарва в него. Или по-точно, той разпознава още веднъж, че stdinпотокът не е свързан с терминален прозорец.

Нека да стартираме скрипта без нито тръби, нито пренасочвания.

./input.sh

В stdinпоток е свързан с конзолен прозорец, а сценарият отчита това по съответния начин.

За да проверим същото с изходния поток, се нуждаем от нов скрипт. Въведете следното в редактор и го запазете като output.sh.

#! / bin / bash ако [-t 1]; след това echo stdout отива към прозореца на терминала, в противен случай echo stdout се пренасочва или подава fi

Използвайте следната команда, за да го направите изпълним:

chmod + x input.sh

Единствената значителна промяна в този скрипт е в теста в квадратните скоби. Използваме цифрата 1, за да представим дескриптора на файла за stdout.

Нека го изпробваме. Ще прекараме изхода cat.

./output | котка

Скриптът разпознава, че изходът му не отива директно към терминален прозорец.

Също така можем да тестваме скрипта, като пренасочим изхода към файл.

./output.sh> capture.txt

Няма изход към прозореца на терминала, ние се връщаме тихо в командния ред. Както очаквахме.

Можем да погледнем във файла capture.txt, за да видим какво е заснето. Използвайте следната команда, за да го направите.

улавяне на котка.ш

Отново, простият тест в нашия скрипт открива, че stdoutпотокът не се изпраща директно към терминален прозорец.

Ако стартираме скрипта без никакви тръби или пренасочвания, той трябва да открие, че stdoutсе доставя директно в прозореца на терминала.

./output.sh

И точно това виждаме.

Потоци на съзнанието

Знаейки как да разберете дали вашите скриптове са свързани към прозореца на терминала или тръба или са пренасочени, ви позволява да коригирате съответно тяхното поведение.

Изходът за регистриране и диагностика може да бъде повече или по-малко подробен, в зависимост от това дали отива на екрана или във файл. Съобщенията за грешки могат да бъдат регистрирани в файл, различен от нормалния изход на програмата.

Както обикновено се случва, повече знания носят повече възможности.