Jaki jest dobry przykład łączenia potoków razem?

33

Gdybyś pomagał komuś nauczyć się pojęcia potoków w wierszu poleceń, jakiego przykładu byś użył? Przykład, który się pojawił, był następujący:

cat whatever.txt | less

Wydaje mi się, że nie jest to najlepszy przykład, ponieważ jest tylko jeden krok. Jakie jest dobre, ale fundamentalne zastosowanie |?

Idealnie w przykładzie, który przedstawię, będą używać programów, które same mają wyjścia, które mogą być uruchamiane niezależnie, a następnie wyświetlane razem.

Mateusz
źródło
3
Twój przykład naprawdę nie jest tak dobry - jest to w zasadzie nominacja do nagrody za bezużyteczne użycie kota.
maxschlepzig
@maxschlepzig Nie to, że się mylimy, ale też nie jesteś zbyt pomocny; nie potrzebujesz cattego, ponieważ less whatever.txtdziała dobrze.
Bora M. Alper

Odpowiedzi:

34

Przedstawię ci nieco skomplikowany przykład oparty na prawdziwym scenariuszu.

Problem

Powiedzmy, że polecenie conkyprzestało odpowiadać na moim pulpicie i chcę go zabić ręcznie. Znam trochę Uniksa, więc wiem, że muszę wykonać polecenie kill <PID>. W celu odzyskania PID, można użyć pslub topczy cokolwiek narzędzie mój rozkład Unix mi dał. Ale jak mogę to zrobić za pomocą jednego polecenia?

Odpowiedź

$ ps aux | grep conky | grep -v grep | awk '{print $2}' | xargs kill

ZASTRZEŻENIE: To polecenie działa tylko w niektórych przypadkach. Nie kopiuj / wklej go w swoim terminalu i zacznij go używać, może to nieświadomie zabić procesy. Naucz się raczej, jak go zbudować .

Jak to działa

1- ps aux

To polecenie wyświetli listę uruchomionych procesów i informacje o nich. Ciekawą informacją jest to, że wyświetli PID każdego procesu w drugiej kolumnie. Oto fragment danych wyjściowych polecenia na moim pudełku:

$ ps aux
 rahmu     1925  0.0  0.1 129328  6112 ?        S    11:55   0:06 tint2
 rahmu     1931  0.0  0.3 154992 12108 ?        S    11:55   0:00 volumeicon
 rahmu     1933  0.1  0.2 134716  9460 ?        S    11:55   0:24 parcellite
 rahmu     1940  0.0  0.0  30416  3008 ?        S    11:55   0:10 xcompmgr -cC -t-5 -l-5 -r4.2 -o.55 -D6
 rahmu     1941  0.0  0.2 160336  8928 ?        Ss   11:55   0:00 xfce4-power-manager
 rahmu     1943  0.0  0.0  32792  1964 ?        S    11:55   0:00 /usr/lib/xfconf/xfconfd
 rahmu     1945  0.0  0.0  17584  1292 ?        S    11:55   0:00 /usr/lib/gamin/gam_server
 rahmu     1946  0.0  0.5 203016 19552 ?        S    11:55   0:00 python /usr/bin/system-config-printer-applet
 rahmu     1947  0.0  0.3 171840 12872 ?        S    11:55   0:00 nm-applet --sm-disable
 rahmu     1948  0.2  0.0 276000  3564 ?        Sl   11:55   0:38 conky -q

2- grep conky

Interesuje mnie tylko jeden proces, więc grepznajduję wpis odpowiadający mojemu programowi conky.

$ ps aux | grep conky
 rahmu     1948  0.2  0.0 276000  3564 ?        Sl   11:55   0:39 conky -q
 rahmu     3233  0.0  0.0   7592   840 pts/1    S+   16:55   0:00 grep conky

3- grep -v grep

Jak widać w kroku 2, polecenie pswyświetla grep conkyproces na liście (w końcu jest uruchomionym procesem). Aby go przefiltrować, mogę uruchomić grep -v grep. Ta opcja -vmówi grepo dopasowaniu wszystkich linii oprócz linii zawierających wzór.

$ ps aux | grep conky | grep -v grep
 rahmu     1948  0.2  0.0 276000  3564 ?        Sl   11:55   0:39 conky -q

NB: Chciałbym znać sposób na wykonanie czynności 2 i 3 w jednym greppołączeniu.

4- awk '{print $2}'

Teraz, gdy wyizolowałem proces docelowy. Chcę odzyskać jego PID. Innymi słowy, chcę odzyskać drugie słowo wyniku. Na szczęście dla mnie większość (wszystkich?) Współczesnych jednorożców dostarczy jakąś wersję awkjęzyka skryptowego, który robi cuda z danymi tabelarycznymi. Nasze zadanie staje się tak proste jak print $2.

$ ps aux | grep conky | grep -v grep | awk '{print $2}'
 1948

5- xargs kill

Mam PID. Wszystko czego potrzebuję to przekazać kill. Aby to zrobić, użyję xargs.

xargs killodczyta dane wejściowe (w naszym przypadku z potoku), utworzy polecenie składające się z kill <items>( <items>są czymkolwiek odczytane z danych wejściowych), a następnie wykona utworzone polecenie. W naszym przypadku zostanie wykonane kill 1948. Misja zakończona sukcesem.

Ostatnie słowa

Zauważ, że w zależności od używanej wersji Uniksa niektóre programy mogą zachowywać się nieco inaczej (na przykład psmogą wyświetlać PID w kolumnie $ 3). Jeśli coś wydaje się niewłaściwe lub inne, przeczytaj dokumentację dostawcy (lub lepiej manstrony). Uważaj również, ponieważ długie rury mogą być niebezpieczne. Nie przyjmuj żadnych założeń, szczególnie podczas używania poleceń takich jak killlub rm. Na przykład, jeśli istnieje inny użytkownik o nazwie „conky” (lub „Aconkyous”), moje polecenie może zabić wszystkie jego uruchomione procesy!

Mówię ostrożnie, szczególnie w przypadku długich rur. Zawsze lepiej jest budować go interaktywnie, tak jak my tutaj, niż zakładać i później żałować.

rahmu
źródło
NB: Chciałbym wiedzieć, jak wykonać kroki 2 i 3 w jednym wywołaniu grep. -> grep „conky -q” :)
Wolfy,
3
W rzeczywistości jest to zły przykład, jak można to po prostu zrobićkill $(pgrep conky)
Patrick
5
Wiem, że jest późno, ale można to jeszcze bardziej uprościćpkill conky
strugee
2
„” „Uwaga: Chciałbym znać sposób wykonywania kroków 2 i 3 w jednym wywołaniu grep.” „” Zamiast „aux” użyj „-o pid, comm” - jest to również bardziej przenośne, ponieważ jest POSIX -zgodny. W ten sposób proces grep będzie po prostu pojawiał się jako „grep” zamiast „grep conky”, więc nie będzie pasował do siebie.
Random832,
2
NB: Chciałbym znać sposób na wykonanie czynności 2 i 3 w jednym greppołączeniu. grep [c]onkyjest tym, czego szukasz.
AlexT
15

Moim ulubionym jest ten:

youtube-dl $1 -q -o - | ffmpeg -i - $2

pobiera wideo z podanego adresu URL YouTube i przekazuje $1go jako plik podany przez $2. Zwróć uwagę, jak plik jest po cichu -qprzesyłany do STDOUT -o -, przesyłany potokowo do ffmpeg i wykorzystywany przez niego jako dane wejściowe -i -.

Szczególnie dla początkujących Linuksa może to być praktyczny przykład, dlaczego wiersz poleceń może być użyteczny i ułatwiać korzystanie z narzędzi GUI. Nie jestem pewien, ile czasu zajęłoby pobranie filmu z YouTube i przekonwertowanie jego dźwięku na format mp3. Powyższa linia może to zrobić w ciągu kilku sekund.

Baarn
źródło
3
youtube-dl ma opcję zapisywania tylko dźwięku. My zwykle polecenie to jest, gdzie adresy przyjść na stdin: youtube-dl --extract-audio --audio-format mp3 -a -. Wciąż fajny przykład, ale są na to łatwiejsze sposoby. (Nazywa się ffmpeg wewnętrznie.)
Brigand
3
@FakeRainBrigand: Haha, dobrze wiedzieć! Ale mam alternatywę, która nie powinna być wbudowana: youtube-dl $1 -q -o - | mplayer -bezpośrednio odtwarza wideo w MPlayerze. Używam tego polecenia z laptopa, aby powiedzieć mojemu serwerowi (który jest podłączony do telewizora), aby odtwarzał filmy. Muszę dołączyć, -display :0.0 -geometry 400x300+1200+200aby okno mplayera pojawiło się na odpowiednim ekranie.
Baarn
9

Ogólne zastosowanie (czytaj: sposób, w jaki najczęściej go używam) polega na tym, że z jakiegoś powodu muszę uruchamiać niektóre dane za pomocą kilku narzędzi, aby wykonywać różne zadania przetwarzania.

Więc powiedziałbym stosowanie rur jest jako klej do montażu kilka cegiełek (różne narzędzia UNIX) razem. Jak powiedział Ulrich, i jest to powszechna zwrotka.sortuniq

W zależności od odbiorców, jeśli chcesz podkreślić wykorzystanie rur, możesz na przykład zacząć od: „hej, ten program zawiera linki do kilku interesujących plików PDF z artykułami i notatkami z wykładów, ale niektóre z nich są powtarzane. jakoś to zautomatyzować? ”

Następnie możesz pokazać, w jaki sposób lynx --dump --listonlypobiera listę linków, jak grepmożna filtrować linki kończące się na .pdf, jak colrmlub sedmożna pozbyć się liczb lynxzapisywanych do każdego adresu URL, jak sorti jak uniqmożna pozbyć się duplikatów, a na koniec, jak wget -i -można użyć do odzyskania pliki ( --waitoczywiście łagodne dla serwera).

Obawiam się, że to złożony przykład. Z drugiej strony, może pomóc pokazać moc potoków, gdy po prostu potokujesz i masz powłokę uruchamiającą wszystko naraz.

njsg
źródło
2
Możesz używać także sort -uw jądrach GNU .
Teresa e Junior
2

Nie wiem dokładnie, co jest dobre, ale przesyłanie strumieniowe grepmusi być jednym z najczęstszych zastosowań, prawdopodobnie po nim wc -l. (Tak, grepma mało znany -cprzełącznik.)

Inną powszechną zwrotką jest | sort | uniqchoćby dlatego, że uniqwymaga sortowania danych wejściowych.

Ulrich Schwarz
źródło
Większość ludzi woli, ... | sort -ujeśli są dostępne!
2

Nie dlatego, że potrzebujesz go w tym przykładzie, ale:

$ ps aux | grep -v grep | grep conky

... odwrócenie kolejności greps zachowuje kolorowanie, ale jest DUŻO mniej wydajne. przypuszczalnie na dużych listach kolor nie miałby znaczenia.

ta strona sugeruje również:

https://stackoverflow.com/questions/9375711/more-elegant-ps-aux-grep-v-grep

> Johnsyweb odpowiedział 21 lutego 2012 o 10:31
> Zwykła sztuczka jest następująca:
> ps aux | grep „[t] erminal”
> To dopasuje wiersze zawierające terminal, którego grep '[t] erminal' nie!
> Działa również na wielu odmianach Uniksa.

... ale to nie zadziała, jeśli szukasz pojedynczej litery (np. proces „X”).

anonimowe
źródło
2

W końcu mogę podzielić się tym bałaganem oneliner, który zrobiłem około półtora roku temu ...

while read in; do host "$in"; done < sites.txt | grep -iv "GOOGLE" | grep -E '1\.2\.3\.4|5\.6\.7\.8' | sed -e 's/has\ address\ 216.70.91.72//' | sed -e 's/has\ address\ 94.23.33.92//' | while read sites; do curl -sL -w "%{http_code} %{url_effective}\\n" "$sites" -o /dev/null; done | grep -ivE '4.*|5.*' | sed -e 's/200//' | sed -e 's/HTTP/http/'

To...

  1. Czyta strony site.txt
  2. Uruchamia „host” na każdym z nich (z perspektywy czasu, kopanie + kręcenie ułatwiłoby to tonę)
  3. Usuwa wiersze zawierające „GOOGLE” - są to rekordy MX
  4. Pobiera linie, które mają jeden z dwóch adresów IP
  5. Pobiera kod stanu HTTP z każdej witryny na liście
  6. Usuwa witryny zwracające 4xx lub 5xx
  7. Usuwa „200” z witryn, które to zwróciły
  8. Zamienia „HTTP” na „http” - czysto estetyczny, bez prawdziwego powodu.

Założę się, że można to zrobić o wiele lepiej za pomocą jednego skryptu Python.

garbarz
źródło
Uh ... Nie jestem pewien, czy byłby to najczystszy i najłatwiejszy sposób na wyjaśnienie nowicjuszowi rurociągów;)
Erathiel,
2
Moje pytanie brzmi: jaki jest jego cel?
ADTC
Miałem plik pełen domen i musiałem sprawdzić, czy znajdują się one na jednym z moich dwóch serwerów (które „odziedziczyłem”, niestety). Odczytuje plik, wykonuje „host” i czyści dane wyjściowe, a następnie wykonuje tylko żądanie sprawdzenia, czy zwraca błąd 4xx czy 5xx. Jeśli tak, to odrzuci domenę; jeśli nie, wypisuje je i umieszczam w innym pliku.
garbarz
1

To pierwsza rzecz, która przyszła mi do głowy ...

mysqldumpto aplikacja konsolowa, która wysyła dane, schemat oraz opcjonalnie procedury i funkcje do standardowego wyjścia. Zwykle zostaje przekierowany do pliku w celu utworzenia kopii zapasowej.

mysqldump <options> > mydb.dump

To dałoby ci nieskompresowany skrypt SQL. Aby zaoszczędzić miejsce, możesz skompresować go za pomocą bzip2.

bzip2 mydb.dump

Alternatywnie możesz zrobić jedno i drugie w jednym kroku:

mysqldump <options> | bzip2 > mydb.dump.bz2

W powyższym przykładzie stdout z mysqldumpjest przesyłany potokowo do bzip2, który następnie przekierowuje dane wyjściowe do pliku.

Sean C.
źródło
1
Dodaj odwrotne działanie zbyt: bzcat mydb.dump.bz2 | mysql <options>.
manatwork
1

Oto przykład, którego używam w mojej pracy z wieloma potokami w jednym poleceniu. Używa gawk do przeszukiwania ogólnego dziennika zapytań MySQL ($ OFILE) i znajdowania wszelkich odmówionych logowań. Następnie sortuje tę listę według nazwy, potokuje tę listę do uniq, która liczy wystąpienia, a następnie potokuje sortowanie po raz ostatni, aby posortować zliczoną listę numerycznie ...

gawk '{ for (x=1;x<=NF;x++) if ( $x~"Access" && $(x+4)~".*@.*") print $(x+4)}' $OFILE | sort | uniq -c | sort -n
Rob Berkes
źródło
1

Rury najlepiej działają z filtrami i tłumaczami

find /usr/bin/ |                #produce 
sed 's:.*/::'  |                #translate: strip directory part
grep -i '^z'   |                #filter   : select items starting with z
xargs -d '\n' aFinalConsumer    #consume  

W ten sposób dane mogą przepływać z jednego programu do drugiego, co oznacza, że ​​w żadnym momencie wszystkie dane nie muszą znajdować się w pamięci jednocześnie.

PSkocik
źródło
0

cat filename | less jest okropnym zastosowaniem orurowania, ponieważ możesz to po prostu zrobić less filename

Oto przykład pipsów, których używam na co dzień (ale może też być złym przykładem): ls -la | more -c

Odpowiedzi Scott Hoffman i NJSG są lepszymi przykładami.

DwB
źródło
0

wykonaj ten w dowolnym katalogu, w którym chcesz posortować analizę rozmiaru folderu (następnie przewiń w dół klawiszem END):

du -m| sort -n| less

Sortiert nach Ordnergrösse

Xubunuser
źródło
0

Oto przykład, którego użyłem do ustawienia zmiennej DISPLAY, gdy xauth nie było opcją ...

export DISPLAY=\`who am i |awk '{print $NF}' | sed 's/[()]//g'`":0.0"

Pierwsze polecenie pobiera potrzebne dane, tj. Nazwę hosta lub adres IP. Drugie polecenie pobiera tylko te dane (ostatnie pole). Wreszcie ostatnie polecenie usuwa nawiasy z danych.

Scott Hoffman
źródło
0

Pipowanie poleceń, którego możesz używać wszędzie tam, gdzie uważasz, że dane wyjściowe pierwszego polecenia mogą być podawane jako dane wejściowe do następnego.

Przykłady

  1. Za pomocą plików tekstowych możesz przekazać plik tekstowy do grep, aby znaleźć określone wiersze tekstu. Następnie możesz przekazać dane wyjściowe do sed lub awk, aby zmodyfikować lub wydrukować określoną część linii.

przykład kota txt | grep {some_line} | awk {some_command}

  1. Pracując z procesem, możesz używać potoków do wysyłania poleceń do zabicia procesu.

Jest to po prostu koncepcja, że ​​jeśli czujesz, że uruchomione polecenie może być wprowadzone przez inne polecenie, możesz je potokować.

Piyush Jain
źródło