Was ist ein gutes Beispiel für das Zusammenführen von Befehlen?

33

Wenn Sie jemandem helfen würden, das Konzept der Pipes in der Befehlszeile zu erlernen, welches Beispiel würden Sie verwenden? Das tatsächlich aufgetauchte Beispiel war wie folgt:

cat whatever.txt | less

Ich denke, das ist nicht das beste Beispiel, weil es nur einen Schritt gibt. Was ist eine gute, aber fundamentale Verwendung von |?

Im Idealfall werden in dem von mir vorgestellten Beispiel Programme verwendet, die selbst Ausgaben haben, die unabhängig voneinander ausgeführt und dann zusammen weitergeleitet werden können.

Matthew
quelle
3
Ihr Beispiel ist wirklich nicht so gut - es ist im Grunde eine Nominierung für den Preis für nutzlose Katzennutzung.
Maxschlepzig
@maxschlepzig Nicht dass du uns Unrecht tust, aber du bist auch nicht sehr hilfreich; das brauchst du nicht cat, das less whatever.txtfunktioniert prima.
Bora M. Alper

Antworten:

34

Ich werde Sie durch ein etwas komplexes Beispiel führen, das auf einem realen Szenario basiert.

Problem

Angenommen, der Befehl conkyreagiert auf meinem Desktop nicht mehr und ich möchte ihn manuell beenden. Ich kenne ein bisschen Unix, also weiß ich, dass ich den Befehl ausführen muss kill <PID>. Um die PID abzurufen, kann ich verwenden psoder topoder was auch immer Werkzeug meiner Unix - Distribution mir gegeben hat. Aber wie kann ich das mit einem Befehl machen?

Antworten

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

HAFTUNGSAUSSCHLUSS: Dieser Befehl funktioniert nur in bestimmten Fällen. Kopieren Sie es nicht in Ihr Terminal und fangen Sie nicht an, es könnte Prozesse ahnungslos abbrechen. Lerne lieber, wie man es baut .

Wie es funktioniert

1- ps aux

Dieser Befehl gibt die Liste der ausgeführten Prozesse und einige Informationen dazu aus. Die interessante Info ist, dass es die PID jedes Prozesses in seiner 2. Spalte ausgibt. Hier ist ein Auszug aus der Ausgabe des Befehls auf meiner Box:

$ 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

Ich interessiere mich nur für einen Prozess, daher suche ich grepden Eintrag, der meinem Programm entspricht 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

Wie Sie in Schritt 2 sehen können, gibt der Befehl psden grep conkyProzess in seiner Liste aus (es ist immerhin ein laufender Prozess). Um es zu filtern, kann ich laufen grep -v grep. Die Option -vsagt grepalle Linien passen ohne diejenigen , die Muster enthalten.

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

NB: Ich würde gerne wissen, wie Sie die Schritte 2 und 3 in einem einzigen grepAnruf ausführen können.

4- awk '{print $2}'

Jetzt habe ich meinen Zielprozess isoliert. Ich möchte die PID abrufen. Mit anderen Worten, ich möchte das 2. Wort der Ausgabe abrufen. Glücklicherweise bieten die meisten (alle?) Modernen Unices eine Version von awk, einer Skriptsprache, die mit tabellarischen Daten Wunder vollbringt. Unsere Aufgabe wird so einfach wie print $2.

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

5- xargs kill

Ich habe die PID. Ich muss es nur weitergeben kill. Dazu werde ich verwenden xargs.

xargs killliest aus der Eingabe (in unserem Fall aus der Pipe), bildet einen Befehl , der aus kill <items>( <items>was auch immer aus der Eingabe gelesen wird) besteht, und führt dann den erstellten Befehl aus. In unserem Fall wird es ausgeführt kill 1948. Mission erfüllt.

Letzte Worte

Beachten Sie, dass sich bestimmte Programme je nach verwendeter Unix-Version möglicherweise etwas anders verhalten (z. B. psdie PID in Spalte $ 3 ausgeben). Wenn etwas falsch oder anders scheint, lesen Sie die Dokumentation Ihres Anbieters (oder besser die manSeiten). Seien Sie auch vorsichtig, da lange Rohre gefährlich sein können. Machen Sie keine besonderen Annahmen, wenn Sie Befehle wie killoder verwenden rm. Wenn es beispielsweise einen anderen Benutzer mit dem Namen "conky" (oder "Aconkyous") gab, kann mein Befehl auch alle laufenden Prozesse beenden!

Was ich sage, ist Vorsicht, besonders bei langen Rohren. Es ist immer besser, es interaktiv aufzubauen, als Annahmen zu treffen und sich später zu entschuldigen.

rahmu
quelle
NB: Ich würde gerne wissen, wie Sie die Schritte 2 und 3 in einem einzigen grep-Aufruf ausführen können. -> grep "conky -q" :)
Wolfy
3
Eigentlich ist das ein schlechtes Beispiel, wie man es einfach machen könntekill $(pgrep conky)
Patrick
5
Ich weiß , das spät ist, aber man konnte es vereinfachen noch weiterpkill conky
strugee
2
"" NB: Ich würde gerne wissen, wie Sie die Schritte 2 und 3 in einem einzigen grep-Aufruf ausführen können. " -konforme. Auf diese Weise wird der grep-Prozess nur als "grep" anstelle von "grep conky" angezeigt, sodass er nicht mit sich selbst übereinstimmt.
Random832
2
NB: Ich würde gerne wissen, wie Sie die Schritte 2 und 3 in einem einzigen grepAnruf ausführen können. grep [c]onkyist was Sie suchen.
AlexT
15

Mein Favorit ist dieser:

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

Lädt ein Video von der angegebenen YouTube-URL herunter $1und gibt es als die von angegebene Datei aus $2. Beachten Sie, wie leise die Datei ist-q im Hintergrund an STDOUT ausgegeben -o -, an ffmpeg weitergeleitet und von dort als Eingabe verwendet wird -i -.

Insbesondere für Linux-Neulinge kann dies ein praktisches Beispiel sein, warum die Befehlszeile nützlich sein kann und die Dinge einfacher macht als die Verwendung von GUI-Tools. Ich bin mir nicht sicher, wie lange es dauern würde, ein Video von YouTube herunterzuladen und seinen Sound in eine MP3-Datei umzuwandeln. Die obige Zeile kann das in einigen Sekunden erledigen.

Baarn
quelle
3
youtube-dl hat die Option, nur Audio zu speichern. Mein üblicher Befehl ist dies, wo URLs in auf stdin kommen: youtube-dl --extract-audio --audio-format mp3 -a -. Ein cooles Beispiel, aber es gibt einfachere Möglichkeiten. (Es ruft intern ffmpeg auf.)
Brigand
3
@FakeRainBrigand: Haha, gut zu wissen! Aber ich habe eine Alternative, die nicht eingebaut werden sollte: youtube-dl $1 -q -o - | mplayer -Spielt das Video direkt im mplayer ab. Ich benutze diesen Befehl von meinem Laptop, um meinem Server (der an das Fernsehgerät angeschlossen ist) mitzuteilen, dass Videos abgespielt werden sollen. Ich muss anhängen -display :0.0 -geometry 400x300+1200+200, damit das mplayer-Fenster auf dem richtigen Bildschirm angezeigt wird.
Baarn
9

Die allgemeine Verwendung (sprich: die Art, wie ich es meistens benutze) ist, wenn ich aus irgendeinem Grund einige Daten über mehrere Tools ausführen muss, um verschiedene Verarbeitungsaufgaben auszuführen.

Ich würde also sagen, dass die Verwendung von Pipes als Klebstoff dient, um mehrere Bausteine ​​(die verschiedenen UNIX-Tools) zusammenzufügen. Wie Ulrich sagte, sortund uniqist eine gemeinsame Strophe.

Wenn Sie die Verwendung von Pipes hervorheben möchten, können Sie je nach Publikum beispielsweise mit folgendem beginnen: "Hey, dieser Lehrplan enthält Links zu mehreren interessanten PDFs mit Beiträgen und Vorlesungsskripten, einige davon werden jedoch wiederholt. Kann ich irgendwie automatisieren? "

Dann könnten Sie zeigen , wie lynx --dump --listonlydie Liste der Links bekommen, wie grepfür Links filtern könnte enden .pdf, wie colrmoder sedloszuwerden, die Zahlen bekommen konnte lynxschreibt zu jeder URL links, wie sortund uniqkönnten Duplikate entfernen, und schließlich , wie wget -i -verwendet werden kann , die zum Abrufen Dateien (mit--wait um den Server zu schonen).

Ich fürchte, das ist ein komplexes Beispiel. Auf der anderen Seite kann es hilfreich sein, die Leistung von Pfeifen zu zeigen, wenn Sie sie nur pfeifen und die Shell alles auf einmal laufen lassen.

njsg
quelle
2
Sie können es auch sort -uin GNU-Coreutils verwenden .
Teresa e Junior
2

Ich weiß nicht genau, was gut ist, aber das Durchpfeifen grepmuss eine der häufigsten Anwendungen sein, möglicherweise gefolgt von wc -l. (Ja, grephat den wenig bekannten -cSchalter.)

Eine weitere häufige Zeilengruppe ist | sort | uniq, wenn auch nur, weil uniqdie Eingabe sortiert werden muss.

Ulrich Schwarz
quelle
Die meisten Leute bevorzugen es, ... | sort -uwenn verfügbar!
2

Nicht, dass Sie es für dieses Beispiel benötigen, aber:

$ ps aux | grep -v grep | grep conky

... das Umkehren der Greps-Reihenfolge bewahrt die Färbung, ist aber VIEL weniger effizient. vermutlich auf großen Listen, würde Farbe nicht ausmachen.

Auch diese Webseite schlägt vor:

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

> Johnsyweb antwortete am 21. Februar 12 um 10:31 Uhr
> Der übliche Trick ist:
> ps aux | grep '[t] erminal'
> Dies passt zu Zeilen, die terminal enthalten, was grep '[t] erminal' nicht tut!
> Es funktioniert auch mit vielen Unix-Versionen.

... aber das wird nicht funktionieren, wenn Sie einen einzelnen Buchstaben suchen (wie Prozess 'X').

anonymisieren
quelle
2

Endlich kann ich dieses Durcheinander mit einem Oneliner teilen, den ich vor ungefähr eineinhalb Jahren gemacht habe ...

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/'

Es...

  1. Liest sites.txt
  2. Läuft auf jedem "host" (im Nachhinein hätte dig + short dies eine Tonne einfacher gemacht)
  3. Entfernt die Zeilen, die "GOOGLE" enthalten - dies sind die MX-Datensätze
  4. Ruft die Leitungen mit einer von zwei IPs ab
  5. Ruft den http-Statuscode von jeder Site in der Liste ab
  6. Entfernt die Sites, die 4xx oder 5xx zurückgeben
  7. Entfernt die "200" von Websites, die diese zurückgegeben haben
  8. Ersetzt "HTTP" durch "http" - rein ästhetisch, kein wirklicher Grund.

Ich wette, das hätte mit einem einzigen Python-Skript viel besser gemacht werden können.

Gerber
quelle
Äh ... Ich bin mir nicht sicher, ob dies das sauberste und einfachste Beispiel ist, um einem Neuling das Piping zu erklären;)
Erathiel
2
Meine Frage ist, was ist ihr Zweck?
ADTC
Ich hatte eine Datei voller Domains und musste feststellen, ob sie sich auf einem meiner beiden Server befanden (die ich leider "geerbt" hatte). Dadurch wird die Datei gelesen, "host" ausgeführt und die Ausgabe bereinigt. Anschließend wird nur eine Anforderung ausgeführt, um festzustellen, ob ein 4xx- oder 5xx-Fehler zurückgegeben wird. Wenn dies der Fall wäre, würde die Domäne verworfen. wenn nicht, gibt es sie aus und ich lege es in eine andere Datei.
Gerber
1

Das ist mir als erstes in den Sinn gekommen ...

mysqldumpist eine Konsolenanwendung, die Daten, Schemata und optional Prozeduren und Funktionen an stdout sendet. Normalerweise wird es zur Sicherung in eine Datei umgeleitet.

mysqldump <options> > mydb.dump

Das würde Ihnen ein unkomprimiertes SQL-Skript geben. Um Platz zu sparen, können Sie es mit bzip2 komprimieren.

bzip2 mydb.dump

Alternativ können Sie beide Schritte in einem Schritt ausführen:

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

In diesem obigen Beispiel wird die stdout von mysqldumpan bzip2 weitergeleitet, dessen Ausgabe dann in eine Datei umgeleitet wird.

Sean C.
quelle
1
Fügen Sie die umgekehrte Operation zu: bzcat mydb.dump.bz2 | mysql <options>.
Manatwork
1

Hier ist ein Beispiel, das ich in meinem Job für mehrere Pipes in einem Befehl verwende. Dies verwendet gawk, um das allgemeine MySQL-Abfrageprotokoll ($ OFILE) zu durchsuchen und alle abgelehnten Anmeldungen zu finden. Anschließend wird diese Liste nach Namen sortiert, die Liste wird an uniq weitergeleitet, wobei die Vorkommen gezählt werden. Anschließend wird die Liste ein letztes Mal weitergeleitet, um die gezählte Liste numerisch zu sortieren.

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

Pipes eignen sich am besten für Filter und Übersetzer

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

Auf diese Weise können die Daten von einem Programm zum nächsten gepuffert fließen, und zu keinem Zeitpunkt müssen sich alle Daten auf einmal im Speicher befinden.

PSkocik
quelle
0

cat filename | less ist eine schreckliche Verwendung von Rohrleitungen, da Sie nur tun können less filename

Hier ist ein Beispiel für Pips, die ich jeden Tag verwende (aber möglicherweise auch ein schlechtes Beispiel): ls -la | more -c

Die Antworten von Scott Hoffman und NJSG sind bessere Beispiele.

DwB
quelle
0

Führen Sie diesen Befehl in einem beliebigen Verzeichnis aus, für das Sie eine sortierte Analyse der Ordnergröße durchführen möchten (dann scrollen Sie mit der END-Taste nach unten):

du -m| sort -n| less

Sortiert nach Ordnergrösse

xubunuser
quelle
0

Hier ist ein Beispiel, das ich zum Setzen der DISPLAY-Variablen verwendet habe, als xauth keine Option war ...

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

Der erste Befehl ruft die benötigten Daten ab, dh Hostname oder IP. Der zweite Befehl erhält genau diese Daten (letztes Feld). Schließlich entfernt der letzte Befehl Klammern aus den Daten.

Scott Hoffman
quelle
0

Befehls-Piping können Sie überall dort verwenden, wo Sie das Gefühl haben, dass die Ausgabe des ersten Befehls als Eingabe an die nächste weitergeleitet werden kann.

Beispiele.

  1. Bei Textdateien können Sie die Textdatei an grep übergeben, um bestimmte Textzeilen zu finden. Anschließend können Sie die Ausgabe an sed oder awk übergeben, um einen bestimmten Teil der Zeile zu ändern oder zu drucken.

Katzenbeispiel txt | grep {some_line} | awk {some_command}

  1. Bei der Arbeit mit Prozessen können Sie mithilfe der Piping-Funktion Befehle zum Beenden des Prozesses senden.

Es ist einfach das Konzept, dass, wenn Sie glauben, dass die Ausgabe eines Befehls, den Sie ausgeführt haben, die Eingabe eines anderen Befehls sein kann, den Sie weiterleiten können.

Piyush Jain
quelle