Combine dois comandos em um comando

4

Como posso combinar esses dois comandos ps aux | head -n1 ; ps aux | grep vlc em um comando? Eu tentei usar o comando tee ( ps aux | tee >(head -n1) >(grep vlc) ), mas não funcionou!

    
por HBS 15.09.2015 / 16:34

5 respostas

19

Você está tentando preservar a cabeça do comando PS (assim você pode ver os cabeçalhos), mas mostra apenas os comandos vlc .

Eu pessoalmente usaria apenas awk e filtrar com base em duas condições, o número da linha e o VLC. Se um deles for verdadeiro, nós geramos a linha:

$ ps aux | awk 'NR==1 || ~/vlc/'
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
oli       4833  0.6  0.2 795220 62952 ?        Sl   15:37   0:00 /usr/bin/vlc

Tem a vantagem adicional de estar executando apenas ps uma vez. E como o campo 11 é o comando principal (não qualquer um dos seus argumentos), também não capturaremos o comando awk que está sendo executado. Acabamos de obter o VLC e os cabeçalhos das colunas.

Em uma barra lateral, algo como isso deve funcionar ... mas não ...

ps aux | tee >(head -1 >&2) | grep vlc

Você estava perto, você precisava canalizar para o último comando ou tee vai se desentender sobre STDOUT, e se você enviar para STDOUT e depois para pipe, é provável que ele seja capturado no último grep . No acima, eu imprimo os cabeçalhos em STDERR (2) para impedir que grep interfira nele. Bit hacky mas hey-ho.

Mas sim, isso ainda não funciona . O motivo é que head fecha o STDOUT , que filtra de volta para tee e detém o grep . Isso ocorre por design, portanto, head não processa mais entradas do que o necessário. Você pode simular o que está fazendo com awk :

$ ps aux | tee >(awk 'NR==1 {print;exit}' >&2) | grep "grep"
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND

Isso é equivalente a head -1 . Ele encontra a primeira linha e depois sai. Isso elimina o buffer de entrada e tee falha.

Aqui está uma versão em que awk não sai depois de encontrar a primeira linha. Vai continuar correndo (coisa boa ou não) sobre cada linha:

$ ps aux | tee >(awk 'NR==1' >&2) | grep "grep"
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
oli      15103  0.0  0.0  11752  2236 pts/18   S+   11:32   0:00 grep --color=auto grep

Outra alternativa é enviar a entrada para sponge . O Sponge absorve todo o fluxo de entrada antes de gravá-lo em um arquivo (ou ser redirecionado). Isso impede que a cabeça elimine o fluxo pai, mas significa que a entrada será invertida (o grep será a saída primeiro), então vamos passar por uma instância sponge também:

$ ps aux | tee >(sponge >(head -1 >&2)) | sponge >(grep "grep")
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
oli      14875  0.0  0.0  11752  2192 pts/18   S    11:19   0:00 grep --color=auto grep

Mas enquanto esses dois segundos funcionam, e você está gerando apenas ps aux de saída, eles ainda têm sérios problemas . O awk|grep está processando tudo duas vezes e o sponge orgy está armazenando tudo duas vezes.

tl; dr : Se você puder processar tudo em um comando como você pode com awk , por que você não faria isso?

    
por Oli 15.09.2015 / 16:38
8

Você pode dizer a ps para imprimir apenas os IDs de processo de vlc com -C .

De man ps :

   -C cmdlist
          Select by command name.  This selects the processes whose
          executable name is given in cmdlist.

Exemplo:

$ ps u -C vlc
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
sylvain  12586  0.1  0.3 1076848 60908 ?       Sl   20:10   0:00 /usr/bin/vlc
    
por Sylvain Pineau 15.09.2015 / 20:16
7

Use bash de substituição do processo e cat :

cat <(ps aux | head -1) <(ps aux | grep '[v]lc')

O padrão de substituição do processo <() substitui a saída do comando dentro dele como um arquivo. cat irá concatenar os arquivos como de costume.

Exemplo:

$ cat <(ps aux | head -1) <(ps aux | grep '[v]lc')
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
chayan   26031  2.3  0.4 1098532 38556 pts/31  Sl   20:45   0:00 vlc
    
por heemayl 15.09.2015 / 16:38
6

eu usaria

ps aux | grep -E '^USER|vlc'

você pode adicionar | grep -v grep para excluir a linha grep

    
por Wayne_Yux 15.09.2015 / 16:37
6

Diga apenas ps para mostrar apenas a saída para vlc :

$ ps -P $(pgrep vlc)
PID PSR TTY      STAT   TIME COMMAND
6728   2 pts/0    Sl     0:00 vlc

pgrep lista os PIDs de qualquer processo cujo nome corresponda ao padrão fornecido. A opção -P do ps permite listar informações somente para PIDs específicos. A combinação dos dois fornece o cabeçalho ps e somente as linhas de seu interesse.

    
por terdon 15.09.2015 / 17:01