Apara dinamicamente a largura da linha stdout no Bash

9

Ultimamente, tenho feito experiências com o comando ps e, às vezes, os caminhos longos encapsulam a próxima linha (ou dois) e dificultam a leitura. Eu quero canalizar a saída ps para outro programa para limitar a saída para x de caracteres.

Aqui está o que eu tenho até agora, mas não funciona muito bem:

ps aux | cut -c1-$(stty size | cut -d' ' -f2)

$(stty size | cut -d' ' -f2) é avaliado como 167, mas não parece ser uma entrada válida para cut .

Existe uma maneira de fazer esse tipo de sintaxe funcionar no bash?

    
por lentils 18.04.2014 / 06:16

3 respostas

4

Os seguintes trabalhos:

ps aux | cut -c1-$(stty size </dev/tty | cut -d' ' -f2)

Isso também funciona:

v=$(stty size | cut -d' ' -f2) ; ps aux | cut -c1-$v

O problema parece ser que stty precisa ter o tty em sua entrada padrão para funcionar. As duas abordagens acima resolvem isso.

Ainda há outra opção. Enquanto stdin e stdout de stty são ambos redirecionados nos comandos acima, seu stderr não é: ele ainda aponta para um terminal. Estranhamente, stty também funcionará se for dado stderr como sua entrada:

ps aux | cut -c1-$(stty size <&2 | cut -d' ' -f2)
    
por 18.04.2014 / 06:33
7

Algumas conchas como zsh , bash ou mksh definem automaticamente a variável $COLUMNS para a largura do terminal, portanto, você não precisa invocar stty aqui.

Todas as implementações de ps tentei suportar que a sintaxe não padrão (tipo BSD) consulta a largura do terminal por si só. Estou surpreso que o seu não. Eu espero que ele olhe para o conteúdo da variável COLUMNS ambiente .

Então você poderia fazer:

export COLUMNS; ps aux

Se não,

ps aux | cut -c"1-$COLUMNS"

Você também pode dizer ao seu terminal para não quebrar linhas:

tput rmam
ps aux
    
por 18.04.2014 / 08:06
3

Você também pode lidar com ps output um pouco melhor.

ps --width ${n:-$COLUMNS} ${opts} #set ps terminal width

ps -ww ${opts} #no word wrap

ps -o ${only_interesting_output} ${opts} #trim output

Isso dirá ps para analisar sua saída conforme suas especificações, conforme necessário.

Claro, se você não quebra a palavra, você tem o problema de perder informações. Você realmente precisa de tudo isso para todos os processos? Abra-o em um pager, se assim for:

ps ww ${opts} | $PAGER

Se não, especifique o que você deseja ver:

ps -o args= -p $pid

Como alternativa, você pode informar explicitamente ps do seu terminal --width :

man ps

...

w Wide output. Use this option twice for unlimited width.

-w Wide output. Use this option twice for unlimited width.

--width n Set screen width.

A coisa --width funciona exatamente com as especificações solicitadas sem a necessidade de envolver filtros adicionais ou processos auxiliares (o que provavelmente sobrecarregará ainda mais sua -aux de saída). E com $COLUMNS como mostrado acima e como Stephane aponta, ele vai até funcionar dinamicamente.

Provavelmente, é interessante notar que muitas vezes as pessoas tentam adicionar esse tipo de filtro desnecessário para acomodar um filtro |pipe através de outro para analisar a saída, o que também é bastante provável ser desnecessário. É claro que, por pessoas , eu quero dizer mim.

O operando -o utput que mencionei acima permite que você filtre quais colunas ps exibem, e quando você adiciona o = assigment, você pode até nomear a coluna como quiser. Eu deixo a atribuição vazia e entrego a ela um destino -p rocess $pid , então a única saída de ps é o nome do comando $pid e seu args na invocação. E -o apenas arranha a superfície de como você pode definir o que ps irá ou não exibir. Essa é a direção que eu recomendaria que você fizesse, especialmente por meio de:

man ps

... 

To see every process on the system using BSD syntax:

ps ax

ps axu

     

Para imprimir uma árvore de processos:

     

ps -ejH

ps axjf

     

Para obter informações sobre tópicos:

     

ps -eLf

ps axms

     

Para obter informações de segurança:

     

ps -eo euser,ruser,suser,fuser,f,comm,label

ps axZ

ps -eM

     

Para ver todos os processos em execução como raiz (ID real e efetiva) no formato do usuário:

     

ps -U root -u root u

     

Para ver todos os processos com um formato definido pelo usuário:

     

ps -eo pid,tid,class,rtprio,ni,pri,psr,pcpu,stat,wchan:14,comm

ps axo stat,euid,ruid,tty,tpgid,sess,pgrp,ppid,pid,pcpu,comm

ps -Ao pid,tt,user,fname,tmout,f,wchan

     

Imprimir apenas os IDs do processo do syslogd:

     

ps -C syslogd -o pid=

     

Imprimir apenas o nome do PID 42:

     

ps -p 42 -o comm=

    
por 18.04.2014 / 08:50