Qual è un buon esempio di comandi di piping insieme?


33

Se aiutassi qualcuno ad imparare il concetto di pipe dalla riga di comando quale esempio useresti? L'esempio che effettivamente è emerso è stato il seguente:

cat whatever.txt | less

Sento che non è il miglior esempio, vale a dire perché c'è solo un passo. Che cosa è un buon, ma fondamentale, uso di |?

Idealmente, l'esempio che presenterò utilizzerà programmi che hanno output stessi che possono essere eseguiti in modo indipendente e quindi mostrati insieme.


3
Il tuo esempio non è poi così buono - è fondamentalmente una nomination per il premio inutile-di-gatto.
maxschlepzig,

@maxschlepzig Non ti sbagli, ma non sei di grande aiuto; non ti serve catperché less whatever.txtfunziona bene.
Bora M. Alper,

Risposte:


34

Ti guiderò attraverso un esempio piuttosto complesso, basato su uno scenario di vita reale.

Problema

Diciamo che il comando ha conkysmesso di rispondere sul mio desktop e voglio ucciderlo manualmente. Conosco un po 'Unix, quindi so che quello che devo fare è eseguire il comando kill <PID>. Al fine di recuperare il PID, posso usare pso topo qualunque strumento mia distribuzione Unix mi ha dato. Ma come posso farlo in un solo comando?

Risposta

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

NOTA BENE: questo comando funziona solo in alcuni casi. Non copiarlo / incollarlo nel tuo terminale e iniziare a usarlo, potrebbe uccidere i processi in modo ignaro. Piuttosto impari come costruirlo .

Come funziona

1- ps aux

Questo comando mostrerà l'elenco dei processi in esecuzione e alcune informazioni su di essi. Le informazioni interessanti sono che produrrà il PID di ogni processo nella sua seconda colonna. Ecco un estratto dall'output del comando sulla mia scatola:

$ 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

Sono interessato a un solo processo, quindi utilizzo grepla voce corrispondente al mio programma 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

Come puoi vedere nel passaggio 2, il comando psgenera il grep conkyprocesso nel suo elenco (dopo tutto è un processo in esecuzione). Per filtrarlo, posso eseguire grep -v grep. L'opzione -vdice grepdi abbinare tutte le linee escludendo quelle che contengono il modello.

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

NB: Mi piacerebbe conoscere un modo per eseguire i passaggi 2 e 3 in una singola grepchiamata.

4- awk '{print $2}'

Ora che ho isolato il mio processo target. Voglio recuperare il suo PID. In altre parole, voglio recuperare la seconda parola dell'output. Fortunatamente per me, la maggior parte dei (tutti?) Gli unici moderni fornirà una versione di awk, un linguaggio di scripting che fa miracoli con dati tabulari. Il nostro compito diventa facile come print $2.

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

5- xargs kill

Ho il PID. Tutto ciò di cui ho bisogno è passarlo a kill. Per fare questo, userò xargs.

xargs killleggerà dall'input (nel nostro caso dalla pipe), formerà un comando costituito da kill <items>( <items>sono qualunque cosa abbia letto dall'input), e quindi eseguirà il comando creato. Nel nostro caso verrà eseguito kill 1948. Missione compiuta.

Parole finali

Si noti che a seconda della versione di unix in uso, alcuni programmi potrebbero comportarsi in modo leggermente diverso (ad esempio, pspotrebbe generare il PID nella colonna $ 3). Se qualcosa sembra sbagliato o diverso, leggi la documentazione del tuo fornitore (o meglio, le manpagine). Inoltre, fai attenzione perché i tubi lunghi possono essere pericolosi. Non fare ipotesi soprattutto quando si usano comandi come killo rm. Ad esempio, se ci fosse un altro utente chiamato "conky" (o "Aconkyous") il mio comando potrebbe anche uccidere tutti i suoi processi in esecuzione!

Quello che sto dicendo è fare attenzione, soprattutto per le pipe lunghe. È sempre meglio costruirlo interattivamente come abbiamo fatto qui, piuttosto che fare ipotesi e sentirsi dispiaciuto in seguito.


NB: Mi piacerebbe conoscere un modo per eseguire i passaggi 2 e 3 in una singola chiamata grep. -> grep "conky -q" :)
Wolfy,

3
In realtà questo è un cattivo esempio, come potresti semplicemente farekill $(pgrep conky)
Patrick,

5
So che è tardi, ma potresti semplificarlo ancora di piùpkill conky
strugee,

2
"" "NB: Mi piacerebbe conoscere un modo per eseguire i passaggi 2 e 3 in una singola chiamata grep." "" Invece di "aux" usa "-o pid, comm" - anche questo è più portabile poiché POSIX -conforme. In questo modo il processo grep verrà visualizzato come "grep" invece di "grep conky" in modo che non corrisponda a se stesso.
Casuale 832,

2
NB: Mi piacerebbe conoscere un modo per eseguire i passaggi 2 e 3 in una singola grepchiamata. grep [c]onkyè quello che stai cercando.
AlexT

15

Il mio preferito è questo:

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

scarica un video dall'URL di YouTube fornito $1e lo emette come file fornito da $2. Nota come il file viene inviato in modo silenzioso -qa STDOUT -o -, reindirizzato a ffmpeg e utilizzato come input lì -i -.

Soprattutto per i neofiti di Linux, questo potrebbe essere un esempio pratico del motivo per cui la riga di comando può essere utile e rendere le cose più semplici rispetto all'utilizzo degli strumenti della GUI. Non sono sicuro di quanto tempo ci vorrebbe per scaricare un video da YouTube e convertire il suo suono in un mp3. La riga sopra può farlo in alcuni secondi.


3
youtube-dl ha un'opzione per salvare solo l'audio. Il mio solito comando è questo, in cui gli URL vengono in su stdin: youtube-dl --extract-audio --audio-format mp3 -a -. Ancora un bell'esempio, ma ci sono modi più semplici per farlo. (Chiama ffmpeg internamente.)
Brigand

3
@FakeRainBrigand: Haha, buono a sapersi! Ma ho un'alternativa che non dovrebbe essere integrata: youtube-dl $1 -q -o - | mplayer -riproduce direttamente il video all'interno di mplayer. Uso quel comando dal mio laptop per dire al mio server (che è collegato alla TV) di riprodurre video. Devo aggiungere -display :0.0 -geometry 400x300+1200+200per far apparire la finestra di mplayer sullo schermo corretto.
Baarn,

9

L'uso generale (leggi: il modo in cui lo uso la maggior parte delle volte) è quando, per qualche motivo, devo eseguire alcuni dati attraverso diversi strumenti per svolgere diverse attività di elaborazione.

Quindi direi che l' uso di tubi è come colla per assemblare insieme diversi elementi costitutivi (i diversi strumenti UNIX). Come ha detto Ulrich, sorted uniqè una strofa comune.

A seconda del pubblico, se si desidera evidenziare questo utilizzo delle pipe, è possibile, ad esempio, iniziare con: "hey, questo programma ha collegamenti a diversi PDF interessanti con documenti e appunti delle lezioni, ma alcuni di essi vengono ripetuti. in qualche modo automatizzare questo? "

Quindi puoi mostrare come lynx --dump --listonlyottiene l'elenco dei collegamenti, come grepfiltrare i collegamenti che finiscono .pdf, come colrmo come sedsbarazzarsi dei numeri lynxscritti su ciascun URL, come sorte come uniqsbarazzarsi dei duplicati e infine come si wget -i -può usare per recuperare il file (usando --waitper essere gentili sul server, ovviamente).

Temo che questo sia un esempio complesso. D'altra parte, può essere utile mostrare la potenza dei tubi quando si esegue semplicemente il tubo e si esegue il guscio tutto in una volta.


2
Puoi usarlo anche sort -unei coreutils GNU .
Teresa e Junior,

2

Non so esattamente del bene, ma il piping through grepdeve essere uno degli usi più comuni, probabilmente seguito da wc -l. (Sì, grepha l' -cinterruttore poco noto .)

Un'altra strofa comune è | sort | uniq, se non altro perché uniqrichiede che il suo input sia ordinato.


La maggior parte delle persone preferisce ... | sort -use disponibile!

2

Non che ne hai bisogno per questo esempio, ma:

$ ps aux | grep -v grep | grep conky

... invertire l'ordine delle greps preserva la colorazione, ma è MOLTO meno efficiente. presumibilmente su grandi elenchi, il colore non avrebbe importanza.

inoltre, questa pagina web suggerisce:

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

> Johnsyweb ha risposto il 21 febbraio 12 alle 10:31
> Il solito trucco è questo:
> ps aux | grep '[t] erminal'
> Questo abbinerà le righe contenenti il ​​terminale, che grep '[t] erminal' non lo fa!
> Funziona anche su molti gusti di Unix.

... ma non funzionerà se stai cercando una singola lettera (come il processo 'X').


2

Finalmente riesco a condividere questo casino di un oneliner che ho fatto circa un anno e mezzo fa ...

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

E '...

  1. Legge sites.txt
  2. Esegue "host" su ciascuno (con il senno di poi, dig + short avrebbe reso tutto molto più semplice)
  3. Rimuove le righe che contengono "GOOGLE": questi sono i record mx
  4. Ottiene le linee che hanno uno dei due IP
  5. Ottiene il codice di stato http da ciascun sito nell'elenco
  6. Rimuove i siti che restituiscono 4xx o 5xx
  7. Elimina i "200" dai siti che lo hanno restituito
  8. Sostituisce "HTTP" con "http" - puramente estetico, nessuna vera ragione.

Scommetto che questo avrebbe potuto essere fatto molto meglio con un singolo script Python.


Uh ... Non sono sicuro che questo sarebbe l'esempio più semplice e pulito per spiegare le tubazioni a un principiante;)
Erathiel

2
La mia domanda è: qual è il suo scopo?
ADTC

Avevo un file pieno di domini e avevo bisogno di vedere se erano su uno dei miei due server (che "ereditavo", sfortunatamente). Questo legge il file, fa "host" e pulisce quell'output, quindi fa solo una richiesta per vedere se restituisce un errore 4xx o 5xx. In tal caso, eliminerebbe il dominio; in caso contrario, li ha emessi e l'ho messo in un altro file.
conciatore

1

Questa è la prima cosa che mi è venuta in mente ...

mysqldumpè un'applicazione console che invia dati, schema e facoltativamente procedure e funzioni a stdout. Di solito viene reindirizzato a un file per il backup.

mysqldump <options> > mydb.dump

Ciò ti darebbe uno script sql non compresso. Per risparmiare spazio, è possibile comprimerlo con bzip2.

bzip2 mydb.dump

In alternativa, puoi fare entrambe le cose in un solo passaggio:

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

In questo esempio sopra, lo stdout da mysqldumpviene reindirizzato a bzip2, il cui output viene quindi reindirizzato su un file.


1
Aggiungere l'operazione inversa troppo: bzcat mydb.dump.bz2 | mysql <options>.
arte

1

Ecco un esempio che utilizzo nel mio lavoro di più pipe in un solo comando. Questo utilizza gawk per cercare nel log delle query generali di MySQL ($ OFILE) e trovare eventuali accessi negati. Quindi ordina tale elenco per nome, reindirizza l'elenco a uniq che conta le occorrenze e quindi lo ordina un'ultima volta per ordinare numericamente l'elenco contato ...

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

1

I tubi funzionano meglio con filtri e traduttori

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

In questo modo, i dati possono fluire da un programma a quello successivo senza errori e in nessun momento tutti i dati devono essere in memoria contemporaneamente.


0

cat filename | less è un uso terribile delle tubazioni poiché puoi semplicemente farlo less filename

Ecco un esempio di pips che uso ogni giorno (ma potrebbe anche essere un cattivo esempio): ls -la | more -c

Le risposte di scott hoffman e njsg sono esempi migliori.



0

esegui questo in qualsiasi directory desideri avere un'analisi ordinata per le dimensioni della cartella (quindi scorri verso il basso con il tasto END):

du -m| sort -n| less

Sortiert nach Ordnergrösse


0

Ecco un esempio che ho usato per impostare la variabile DISPLAY quando xauth non era un'opzione ...

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

Il primo comando ottiene i dati necessari, ovvero nome host o IP. Il secondo comando ottiene solo quei dati (ultimo campo). Infine, l'ultimo comando elimina la parentesi dai dati.


0

Piping dei comandi che puoi utilizzare ovunque ritieni che l'output del primo comando possa essere immesso come input per il successivo.

Esempi.

  1. Con i file di testo è possibile passare il file di testo a grep per trovare particolari righe di testo. Quindi è possibile passare l'output a sed o awk per modificare o stampare determinate parti della linea.

cat esempio txt | grep {some_line} | awk {some_command}

  1. Lavorando con il processo è possibile utilizzare il piping per inviare comandi per terminare il processo.

È semplicemente il concetto che se ritieni che l'output del comando che hai eseguito possa essere immesso da un altro comando, puoi eseguirne il pipe.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.