Narzędzia użytkownika

Narzędzia witryny


materialy:podstawy-administracji:przekierowania-i-potoki

Przekierowania, strumienie, potoki oraz komendy wspomagające

Przekierowania i potoki

stdin stdout stderr

Każdą komendę Linux można traktować jak czarną skrzynkę z jednym wejściem (stdin - standard input) oraz dwoma wyjściami (stdout, stderr). Te kanały nazywane są standardowymi strumieniami.

  1. stdin – strumień wejścia – jest to miejsce, do którego przesyłane są wejściowe dane dla programu. Program otrzymuje tym kanałem informacje, aby je przetworzyć. Aby działanie edytora tekstu miało sens, należy na jego stdin przesłać dane w postaci pliku, którego użytkownik chce edytować. Na standardowe wejście przesyła się również komendy sterujące w programach wymagających interaktywnego wpisywania znaków lub poleceń. Przykładem może być nslookup, służący do odpytywania serwerów usługi DNS. Na jego standardowe wejście przesyłane są dane pochodzące z klawiatury komputera, które dalej analizowane są przez sam program. Za pomocą przekierowań można zmienić źródło danych przekazywanych na stdin - zamiast komend wpisywanych z klawiatury, można na wejście przesłać plik z treścią komend.
  2. stdout – strumień wyjścia – strumień ten opuszczają dane, które generuje program (są wynikiem jego działania). Dane pochodzące z tego strumienia najczęściej są wyświetlanie w terminalu, na ekranie monitora. Strumień stdout jest więc domyślnie skierowany na konsolę. Efekt można zobaczyć uruchamiając dowolną z podstawowych komend, np. date. Wynik (aktualna data i godzina) można zobaczyć na ekranie monitora. Można jednak przekierować strumień wyjścia w inne miejsce – do pliku lub do strumienia wejścia innego programu. W takich przypadkach data nie zostanie wyświetlona na ekranie, tylko będzie zapisana w pliku tekstowym lub przeanalizowana przez następny program jako dane wejściowe.
  3. stderr – strumień wyjścia błędów – podobnie jak w stdout strumień ten opuszczają dane, które generuje program. Charakterystyczną cechą danych pochodzących z tego strumienia jest to, iż informują one o błędach, jakie program napotkał przy wykonywaniu swojego zadania. Przykładowo, jeśli wykonamy komendę zmiany katalogu (cd) i jako parametr podamy nieistniejący katalog, to program wyśle przez strumień wyjścia błędów (stderr) informację w postaci tekstu, że taki katalog nie istnieje. Domyślnie strumień błędów jest skierowany na konsolę (tak jak stdout), czyli pośrednio również na ekran monitora. Dlatego też, użytkownik jest o wszystkich błędach informowany na bieżąco w trakcie wykonywania programu. Strumień wyjścia błędów, podobnie jak stdout można przekierować, aby nie przesyłał informacji o błędach na ekran, tyko zapisywał w pliku. Wprowadzono dwa odrębne strumienie, aby każdy z nich można przekierować w inne miejsce

Podsumowując domyślne przekierowania strumieni:

  • stdout jest standardowo skierowany na ekran/konsolę w której komenda jest wywoływana
  • stderr identycznie jak stdout
  • stdin standardowo otrzymuje dane z klawiatury użytkownika

Przekierowanie stdout

Przekierowanie stdout za pomocą symboli > oraz »

Są komendy, które mają na zadanie wyświetlić w przystępny sposób użytkownikowi informacje na konsoli. Jeśli prosimy system o podanie aktualnej konfiguracji sieciowej za pomocą komendy ifconfig, aktualnie wykorzystanej pamięci fizycznej za pomocą free czy też zawartości pliku tekstowego z konfiguracją montowanych partycji cat /etc/fstab na ekranie konsoli pojawiają się informacje o które prosiliśmy. Te informacje wyświetlane są na konsoli, gdyż stdout standardowo jest przekierowane na konsolę.

Aby informacje te były zapisane w pliku wystarczy na końcu komendy użyć symbolu przekierowania stdout do pliku > - nadpisanie pliku lub » - dopisanie do pliku. Jeśli plik docelowy nie istnieje zostaje utworzony:

free > wolna.pamiec.output
cat /etc/fstab > fstab.output #ekwiwalent cp /etc/fstab fstab.output

date >> konfiguracja-sieciowa.txt
ifconfig >> konfiguracja-sieciowa.txt

Proszę zauważyć, że gdyby w ostatniej komendzie użyto > zamiast » plik konfiguracja-sieciowa.txt zostałby nadpisany (usunięto by całą jego zawartość przed zapisaniem wyniku komendy ifconfig, data zapisana w pliku w poprzedniej komendzie zostałaby utracona).

Przekierowanie stderr

Przekierowanie stderr za pomocą symboli 2> oraz

Podobnie jak stdout, stderr można przekierować do pliku używając odpowiednich parametrów. Proszę zauważyć, że każdy z tych strumieni może być przekierowany do innego pliku. Użycie powoduje dopisanie informacji do pliku a nie jego nadpisanie jak w przypadku 2>.

find / -size +100M > duze-pliki-pow-100M.txt 2> bledy.txt
ls -la /tmp/* > zawartosc-tmp.txt 2>> bledy.txt

Przekierowanie strumieni na /dev/null

/dev/null jest specjalnym plikiem, bardzo przydatnym przy przekierowaniach, gdy użytkownik nie chce wyświetlać informacji na ekranie ani też zapisywać ich do jakiegokolwiek pliku. /dev/null reprezentuje „kosz bez dna”, „czarną dziurę” - cokolwiek będzie przekierowane do tego pliku nie zostanie nigdzie zapisane na trwałe (i nie zostanie wyświetlone).

find / -size +100M > duze-pliki-pow-100M.txt 2> /dev/null
ls -la /tmp/* > zawartosc-tmp.txt 2> /dev/null

Przekierowanie strumienia stdout i stderr do jednego pliku

Przekierowanie strumienia stdout i stderr do jednego pliku za pomocą symboli &> oraz

W przypadku potrzeby zapisania stdout i stderr do jednego pliku należy użyć operatorów &> (nadpisanie) lub (dopisanie). Standardowo stdout i stderr jest przekierowany na konsolę. Używając więc tego operatora otrzymamy w pliku odzwierciedlenie tego co zobaczylibyśmy na ekranie nie używając operatorów przekierowań:

find / -size +100M &> duze-pliki-pow-100M.txt

Zmiana źródła dla stdin

Zmiana/przekierowanie źródła dla stdin za pomocą symbolu <

Standardowo, jeśli program podczas działania potrzebuje dodatkowych informacji od użytkownika ten musi je podać wpisując je na klawiaturze. Są jednak sytuacje, najczęściej dla zautomatyzowania procesów, gdy dane wejściowe przygotowujemy w pliku a plik ten przekierowujemy na stdin, czyli strumień wejścia.

echo www.mimowszystko.pl > lista-domen
echo www.szkolenia-linux.pl >> lista-domen
echo www.lpi.com >> lista domen
#powyżej przygotowanie pliku z listą domen

nslookup < lista-domen
tr 'w' 'W' < lista-domen

Przedostatnia komenda będzie przyjmowała z pliku lista-domen „komendy”, które następnie będą interpretowane przez nslookup (klient DNS zwracający adresy IP dla wskazanych adresów domenowych). Komenda tr zamieni małą literę w na wielką a jako źródło zmian przyjmie plik lista-domen.

Potoki

Użycie potoków za pomocą symbolu |

Potoki - niezwykle przydatna funkcjonalność powłoki pozwala na przekierowanie strumienia wyjścia jednej komendy (stdout) na strumień wejścia (stdin) drugiej komendy. Potoki przydają się przy złożonym i nawet kilkukrotnym parsowaniu wyniku wyświetlanym na ekranie. Przykład:

Wzór:

komenda1 | komenda2 | komenda 3 

Przykłady:

ls -l /etc | grep host
sudo ifconfig | grep "inet addr" | cut -f2 -d: | cut -f1 -d" "

Powyższe komendy wyświetlą odpowiednio:

  1. te linie wyniku komendy ls -l /etc które zawierają słowo host
  2. adresy IP działających kart sieciowych - ifconfig wyświetla pełną konfigurację, linie z tekstem „inet addr” zawierają poszukiwane IP, kolejne filtrowania po polach (drugie pole odzielone dwukropkiem, następnie pierwsze pole oddzielone spacją) daje pożądany wynik

Podsumowanie

  • Przekierowania standard output - stdout:
    • na konsolę - domyślnie
    • > do pliku (nadpisanie)
    • » dopisanie do pliku
    • | do stdin innej komendy (potok)
  • Przekierowania standard input - stdin:
    • < ze wskazanego pliku
  • Przekierowania standard error - stderr:
    • na konsolę - domyślnie
    • 2> do pliku (nadpisanie)
    • dopisanie do pliku
  • Jednoczesne przekierowanie stdout oraz stderr:
    • &> do pliku (nadpisanie)
    • dopisanie do pliku
  • Przekierowanie tam gdzie drugi strumień:
    • 1>&2- przekierowanie strumienia stdout tam gdzie jest przekierwaony stderr;
    • 2>&1- przekierowanie strumienia stderr tam gdzie jest przekierwaony stdout;
  • | - potok, przekierowanie stdout na stdin innej komendy

Komendy wspomagające

tee - jednoczesne przekierowanie na stdout i do pliku

Zdarza się, że mamy potrzebę, aby wynik komendy był jednocześnie przekierowany na ekran oraz do pliku. Za pomocą standardowych przekierowań można zapisać informacje w jednym miejscu. Z pomocą przychodzi komenda tee która jest rodzajem „rozgałęziacza”. Wszystko co otrzyma na stdin wysyła jednocześnie na swój stdout i jednocześnie zapisuje (lub dopisuje - parametr -a) do pliku podanego jako argument.

Wzór użycia:

komenda | tee -a plik

Przykład:

ping www.mimowszystko.pl | tee -a czy-serwer-odpowiada.log

Aby zakończyć powyższą komendę należy użyć <CTRL+C>. Powyższa komenda spowoduje wyświetlanie na ekranie tych samych informacji co wyświetliłaby komenda ping www.mimowszystko.pl ale dodatkowo dopisze wynik do pliku czy-serwer-odpowiada.log.

xargs - lista argumentów podawana w stdin

Jedną z ciekawszych do zastosowania komend z użyciem potoków jest xargs dzięki któremu można wywoływać podobne komendy ale z różnymi argumentami, gdzie te argumenty dostarczane są ze strumienia wejściowego (wynik innej komendy lub zawartość pliku). Wyobraźmy sobie, że mamy potrzebę wykonania na ekranie takiego tekstu:

Odliczam 7
Odliczam 6
Odliczam 5
Odliczam 4
Odliczam 3
Odliczam 2
Odliczam 1
Odliczam 0

Można to zrealizować za pomocą serii komend (najlepiej zapisanych w skrypcie):

echo Odliczam 7
echo Odliczam 6
echo Odliczam 5
echo Odliczam 4
echo Odliczam 3
echo Odliczam 2
echo Odliczam 1
echo Odliczam 0

Jak widać w powyższym każda komenda rozpoczyna się tekstem echo Odliczam po czym następuję w każdym wywołaniu inna cyfra. Z pomocą xargs można wywołać komendę echo Odliczam a serię argumentów (7..0) pobrać ze stdin:

echo 7 6 5 4 3 2 1 0 | xargs -n1 echo Odliczam

Do wyświetlenia sekwencji liczb można również użyć komendy seq:

seq 7 -1 0 | xargs -n1 echo Odliczam

Jak widać w powyższych przykładach argumenty pobrane ze stdin są doklejane na koniec komendy podanej w xargs. Aby były one doklejane w określonym miejscu, należy zdefiniować nazwę zmiennej (parametr -Inazwa) i użyć jej w odpowiednim miejscu:

seq 7 -1 0 | xargs -n1 -ILICZBA echo Odliczam LICZBA sekund do uruchomienia

xargs przyjmuje argumenty ze stdin, które mogą nie być dostarczone w formie „zorganizowanej”, aby poprawnie rozdzielić argumenty należy użyć wspomagających opcji -L oraz -n które oznaczają ile linii strumienia wejściowego ma być użyte jako jeden argument lub ile wyrazów (oddzielonych białymi znakami) ma być użyte jako jeden argument. Dla zobrazowania tego zagadnienia sugerujemy wywołać komendy:

# przygotowanie pliku xfile
echo raz dwa trzy > xfile
echo cztery piec >> xfile
echo szesc >> xfile
echo siedem osiem dziewiec >> xfile
echo dzisiec >>xfile

cat xfile

cat xfile | xargs -L 1 echo argumenty:
cat xfile | xargs -L 2 echo argumenty:
cat xfile | xargs -n 1 echo argumenty:
cat xfile | xargs -n 2 echo argumenty:

xargs w połączeniu z find

Komenda xargs często wykorzystywana jest do wykonywania tych samych operacji (komend) na wielu plikach, które znaleziono z pomocą komendy find. Ważne w tym połączeniu jest użycie opcji -print0 po stronie find oraz -0 po stronie xargs, aby każdy znaleziony obiekt w find był uznawany za jeden argument dla xargs.

Wzór:

find GDZIE-SZUKAC KRYTERIA -print0 | xargs -0 -IFILE komenda FILE

Przykłady:

Skopiuj każdy plik o rozszerzeniu .conf z katalogu /etc do katalogu konfiguracje

find /etc/ -type f -iname '*.conf' -print0 | xargs -0 -IFILE cp FILE ./konfiguracje/ 

Wykonaj kopię zapasową każdego pliku z katalogu domowego

find ~ -type f -print0 | xargs -0 -IFILE cp FILE FILE.backup-2014-09-21

Zmniejsz wszystkie znalezione zdjęcia .jpg ze swojego katalogu domowego do rozmiaru 800×600 i zapisz je w osobnym katalogu:

find ~ -type f -name '*.jpg' -print0 | xargs -0 -IPLIK convert -resize 800x600 PLIK zmniejszone/PLIK

Uruchamianie komend inline

Czasami chcielibyśmy, aby wynik jednej komendy był wykorzystany jako parametr innej komendy. Jest to możliwe dzięki „backquotes” (grawis):

Wzór (wywołanie komenda2, której wynik będzie argumentem dla komenda1):

komenda1 `komenda2`

Przykłady:

echo Dzisiaj jest `date`
echo `date +%F_%T`: wpis w logu >> moj.log

Identyczną funkcjonalność do `komenda` ma zapis $(komenda):

echo Dzisiaj jest $(date)
echo $(date +%F_%T): wpis w logu >> moj.log

Masz potrzebę, aby powyższa strona była rozbudowana? - Napisz do nas!.

materialy/podstawy-administracji/przekierowania-i-potoki.txt · ostatnio zmienione: 2015/02/16 16:57 przez mzalewski

(C) 2017 ITMZ Mariusz Zalewski