Como alinhar uma tabela de exibição bem

4

Estou tentando criar um script que funcione como um comando ps com suas próprias propriedades que desejo exibir. Digamos que é assim que os processos se pareceriam no comando ps:

sas 24431     1  0 Oct10 ?        00:51:08 /usr/lib/jvm/java-1.7.0-oracle-1.7.0.25.x86_64/jre/bin/java -Denv=DEV -Dapp.name=myApp -Xms512m -Xmx1g -Dlog.dir=/apps/java/logs

Eu quero mostrar como abaixo:

UID  PID    APPNAME
sas  24431  -Dapp.name=myApp
sas  24432  -Dapp.name=myApp2
sas  24433  -Dapp.name=myApp3

Nota: a propriedade app.name é um argumento de comando que é extraído do comando ps

Este é o meu script:

echo -e "PID\tUSERID\t\tAPPNAME"
ps -u $USER -f |grep "java"|grep -v "grep"|
while read LINE 
do 
  #Get pid from the line
  PID=$(cut -d" " -f2 <<< $LINE);
  #Get parameter value called "-Dapp.name or -DprojectName" 
  #from the ps command for the process
  APPNAME=$(ps -f $PID | awk 'BEGIN {RS=" "}; /-Dapp.name|-DprojectName/');
  USERID=$(cut -d" " -f1 <<< $LINE);

 echo -e $PID"\t"$USERID"\t"$APPNAME;
done;

Agora funciona da maneira que eu quero. Mas às vezes o alinhamento se ferrou. Além disso, esse script pode ser otimizado em um comando de linha?

Qualquer ajuda seria apreciada.

    
por Sas 18.10.2014 / 22:40

3 respostas

3

Also can this script be optimized into one line command?

Eu consideraria usar a opção -o do comando ps para produzir (na medida do possível) apenas os campos de interesse e, em seguida, pós-processamento para corresponder aos argumentos java e ao comando específico (s) que você precisa - algo como

ps -u $USER -o uname=,pid=,args= | 
  gawk -vOFS='\t' '/java/ {print $1,$2,substr($0,match($0,"-D(app[.]name)|(projectName)[^[:space:]]*"),RLENGTH)}'

ou talvez algo assim em perl ( DISCLAIMER: meu conhecimento em perl é incompleto )

ps -u $USER -o uname=,pid=,args= | 
  perl -anle 'print join "\t", @F[0], @F[1], grep /-D(app[.]name)|(projectName)/,@F if /java/'
    
por 18.10.2014 / 23:59
8

Para alinhamento tabular de propósito geral, você quer o utilitário column .

Por exemplo:

(
 printf 'PID\tUSER\tAPPNAME\n'
 printf '%s\t%s\t%s\n' "1" "john" "foo bar"
 printf '%s\t%s\t%s\n' "12345678" "someone_with_a_long_name" "pop tart"
) | column -t -s $'\t'

Resultados em:

PID       USER                      APPNAME
1         john                      foo bar
12345678  someone_with_a_long_name  pop tart
    
por 19.10.2014 / 01:20
2

Aqui está outro usando a formatação de saída de ps :

#!/usr/bin/sh -f
printf '%-8.7s%-8s%s\n' $(
     ps -o uname=UID,pid=PID,args=APPNAME | 
     sed -n '1p;s/\( [0-9]* \).*\(-Dapp.name=[^ ]*\).*//p'
)

Com base em sua string de formato, para cada 3 de seus argumentos printf será impresso:

  1. O primeiro espaço é preenchido à direita para uma largura de tabulação padrão de 8 caracteres e truncado para um máximo de 7 caracteres.
  2. O segundo espaço é preenchido à direita para uma largura de tabulação padrão de 8 caracteres.
  3. E depois o terceiro seguido por um \n ewline.

A substituição do comando não é citada de propósito . Observe o -f que segue sh na linha bang - especifica que o shell não deve glob -, portanto, não há perigo de gerar aleatoriamente nomes de arquivo baseados em caracteres especiais do shell. A substituição do comando será dividida em $IFS defaults - space, tab, newline.

Na substituição do comando, ps imprime três colunas - com UID , PID e APPNAME . ps é não especificado pelo POSIX para imprimir qualquer espaço em qualquer campo exceto o campo args= . Portanto, as duas primeiras colunas são $IFS safe. Ainda assim, para obter a string -Dapp.name do campo args= , ela deve ser processada.

Então sed filtra. Em linhas contendo pelo menos dois espaços e a string -Dapp.name = é impressa:

  1. A primeira sequência de um espaço, então zero ou mais números, depois um espaço e tudo o que o precede ...
  2. A última sequência que ocorre contendo a string -Dapp.name = seguida por todos os caracteres antes do próximo espaço.
As substituições de

sed não afetam os títulos das colunas - impressas com 1p - porque não contêm a string -Dapp.name = . Todas as outras linhas são excluídas da saída.

Depois de aplicar a saída de printf a sed em $IFS , você pode esperar uma saída como a seguinte:

UID     PID     APPNAME
sas     24431   -Dapp.name=myApp
sas     24431   -Dapp.name=myApp
sas     24431   -Dapp.name=myApp
sas     24431   -Dapp.name=myApp
sas     24431   -Dapp.name=myApp

Na minha opinião, porém, essa declaração sed funcionaria um pouco melhor:

sed -n '1p;s/\( [0-9]* \).*-Dapp.name=\([^ ]*\).*//p'

É basicamente o mesmo, exceto que retira a parte -Dapp.name = de para que seja impressa como ...

UID     PID     APPNAME
sas     24431   myApp
sas     24431   myApp
sas     24431   myApp

Porque, como é apenas a impressão de linhas que contêm a sequência -Dapp.name = , inclusive é uma espécie de confusão que pode ser considerada como certa.

    
por 19.10.2014 / 02:28

Tags