Eu me pergunto o que quando devemos usar pipeline e quando não devemos.
Digamos, por exemplo, para eliminar um determinado processo que manipula arquivos PDF, o seguinte não funcionará usando o pipeline:
ps aux | grep pdf | awk '{print $2}'|kill
Em vez disso, só podemos fazer isso das seguintes maneiras:
kill $(ps aux| grep pdf| awk '{print $2}')
ou
ps aux | grep pdf | awk '{print $2}'| xargs kill
De acordo com man bash
(versão 4.1.2
):
The standard output of command is connected via a pipe to the standard input of command2.
Para o cenário acima:
- o stdin de
grep
é o stdout deps
. Isso funciona. - o stdin de
awk
é o stdout degrep
. Isso funciona. - o stdin de
kill
é o stdout deawk
. Isso não funciona.
O stdin do comando a seguir está sempre recebendo entrada do stdout do comando anterior.
- Por que não funciona com
kill
ourm
? - Qual é a diferença entre
kill
,rm
entrada comgrep
,awk
entrada? - Existem regras?
pgrep
,pkill
ekillall
comandos.pgrep
eo resto pode conseguir isso perfeitamente :)Respostas:
Existem duas maneiras comuns de fornecer entradas para os programas:
kill
usa apenas argumentos de linha de comando. Não lê de STDIN. Programas comogrep
eawk
lidos no STDIN (se nenhum nome de arquivo for fornecido como argumento de linha de comando) e processam os dados de acordo com seus argumentos de linha de comando (padrão, instruções, sinalizadores, ...).Você pode canalizar apenas para STDIN de outros processos, não para argumentos de linha de comando.
A regra comum é que os programas usam o STDIN para processar uma quantidade arbitrária de dados. Todos os parâmetros de entrada extras ou, se geralmente houver apenas alguns, são passados pelos argumentos da linha de comando. Se a linha de comando puder ficar muito longa, por exemplo, para
awk
textos longos de programas, geralmente há a possibilidade de lê-los em arquivos de programa extras (-f
opção deawk
).Para usar o STDOUT de programas como argumentos de linha de comando, use
$(...)
ou no caso de muitos dadosxargs
.find
também pode isso diretamente com-exec ... {} +
.Para completar: Para escrever argumentos de linha de comando em STDOUT, use
echo
.fonte
gzip
em SYNOPSIS, ele não disse que deveria receber um FILENAME como entrada. Eu estou procurando há uma maneira mais sistemática de determinar isso.xargs
permitirá com precisão "canalizar para argumentos da linha de comando"?xargs
. Ele chama o comando se necessário mais de uma vez (o tamanho da linha de comando é limitado) e possui muitas outras opções.Essa é uma pergunta interessante e lida com uma parte da filosofia Unix / Linux.
Então, qual é a diferença entre programas como
grep
,sed
,sort
por um lado ekill
,rm
,ls
por outro lado? Eu vejo dois aspectos.O aspecto do filtro
O primeiro tipo de programas também é chamado de filtros . Eles recebem uma entrada, de um arquivo ou de STDIN, modificam-na e geram alguma saída, principalmente para STDOUT. Eles devem ser usados em um canal com outros programas como fontes e destinos.
O segundo tipo de programas atua em uma entrada, mas a saída que eles fornecem geralmente não está relacionada à entrada.
kill
não tem saída quando trabalha regularmente, nem fazls
. Os apenas têm um valor de retorno para mostrar sucesso. Normalmente, eles não recebem entrada de STDIN, mas geralmente fornecem saída para STDOUT.Para programas como
ls
o aspecto do filtro não funciona tão bem. Certamente pode ter uma entrada (mas não precisa de uma) e a saída está intimamente relacionada a essa entrada, mas não funciona como um filtro. No entanto, para esse tipo de programa, o outro aspecto ainda funciona:O aspecto semântico
Para filtros, sua entrada não tem significado semântico . Eles apenas lêem dados, modificam dados, produzem dados. Não importa se esta é uma lista de valores numéricos, alguns nomes de arquivos ou código fonte HTML. O significado desses dados é fornecido apenas pelo código que você fornece ao filtro: a regex para
grep
, as regras paraawk
ou o programa Perl.Para outros programas, como
kill
ouls
, sua entrada tem um significado , uma denotação .kill
espera números de processo,ls
espera nomes de arquivos ou caminhos. Eles não podem manipular dados arbitrários e não devem. Muitos deles nem precisam de nenhuma entrada ou parâmetro, comops
. Eles normalmente não leem do STDIN.Provavelmente, pode-se combinar esses dois aspectos: Um filtro é um programa cuja entrada não tem um significado semântico para o programa.
Tenho certeza de que li sobre essa filosofia em algum lugar, mas não me lembro de nenhuma fonte no momento, desculpe. Se alguém tiver algumas fontes presentes, sinta-se à vontade para editar.
fonte
Não existem "regras" como tais. Alguns programas recebem entrada do STDIN e outros não. Se um programa pode receber informações do STDIN, ele pode ser canalizado para, se não, não pode.
Normalmente, você pode dizer se um programa irá receber informações ou não, pensando no que faz. Se o trabalho do programa é de alguma forma manipular os conteúdos de um arquivo (por exemplo
grep
,sed
,awk
etc.), que normalmente leva a entrada de STDIN. Se seu trabalho é manipular o arquivo em si (por exemplomv
,rm
,cp
) ou um processo (por exemplokill
,lsof
) ou às informações de retorno sobre algo (por exemplotop
,find
,ps
), então isso não acontece.Outra maneira de pensar sobre isso é a diferença entre argumentos e entrada. Por exemplo:
No comando acima,
mv
não tem entrada como tal. O que foi dado são dois argumentos. Ele não sabe nem se importa com o que está em nenhum dos arquivos, apenas sabe que esses são seus argumentos e deve manipulá-los.Por outro lado
Aqui,
sed
foi dada entrada, bem como um argumento. Uma vez que recebe entrada, ela pode ser lida no STDIN e pode ser canalizada para.Fica mais complicado quando um argumento pode ser a entrada. Por exemplo
Aqui
file
está o argumento que foi dadocat
. Para ser mais preciso, o nome do arquivofile
é o argumento. No entanto, comocat
é um programa que manipula o conteúdo dos arquivos, sua entrada é o que estiver dentrofile
.Isso pode ser ilustrado usando
strace
um programa que rastreia as chamadas do sistema feitas por processos. Secat foo
rodarmosstrace
, podemos ver que o arquivofoo
é aberto:A primeira linha acima mostra que o programa
/bin/cat
foi chamado e seus argumentos foramcat
efoo
(o primeiro argumento é sempre o próprio programa). Posteriormente, o argumentofoo
foi aberto no modo somente leitura. Agora, compare isso comAqui também,
ls
tomou-se efoo
como argumentos. No entanto, não háopen
chamada, o argumento não é tratado como entrada. Em vez disso,ls
chama astat
biblioteca do sistema (que não é a mesma coisa que ostat
comando) para obter informações sobre o arquivofoo
.Em resumo, se o comando que você está executando ler sua entrada, você poderá canalizar para ele; se não, não poderá.
fonte
kill
erm
não precisa de STDIN.Para
kill
erm
, os usuários fornecem suas informações personalizadas como argumento e$(cmd)
ajudam a obter o STDOUTcmd
e a convertê-lo no argumento de informações.Para
grep
eawk
, os usuários fornecem argumentos e, além disso, tambémSTDIN
ou um arquivo regular que será processado pelo comando.STDIN
pode ser passado com pipeline|
ou inserindo manualmente.Leia o manual ou os códigos-fonte. E se você não encontrar o que precisa, poderá fazer um teste simples, mas talvez perigoso:
Basta digitar o comando que lhe interessa, com argumentos que você já entendeu, e ver se o comando pausa (nada acontece). Se ele parar, ele está realmente à espera de STDIN (você pode tentar
cat
eecho
ver o diferente). Você digita manualmenteCtrl-D
e o comando prossegue (mostra resultados ou erros) e retorna. Esse comando precisa de STDIN nessa situação (com argumentos que você fornece).O mesmo comando pode não precisar de STDIN em diferentes situações (por exemplo,
cat
aguarda STDIN, mascat file.txt
não).fonte