Ce sunt stdin, stdout și stderr pe Linux?
Publicat: 2022-01-29 stdin
, stdout
și stderr
sunt trei fluxuri de date create atunci când lansați o comandă Linux. Le puteți folosi pentru a afla dacă scripturile dvs. sunt redirecționate sau redirecționate. Vă arătăm cum.
Fluxurile unesc două puncte
De îndată ce începeți să aflați despre Linux și sistemele de operare asemănătoare Unix, veți întâlni termenii stdin
, stdout
și stederr
. Acestea sunt trei fluxuri standard care sunt stabilite atunci când este executată o comandă Linux. În calcul, un flux este ceva care poate transfera date. În cazul acestor fluxuri, acele date sunt text.
Fluxurile de date, precum fluxurile de apă, au două capete. Au o sursă și o ieșire. Indiferent de comandă Linux pe care o utilizați, oferă un capăt al fiecărui flux. Celălalt capăt este determinat de shell-ul care a lansat comanda. Acest capăt va fi conectat la fereastra terminalului, conectat la o conductă sau redirecționat către un fișier sau altă comandă, conform liniei de comandă care a lansat comanda.
Fluxurile standard Linux
În Linux, stdin
este fluxul de intrare standard. Acesta acceptă text ca intrare. Ieșirea textului de la comandă către shell este transmisă prin fluxul stdout
(ieșire standard). Mesajele de eroare de la comandă sunt trimise prin fluxul stderr
(eroare standard).
Deci puteți vedea că există două fluxuri de ieșire, stdout
și stderr
, și un flux de intrare, stdin
. Deoarece mesajele de eroare și ieșirea normală au fiecare conductă proprie pentru a le transporta către fereastra terminalului, acestea pot fi gestionate independent unul de celălalt.
Fluxurile sunt tratate ca și fișiere
Fluxurile în Linux — ca aproape orice altceva — sunt tratate ca și cum ar fi fișiere. Puteți citi text dintr-un fișier și puteți scrie text într-un fișier. Ambele acțiuni implică un flux de date. Deci conceptul de a gestiona un flux de date ca fișier nu este atât de exagerat.
Fiecărui fișier asociat unui proces i se alocă un număr unic pentru a-l identifica. Acesta este cunoscut sub numele de descriptor de fișier. Ori de câte ori este necesară efectuarea unei acțiuni asupra unui fișier, descriptorul fișierului este utilizat pentru a identifica fișierul.
Aceste valori sunt întotdeauna folosite pentru stdin
, stdout,
și stderr
:
- 0 : stdin
- 1 : stdout
- 2 : stderr
Reacționează la conducte și redirecționări
Pentru a ușura introducerea cuiva la un subiect, o tehnică comună este de a preda o versiune simplificată a subiectului. De exemplu, cu gramatica, ni se spune că regula este „I înainte de E, cu excepția după C”. Dar, de fapt, există mai multe excepții de la această regulă decât sunt cazuri care o respectă.
Într-o ordine similară, atunci când vorbim despre stdin
, stdout
și stderr
, este convenabil să scoatem la trap axioma acceptată că unui proces nici nu știe și nici nu-i pasă unde se termină cele trei fluxuri standard ale sale. Ar trebui unui proces să-i pese dacă ieșirea sa va ajunge la terminal sau este redirecționată într-un fișier? Poate chiar să spună dacă intrarea sa provine de la tastatură sau este introdusă în ea dintr-un alt proces?
De fapt, un proces știe – sau cel puțin poate afla, dacă alege să verifice – și își poate schimba comportamentul în consecință dacă autorul software-ului a decis să adauge această funcționalitate.
Putem observa foarte ușor această schimbare de comportament. Încercați aceste două comenzi:
ls
ls | pisică
Comanda ls
se comportă diferit dacă ieșirea sa ( stdout
) este transmisă în altă comandă. Este ls
care comută la o singură coloană de ieșire, nu este o conversie efectuată de cat
. Și ls
face același lucru dacă rezultatul său este redirecționat:
ls > capture.txt
captură pisică.txt
Se redirecționează stdout și stderr
Există un avantaj ca mesajele de eroare să fie livrate printr-un flux dedicat. Înseamnă că putem redirecționa ieșirea unei comenzi ( stdout
) către un fișier și totuși vedem orice mesaj de eroare ( stderr
) în fereastra terminalului. Puteți reacționa la erori dacă este necesar, pe măsură ce apar. De asemenea, oprește contaminarea mesajelor de eroare a fișierului în care a fost redirecționat stdout
.
Tastați următorul text într-un editor și salvați-l într-un fișier numit error.sh.
#!/bin/bash echo „Eu pe punctul de a încerca să accesez un fișier care nu există” cat bad-filename.txt
Faceți scriptul executabil cu această comandă:
chmod +x error.sh
Prima linie a scriptului trimite text în fereastra terminalului, prin fluxul stdout
. A doua linie încearcă să acceseze un fișier care nu există. Acest lucru va genera un mesaj de eroare care este livrat prin stderr
.
Rulați scriptul cu această comandă:
./error.sh
Putem vedea că ambele fluxuri de ieșire, stdout
și stderr
, au fost afișate în ferestrele terminalului.
Să încercăm să redirecționăm rezultatul către un fișier:
./error.sh > capture.txt
Mesajul de eroare care este livrat prin stderr
este încă trimis în fereastra terminalului. Putem verifica conținutul fișierului pentru a vedea dacă ieșirea stdout
a mers la fișier.
captură pisică.txt
Ieșirea de la stdin
a fost redirecționată către fișier așa cum era de așteptat.
Simbolul de redirecționare >
funcționează implicit cu stdout
. Puteți utiliza unul dintre descriptorii de fișier numeric pentru a indica ce flux de ieșire standard doriți să redirecționați.
Pentru a redirecționa în mod explicit stdout
, utilizați această instrucțiune de redirecționare:
1>
Pentru a redirecționa în mod explicit stderr
, utilizați această instrucțiune de redirecționare:
2>
Să încercăm din nou testul nostru și de data aceasta vom folosi 2>
:
./error.sh 2> capture.txt
Mesajul de eroare este redirecționat și mesajul stdout
echo
este trimis în fereastra terminalului:
Să vedem ce este în fișierul capture.txt.
captură pisică.txt
Mesajul stderr
este în capture.txt așa cum era de așteptat.
Redirecționarea Atât stdout, cât și stderr
Cu siguranță, dacă putem redirecționa fie stdout
, fie stderr
către un fișier independent unul de celălalt, ar trebui să le putem redirecționa pe amândouă în același timp, către două fișiere diferite?
Da putem. Această comandă va direcționa stdout
către un fișier numit capture.txt și stderr
către un fișier numit error.txt.
./error.sh 1> capture.txt 2> error.txt
Deoarece ambele fluxuri de ieșire - ieșire standard și eroare standard - sunt redirecționate către fișiere, nu există nicio ieșire vizibilă în fereastra terminalului. Ne întoarcem la promptul liniei de comandă ca și cum nimic nu s-ar fi întâmplat.
Să verificăm conținutul fiecărui fișier:
captură pisică.txt
eroare pisică.txt
Redirecționarea stdout și stderr către același fișier
Este frumos, avem fiecare dintre fluxurile de ieșire standard care merg la propriul fișier dedicat. Singura altă combinație pe care o putem face este să trimitem atât stdout
, cât și stderr
la același fișier.
Putem realiza acest lucru cu următoarea comandă:
./error.sh > capture.txt 2>&1
Să descompun asta.
- ./error.sh : Lansează fișierul script error.sh.
- > capture.txt : redirecționează fluxul
stdout
către fișierul capture.txt.>
este prescurtarea pentru1>
. - 2>&1 : Aceasta folosește instrucțiunea de redirecționare &>. Această instrucțiune vă permite să spuneți shell-ului să facă ca un flux să ajungă la aceeași destinație ca un alt flux. În acest caz, spunem „redirecționează fluxul 2,
stderr
, către aceeași destinație către care este redirecționat fluxul 1,stdout
”.
Nu există nicio ieșire vizibilă. Asta e încurajator.
Să verificăm fișierul capture.txt și să vedem ce este în el.
captură pisică.txt
Atât fluxurile stdout
, cât și stderr
au fost redirecționate către un singur fișier destinație.
Pentru ca rezultatul unui flux să fie redirecționat și aruncat în tăcere, direcționați ieșirea către /dev/null
.
Detectarea redirecționării într-un script
Am discutat despre modul în care o comandă poate detecta dacă vreunul dintre fluxuri este redirecționat și poate alege să-și modifice comportamentul în consecință. Putem realiza acest lucru în propriile noastre scenarii? Da putem. Și este o tehnică foarte ușor de înțeles și folosit.
Tastați următorul text într-un editor și salvați-l ca input.sh.
#!/bin/bash dacă [-t 0 ]; atunci echo stdin care vine de la tastatură altfel echo stdin provenind dintr-o conductă sau un fișier fi
Utilizați următoarea comandă pentru a o face executabilă:
chmod +x input.sh
Partea inteligentă este testul dintre paranteze pătrate. Opțiunea -t
(terminal) returnează true (0) dacă fișierul asociat cu descriptorul de fișier se termină în fereastra terminalului. Am folosit descriptorul de fișier 0 ca argument pentru test, care reprezintă stdin
.
Dacă stdin
este conectat la o fereastră de terminal, testul se va dovedi adevărat. Dacă stdin
este conectat la un fișier sau o conductă, testul va eșua.
Putem folosi orice fișier text convenabil pentru a genera intrare în script. Aici folosim unul numit dummy.txt.
./input.sh < dummy.txt
Ieșirea arată că scriptul recunoaște că intrarea nu provine de la o tastatură, ci de la un fișier. Dacă alegeți, puteți modifica comportamentul scriptului în consecință.
Asta a fost cu o redirecționare a fișierului, hai să încercăm cu o conductă.
manechin de pisică.txt | ./input.sh
Scriptul recunoaște că intrarea sa este introdusă în el. Sau mai precis, recunoaște încă o dată că fluxul stdin
nu este conectat la o fereastră de terminal.
Să rulăm scriptul fără conducte și nici redirecționări.
./input.sh
Fluxul stdin
este conectat la fereastra terminalului, iar scriptul raportează acest lucru în consecință.
Pentru a verifica același lucru cu fluxul de ieșire, avem nevoie de un nou script. Introduceți următoarele într-un editor și salvați-l ca output.sh.
#!/bin/bash dacă [-t1]; atunci echo stdout va ajunge la fereastra terminalului altfel echo stdout este redirecționat sau canalizat fi
Utilizați următoarea comandă pentru a o face executabilă:
chmod +x input.sh
Singura modificare semnificativă a acestui script este în testul dintre paranteze drepte. Folosim cifra 1 pentru a reprezenta descriptorul de fișier pentru stdout
.
Hai să-l încercăm. Vom canaliza ieșirea prin cat
.
./ieșire | pisică
Scriptul recunoaște că rezultatul său nu se duce direct la o fereastră de terminal.
De asemenea, putem testa scriptul redirecționând rezultatul către un fișier.
./output.sh > capture.txt
Nu există nicio ieșire în fereastra terminalului, suntem returnați în tăcere la promptul de comandă. Așa cum ne-am aștepta.
Putem privi în interiorul fișierului capture.txt pentru a vedea ce a fost capturat. Utilizați următoarea comandă pentru a face acest lucru.
captura de pisică.sh
Din nou, testul simplu din scriptul nostru detectează că fluxul stdout
nu este trimis direct la o fereastră de terminal.
Dacă rulăm scriptul fără conducte sau redirecționări, ar trebui să detecteze că stdout
este livrat direct în fereastra terminalului.
./ieșire.sh
Și exact asta vedem.
Fluxuri De Conștiință
Știind cum să știi dacă scripturile tale sunt conectate la fereastra terminalului, la o conductă sau sunt redirecționate, vă permite să le ajustați comportamentul în consecință.
Ieșirea de înregistrare și diagnosticare poate fi mai mult sau mai puțin detaliată, în funcție de faptul că merge pe ecran sau într-un fișier. Mesajele de eroare pot fi înregistrate într-un alt fișier decât rezultatul normal al programului.
Așa cum este de obicei cazul, mai multe cunoștințe aduce mai multe opțiuni.
Comenzi Linux | ||
Fișiere | tar · pv · cat · tac · chmod · grep · diff · sed · ar · om · pushd · popd · fsck · testdisk · seq · fd · pandoc · cd · $PATH · awk · join · jq · fold · uniq · journalctl · tail · stat · ls · fstab · echo · less · chgrp · chown · rev · look · strings · tip · redenumire · zip · dezarhivare · montare · demontare · instalare · fdisk · mkfs · rm · rmdir · rsync · df · gpg · vi · nano · mkdir · du · ln · patch · convert · rclone · shred · srm | |
Procese | alias · ecran · sus · frumos · renice · progres · strace · systemd · tmux · chsh · istoric · la · lot · gratuit · care · dmesg · chfn · usermod · ps · chroot · xargs · tty · pinky · lsof · vmstat · timeout · wall · da · kill · sleep · sudo · su · time · groupadd · usermod · grupuri · lshw · shutdown · repornire · stop · poweroff · passwd · lscpu · crontab · data · bg · fg | |
Rețele | netstat · ping · traceroute · ip · ss · whois · fail2ban · bmon · dig · finger · nmap · ftp · curl · wget · who · whoami · w · iptables · ssh-keygen · ufw |
LEGATE: Cele mai bune laptopuri Linux pentru dezvoltatori și entuziaști