Czym są stdin, stdout i stderr w systemie Linux?
Opublikowany: 2022-01-29 stdin
, stdout
i stderr
to trzy strumienie danych tworzone po uruchomieniu polecenia systemu Linux. Możesz ich użyć, aby stwierdzić, czy twoje skrypty są przesyłane lub przekierowywane. Pokażemy Ci jak.
Strumienie łączą dwa punkty
Gdy tylko zaczniesz poznawać systemy operacyjne Linux i uniksopodobne, natkniesz się na terminy stdin
, stdout
i stederr
. Są to trzy standardowe strumienie, które są ustanawiane podczas wykonywania polecenia systemu Linux. W informatyce strumień to coś, co może przesyłać dane. W przypadku tych strumieni danymi tymi jest tekst.
Strumienie danych, podobnie jak strumienie wody, mają dwa końce. Mają źródło i odpływ. Niezależnie od tego, którego polecenia Linuksa używasz, zapewnia jeden koniec każdego strumienia. Drugi koniec jest określany przez powłokę, która uruchomiła polecenie. Ten koniec zostanie podłączony do okna terminala, podłączony do potoku lub przekierowany do pliku lub innego polecenia, zgodnie z wierszem poleceń, który uruchomił polecenie.
Standardowe strumienie Linuksa
W Linuksie standardowym strumieniem wejściowym jest stdin
. To akceptuje tekst jako dane wejściowe. Wyjście tekstowe z polecenia do powłoki jest dostarczane przez strumień stdout
(standardowe wyjście). Komunikaty o błędach z polecenia są wysyłane przez strumień stderr
(standardowy błąd).
Widać więc, że istnieją dwa strumienie wyjściowe, stdout
i stderr
oraz jeden strumień wejściowy, stdin
. Ponieważ komunikaty o błędach i normalne wyjście mają swój własny kanał do przenoszenia ich do okna terminala, mogą być obsługiwane niezależnie od siebie.
Strumienie są obsługiwane jak pliki
Strumienie w Linuksie — jak prawie wszystko inne — są traktowane tak, jakby były plikami. Możesz czytać tekst z pliku i możesz zapisywać tekst do pliku. Obie te akcje obejmują strumień danych. Tak więc koncepcja obsługi strumienia danych jako pliku nie jest zbyt naciągnięta.
Każdemu plikowi skojarzonemu z procesem przypisywany jest unikalny numer, który go identyfikuje. Jest to znane jako deskryptor pliku. Za każdym razem, gdy wymagane jest wykonanie akcji na pliku, deskryptor pliku jest używany do identyfikacji pliku.
Te wartości są zawsze używane dla stdin
, stdout,
i stderr
:
- 0 : standardowe
- 1 : stdout
- 2 : stderr
Reagowanie na potoki i przekierowania
Aby ułatwić komuś wprowadzenie do tematu, powszechną techniką jest nauczenie uproszczonej wersji tematu. Na przykład w gramatyce mówi się nam, że regułą jest „I przed E, z wyjątkiem po C”. Ale w rzeczywistości jest więcej wyjątków od tej reguły niż przypadków, które jej przestrzegają.
W podobnym duchu, kiedy mówimy o stdin
, stdout
i stderr
, wygodnie jest wywnioskować przyjęty aksjomat, że proces ani nie wie, ani nie dba o to, gdzie kończą się jego trzy standardowe strumienie. Czy proces powinien dbać o to, czy jego dane wyjściowe trafiają do terminala, czy też są przekierowywane do pliku? Czy może w ogóle stwierdzić, czy jego dane wejściowe pochodzą z klawiatury, czy są do niego przesyłane z innego procesu?
W rzeczywistości proces wie – lub przynajmniej może się dowiedzieć, jeśli zdecyduje się to sprawdzić – i może odpowiednio zmienić swoje zachowanie, jeśli autor oprogramowania zdecyduje się dodać tę funkcjonalność.
Bardzo łatwo widzimy tę zmianę w zachowaniu. Wypróbuj te dwa polecenia:
ls
ls | Kot
Polecenie ls
zachowuje się inaczej, jeśli jego dane wyjściowe ( stdout
) są przesyłane do innego polecenia. To ls
przełącza na wyjście jednokolumnowe, nie jest to konwersja wykonywana przez cat
. I ls
robi to samo, jeśli jego wyjście jest przekierowywane:
ls > przechwytywanie.txt
cat capture.txt
Przekierowywanie stdout i stderr
Zaletą jest posiadanie komunikatów o błędach dostarczanych przez dedykowany strumień. Oznacza to, że możemy przekierować wyjście polecenia ( stdout
) do pliku i nadal widzieć wszelkie komunikaty o błędach ( stderr
) w oknie terminala. W razie potrzeby możesz reagować na pojawiające się błędy. Zatrzymuje również komunikaty o błędach przed zanieczyszczeniem pliku, do którego zostało przekierowane standardowe stdout
.
Wpisz następujący tekst do edytora i zapisz go w pliku o nazwie error.sh.
#!/kosz/bash echo "O próbie uzyskania dostępu do pliku, który nie istnieje" kot zła nazwa-pliku.txt
Spraw, aby skrypt był wykonywalny za pomocą tego polecenia:
chmod +x błąd.sh
Pierwsza linia skryptu wyświetla tekst w oknie terminala poprzez strumień stdout
. Druga linia próbuje uzyskać dostęp do pliku, który nie istnieje. Spowoduje to wygenerowanie komunikatu o błędzie, który zostanie dostarczony przez stderr
.
Uruchom skrypt za pomocą tego polecenia:
./błąd.sh
Widzimy, że oba strumienie wyjściowe, stdout
i stderr
, zostały wyświetlone w oknach terminala.
Spróbujmy przekierować wyjście do pliku:
./error.sh > capture.txt
Komunikat o błędzie dostarczany przez stderr
jest nadal wysyłany do okna terminala. Możemy sprawdzić zawartość pliku, aby zobaczyć, czy stdout
trafiło do pliku.
cat capture.txt
Dane wyjściowe z stdin
zostały przekierowane do pliku zgodnie z oczekiwaniami.
Symbol przekierowania >
domyślnie działa ze stdout
. Możesz użyć jednego z numerycznych deskryptorów plików, aby wskazać, który standardowy strumień wyjściowy chcesz przekierować.
Aby jawnie przekierować stdout
, użyj tej instrukcji przekierowania:
1>
Aby jawnie przekierować stderr
, użyj tej instrukcji przekierowania:
2>
Spróbujmy jeszcze raz wykonać nasz test, tym razem użyjemy 2>
:
./error.sh 2> przechwytywanie.txt
Komunikat o błędzie jest przekierowywany, a do okna terminala wysyłany jest komunikat stdout
echo
:
Zobaczmy, co znajduje się w pliku capture.txt.
cat capture.txt
Zgodnie z oczekiwaniami komunikat stderr
znajduje się w pliku capture.txt.
Przekierowanie zarówno stdout, jak i stderr
Z pewnością, jeśli możemy przekierować stdout
lub stderr
do pliku niezależnie od siebie, powinniśmy być w stanie przekierować je jednocześnie do dwóch różnych plików?
Tak możemy. To polecenie skieruje standardowe stdout
do pliku o nazwie capture.txt, a stderr
do pliku o nazwie error.txt.
./error.sh 1> przechwytywanie.txt 2> błąd.txt
Ponieważ oba strumienie danych wyjściowych — standardowe wyjście i błąd standardowy — są przekierowywane do plików, w oknie terminala nie ma widocznych danych wyjściowych. Wracamy do wiersza poleceń, jakby nic się nie wydarzyło.
Sprawdźmy zawartość każdego pliku:
cat capture.txt
błąd kota.txt
Przekierowywanie stdout i stderr do tego samego pliku
To fajne, każdy ze standardowych strumieni wyjściowych trafia do własnego dedykowanego pliku. Jedyną inną kombinacją, jaką możemy zrobić, jest wysłanie stdout
i stderr
do tego samego pliku.
Możemy to osiągnąć za pomocą następującego polecenia:
./error.sh > capture.txt 2>&1
Rozłóżmy to.
- ./error.sh : Uruchamia plik skryptu error.sh.
- > capture.txt : Przekierowuje strumień
stdout
do pliku capture.txt.>
to skrót od1>
. - 2>&1 : Używa instrukcji przekierowania &>. Ta instrukcja pozwala powiedzieć powłoce, aby jeden strumień dotarł do tego samego miejsca docelowego, co inny strumień. W tym przypadku mówimy „przekieruj strumień 2,
stderr
, do tego samego miejsca docelowego, do którego jest przekierowywany strumień 1,stdout
”.
Brak widocznych danych wyjściowych. To zachęcające.
Sprawdźmy plik capture.txt i zobaczmy, co w nim jest.
cat capture.txt
Strumienie stdout
i stderr
zostały przekierowane do jednego pliku docelowego.
Aby dane wyjściowe strumienia zostały przekierowane i po cichu odrzucone, skieruj dane wyjściowe do /dev/null
.
Wykrywanie przekierowania w skrypcie
Omówiliśmy, w jaki sposób polecenie może wykryć, czy którykolwiek ze strumieni jest przekierowywany, i może odpowiednio zmienić swoje zachowanie. Czy możemy to osiągnąć w naszych własnych skryptach? Tak możemy. I jest to bardzo łatwa do zrozumienia i zastosowania technika.
Wpisz następujący tekst do edytora i zapisz go jako input.sh.
#!/kosz/bash jeśli [ -t 0 ]; następnie echo stdin pochodzące z klawiatury w przeciwnym razie echo stdin pochodzące z potoku lub pliku fi
Użyj następującego polecenia, aby uczynić go wykonywalnym:
chmod +x input.sh
Sprytną częścią jest test w nawiasach kwadratowych. Opcja -t
(terminal) zwraca prawdę (0), jeśli plik skojarzony z deskryptorem pliku kończy się w oknie terminala. Użyliśmy deskryptora pliku 0 jako argumentu do testu, który reprezentuje stdin
.
Jeśli stdin
jest podłączony do okna terminala, test okaże się prawdziwy. Jeśli stdin
jest podłączony do pliku lub potoku, test nie powiedzie się.
Do wygenerowania danych wejściowych do skryptu możemy użyć dowolnego wygodnego pliku tekstowego. Tutaj używamy jednego o nazwie dummy.txt.
./input.sh < dummy.txt
Dane wyjściowe pokazują, że skrypt rozpoznaje, że dane wejściowe nie pochodzą z klawiatury, ale pochodzą z pliku. Jeśli tak zdecydujesz, możesz odpowiednio zmienić zachowanie skryptu.
To było z przekierowaniem pliku, spróbujmy z potoku.
kot manekin.txt | ./wejście.sh
Skrypt rozpoznaje, że jego dane wejściowe są do niego przesyłane. A dokładniej, ponownie rozpoznaje, że strumień stdin
nie jest połączony z oknem terminala.
Uruchommy skrypt bez potoków i przekierowań.
./wejście.sh
Strumień stdin
jest podłączony do okna terminala, a skrypt odpowiednio to zgłasza.
Aby sprawdzić to samo ze strumieniem wyjściowym, potrzebujemy nowego skryptu. Wpisz następujące polecenie do edytora i zapisz jako output.sh.
#!/kosz/bash jeśli [ -t 1 ]; następnie standardowe wyjście echo przechodzi do okna terminala w przeciwnym razie standardowe wyjście echo jest przekierowywane lub przesyłane potokiem fi
Użyj następującego polecenia, aby uczynić go wykonywalnym:
chmod +x input.sh
Jedyna istotna zmiana w tym skrypcie dotyczy testu w nawiasach kwadratowych. Używamy cyfry 1 do reprezentowania deskryptora pliku dla stdout
.
Wypróbujmy to. Wyjście prześlemy przez cat
.
./wyjście | Kot
Skrypt rozpoznaje, że jego dane wyjściowe nie trafiają bezpośrednio do okna terminala.
Możemy również przetestować skrypt, przekierowując wyjście do pliku.
./output.sh > przechwytywanie.txt
Nie ma wyjścia do okna terminala, po cichu wracamy do wiersza poleceń. Jak się spodziewaliśmy.
Możemy zajrzeć do pliku capture.txt, aby zobaczyć, co zostało przechwycone. Użyj następującego polecenia, aby to zrobić.
łapanie kota.sh
Ponownie prosty test w naszym skrypcie wykrywa, że strumień stdout
nie jest wysyłany bezpośrednio do okna terminala.
Jeśli uruchomimy skrypt bez potoków lub przekierowań, powinien wykryć, że stdout
jest dostarczane bezpośrednio do okna terminala.
./wyjście.sh
I dokładnie to widzimy.
Strumienie Świadomości
Wiedząc, jak stwierdzić, czy twoje skrypty są połączone z oknem terminala, potoku, czy też są przekierowywane, możesz odpowiednio dostosować ich zachowanie.
Dane wyjściowe logowania i diagnostyki mogą być mniej lub bardziej szczegółowe, w zależności od tego, czy trafiają na ekran, czy do pliku. Komunikaty o błędach mogą być rejestrowane w innym pliku niż normalne wyjście programu.
Jak to zwykle bywa, więcej wiedzy daje więcej możliwości.
Polecenia Linuksa | ||
Pliki | tar · pv · kot · tac · chmod · grep · diff · sed · ar · man · pushd · popd · fsck · dysk testowy · seq · fd · pandoc · cd · $PATH · awk · join · jq · fold · uniq · journalctl · ogon · stat · ls · fstab · echo · mniej · chgrp · chown · rev · wygląd · stringi · typ · zmiana nazwy · zip · rozpakuj · montuj · umount · zainstaluj · fdisk · mkfs · rm · rmdir · rsync · df · gpg · vi · nano · mkdir · du · ln · patch · konwertuj · rclone · shred · srm | |
Procesy | alias · ekran · top · ładne · renice · postęp · strace · systemd · tmux · chsh · historia · w · wsad · free · co · dmesg · chfn · usermod · ps · chroot · xargs · tty · pinky · lsof · vmstat · timeout · ściana · tak · kill · sen · sudo · su · czas · groupadd · usermod · grupy · lshw · zamknij · restart · halt · poweroff · passwd · lscpu · crontab · data · bg · fg | |
Sieć | netstat · ping · traceroute · ip · ss · whois · fail2ban · bmon · dig · finger · nmap · ftp · curl · wget · who · whoami · w · iptables · ssh-keygen · ufw |
POWIĄZANE: Najlepsze laptopy z systemem Linux dla programistów i entuzjastów