Qual é um bom exemplo de comandos de tubulação juntos?

33

Se você estivesse ajudando alguém a aprender o conceito de pipes na linha de comando, que exemplo você usaria? O exemplo que realmente surgiu foi o seguinte:

cat whatever.txt | less

Sinto que esse não é o melhor exemplo, ou seja, porque há apenas um passo. De que serve um uso bom, porém fundamental |?

Idealmente, o exemplo que apresentarei usará programas que possuem saídas próprias que podem ser executadas independentemente e depois mostradas juntas.

Mateus
fonte
3
Seu exemplo realmente não é tão bom - é basicamente uma indicação ao prêmio de uso inútil de gato.
maxschlepzig
@maxschlepzig Não que você esteja errado, mas você também não é muito útil; você não precisa catdisso, pois less whatever.txtfunciona muito bem.
Bora M. Alper

Respostas:

34

Vou orientá-lo em um exemplo um tanto complexo, baseado em um cenário da vida real.

Problema

Digamos que o comando conkyparou de responder na minha área de trabalho e quero matá-lo manualmente. Conheço um pouco do Unix, então sei que o que preciso fazer é executar o comando kill <PID>. Para recuperar o PID, posso usar psou topou qualquer outra ferramenta que minha distribuição Unix me deu. Mas como posso fazer isso em um comando?

Responda

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

AVISO LEGAL: Este comando funciona apenas em certos casos. Não copie / cole no seu terminal e comece a usá-lo, pois isso pode matar os processos sem suspeitar. Em vez disso, aprenda como construí-lo .

Como funciona

1- ps aux

Este comando exibirá a lista de processos em execução e algumas informações sobre eles. A informação interessante é que ele produzirá o PID de cada processo em sua 2ª coluna. Aqui está um extrato da saída do comando na minha caixa:

$ 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

Estou interessado apenas em um processo, então eu uso greppara encontrar a entrada correspondente ao meu programa 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

Como você pode ver na etapa 2, o comando psgera o grep conkyprocesso em sua lista (afinal, é um processo em execução). Para filtrá-lo, eu posso correr grep -v grep. A opção -vindica greppara corresponder a todas as linhas, excluindo as que contêm o padrão.

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

NB: Eu adoraria saber uma maneira de executar as etapas 2 e 3 em uma única grepchamada.

4- awk '{print $2}'

Agora que eu isolei meu processo de destino. Eu quero recuperar seu PID. Em outras palavras, quero recuperar a segunda palavra da saída. Para minha sorte, a maioria (todos?) Dos escritórios modernos fornecerá uma versão de awkuma linguagem de script que faz maravilhas com dados tabulares. Nossa tarefa se torna tão fácil quanto print $2.

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

5- xargs kill

Eu tenho o PID. Tudo que eu preciso é passar para kill. Para fazer isso, eu vou usar xargs.

xargs killlerá da entrada (no nosso caso, do canal), formará um comando que consiste em kill <items>( <items>seja o que for que for lido da entrada) e, em seguida, execute o comando criado. No nosso caso, ele será executado kill 1948. Missão cumprida.

Palavras finais

Observe que, dependendo da versão do unix que você está usando, determinados programas podem se comportar de maneira um pouco diferente (por exemplo, pspode gerar o PID na coluna $ 3). Se algo parecer errado ou diferente, leia a documentação do seu fornecedor (ou melhor, as manpáginas). Também tenha cuidado, pois tubos longos podem ser perigosos. Não faça suposições, especialmente ao usar comandos como killou rm. Por exemplo, se houvesse outro usuário chamado 'conky' (ou 'Aconkyous'), meu comando também poderia matar todos os seus processos em execução!

O que estou dizendo é ter cuidado, especialmente para tubos longos. É sempre melhor construí-lo interativamente, como fizemos aqui, do que fazer suposições e sentir pena depois.

rahmu
fonte
NB: Gostaria muito de saber uma maneira de executar as etapas 2 e 3 em uma única chamada grep. -> grep "-q conky" :)
Wolfy
3
Na verdade, isso é um mau exemplo, como você poderia simplesmente fazerkill $(pgrep conky)
Patrick
5
Eu sei que isto é tarde, mas você poderia simplificá-lo ainda mais parapkill conky
strugee
2
"" "NB: Eu adoraria saber uma maneira de executar as etapas 2 e 3 em uma única chamada grep." "" Em vez de "aux" use "-o pid, comm" - isso também é mais portátil, pois é POSIX -complacente. Dessa forma, o processo grep aparecerá como "grep" em vez de "grep conky", para que não corresponda a si próprio.
Random832
2
NB: Eu adoraria saber uma maneira de executar as etapas 2 e 3 em uma única grepchamada. grep [c]onkyé o que você está procurando.
AlexT
15

O meu favorito é este:

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

baixa um vídeo do URL do YouTube fornecido $1e o exibe como o arquivo fornecido por $2. Observe como o arquivo é -qbaixado silenciosamente para STDOUT -o -, canalizado para ffmpeg e usado como entrada por lá -i -.

Especialmente para iniciantes no Linux, este pode ser um exemplo prático do motivo pelo qual a linha de comando pode ser útil e facilitar as coisas do que usar ferramentas da GUI. Não sei quanto tempo levaria para baixar um vídeo do youtube e converter seu som em um mp3. A linha acima pode fazer isso em alguns segundos.

Baarn
fonte
3
O youtube-dl tem uma opção para salvar apenas o áudio. Meu comando usual é este, onde URLs entrar em stdin: youtube-dl --extract-audio --audio-format mp3 -a -. Ainda é um exemplo legal, mas existem maneiras mais fáceis de fazer isso. (Chama ffmpeg internamente).
Brigand
3
@FakeRainBrigand: Haha, bom saber! Mas eu tenho uma alternativa que não deve ser incorporada: youtube-dl $1 -q -o - | mplayer -reproduz diretamente o vídeo no mplayer. Eu uso esse comando no meu laptop para dizer ao meu servidor (conectado à TV) para reproduzir vídeos. Tenho que acrescentar -display :0.0 -geometry 400x300+1200+200para permitir que a janela do mplayer apareça na tela correta.
Baarn
9

O uso geral (leia-se: o modo como uso na maioria das vezes) é quando, por algum motivo, tenho que executar alguns dados através de várias ferramentas para executar tarefas de processamento diferentes.

Então, eu diria que o uso de tubos é como cola para montar vários blocos de construção (as diferentes ferramentas UNIX) juntos. Como Ulrich disse, sorte uniqé uma estrofe comum.

Dependendo da audiência, se você quiser destacar esse uso de pipes, poderá, por exemplo, começar com: "ei, este programa contém links para vários PDFs interessantes com papéis e notas de aula, mas alguns deles são repetidos. de alguma forma automatizar isso? "

Em seguida, você pode mostrar como lynx --dump --listonlyfica a lista de links, como grepfiltrar os links que terminam em .pdf, como colrmou sedpode se livrar dos números lynxgravados restantes em cada URL, como sorte uniqse livrar das duplicatas e, finalmente, como wget -i -pode ser usado para recuperar o arquivos (usando --waitpara ser gentil com o servidor, é claro).

Receio que este seja um exemplo complexo. Por outro lado, pode ajudar a mostrar a potência dos tubos quando você apenas o canaliza e faz com que a concha execute tudo de uma vez.

njsg
fonte
2
Você pode usar sort -uem coreutils GNU também.
Teresa e Junior
2

Eu não sei exatamente o que é bom, mas a tubulação grepdeve ser um dos usos mais comuns, possivelmente seguido por wc -l. (Sim, greppossui a opção pouco conhecida -c.)

Outra estrofe comum é | sort | uniq, apenas porque uniqrequer que sua entrada seja classificada.

Ulrich Schwarz
fonte
A maioria das pessoas prefere ... | sort -use disponível!
2

Não que você precise para este exemplo, mas:

$ ps aux | grep -v grep | grep conky

... inverter a ordem dos greps preserva a colorização, mas é MUITO menos eficiente. presumivelmente em grandes listas, a cor não importaria.

Além disso, esta página da Web sugere:

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

> Johnsyweb respondeu em 21/02 às 10:31
> O truque usual é este:
> ps aux | grep '[t] erminal'
> Isso corresponderá às linhas que contêm o terminal, que grep '[t] erminal' não!
> Também funciona em muitos sabores do Unix.

... mas isso não funcionará se você estiver procurando uma única letra (como o processo 'X').

anonymuse
fonte
2

Eu finalmente posso compartilhar essa bagunça que eu fiz há cerca de um ano e meio ...

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

Isto...

  1. Lê sites.txt
  2. Executa "host" em cada um (em retrospectiva, dig + short tornaria isso muito mais fácil)
  3. Remove as linhas que contêm "GOOGLE" - esses são os registros mx
  4. Obtém as linhas que possuem um dos dois IPs
  5. Obtém o código de status http de cada site na lista
  6. Remove os sites que retornam 4xx ou 5xx
  7. Retira o "200" dos sites que retornaram esse
  8. Substitui "HTTP" por "http" - puramente estético, sem motivo real.

Isso poderia ter sido muito melhor com um único script Python, aposto.

curtidor
fonte
Uh ... eu não estou certo de que este seria o exemplo mais limpo e mais fácil para explicar a tubagem a um novato;)
Erathiel
2
Minha pergunta é: qual é o seu propósito?
ADTC
Eu tinha um arquivo cheio de domínios e precisava ver se eles estavam em um dos meus dois servidores (que "herdei", infelizmente). Isso lê o arquivo, "hospeda" e limpa essa saída e apenas faz uma solicitação para verificar se ele retorna um erro 4xx ou 5xx. Se o fizesse, descartaria o domínio; caso contrário, ele será exibido e eu o colocarei em outro arquivo.
Tanner
1

Esta é a primeira coisa que me veio à mente ...

mysqldumpé um aplicativo de console que envia dados, esquema e, opcionalmente, procedimentos e funções ao stdout. Geralmente, ele é redirecionado para um arquivo para backup.

mysqldump <options> > mydb.dump

Isso daria a você um script sql não compactado. Para economizar espaço, você pode compactá-lo com o bzip2.

bzip2 mydb.dump

Como alternativa, você pode fazer as duas coisas em uma etapa:

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

Neste exemplo acima, o stdout from mysqldumpé canalizado para o bzip2, que, em seguida, é redirecionado para um arquivo.

Sean C.
fonte
1
Adicione a operação inversa também: bzcat mydb.dump.bz2 | mysql <options>.
Manatwork
1

Aqui está um exemplo que eu uso no meu trabalho de vários pipes em um comando. Isso usa o gawk para pesquisar o log de consultas gerais do MySQL ($ OFILE) e encontrar os logins negados. Em seguida, classifica essa lista por nome, canaliza a lista para uniq, que conta as ocorrências e, em seguida, canaliza uma última vez para classificar a lista contada numericamente ...

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

Os tubos funcionam melhor com filtros e tradutores

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

Dessa forma, os dados podem fluir de um programa para o próximo buffer e, em nenhum momento, todos os dados precisam estar na memória de uma só vez.

PSkocik
fonte
0

cat filename | less é um uso terrível da tubulação, já que você pode simplesmente fazer less filename

Aqui está um exemplo de pips que eu uso todos os dias (mas também pode ser um mau exemplo): ls -la | more -c

As respostas de scott hoffman e njsg são melhores exemplos.

DwB
fonte
0

execute este em qualquer diretório que você deseja classificar para analisar o tamanho da pasta (depois role para baixo com a tecla END):

du -m| sort -n| less

Sortiert nach Ordnergrösse

xubunuser
fonte
0

Aqui está um exemplo que eu usei para definir a variável DISPLAY quando o xauth não era uma opção ...

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

O primeiro comando obtém os dados necessários, ou seja, nome do host ou IP. O segundo comando obtém apenas esses dados (último campo). Finalmente, o último comando retira parênteses dos dados.

Scott Hoffman
fonte
0

Tubulação de comando que você pode usar em qualquer lugar que achar que a saída do primeiro comando pode ser alimentada como entrada para a próxima.

Exemplos.

  1. Com arquivos de texto, você pode passar o arquivo de texto para grep para encontrar linhas de texto específicas. Em seguida, você pode passar a saída para sed ou awk para modificar ou imprimir determinada parte da linha.

exemplo de gato txt | grep {some_line} | awk {some_command}

  1. Trabalhando com o processo, você pode usar a tubulação para enviar comandos para interromper o processo.

É simplesmente o conceito de que, se você sentir a saída do comando executada, pode ser a entrada de outro comando, pode canalizá-los.

Piyush Jain
fonte