Como obtenho o valor de uma opção nomeada de um processo já em execução no Linux?

3

Eu corro o seguinte comando.

ps -e -o args | grep destiny | grep UNIX

Eu recebo a seguinte saída.

/path/to/destiny -r -m UNIX -t TCP -p 1501

Qual comando posso usar para obter o valor dos argumentos impressos (por exemplo, -m ou -t ou -p )? Eu gostaria de alcançar o seguinte.

ps -e -o args | grep destiny | grep UNIX | <someCommand> -p , isso deve imprimir 1501

ps -e -o args | grep destiny | grep UNIX | <someCommand> -m , isso deve imprimir UNIX

ps -e -o args | grep destiny | grep UNIX | <someCommand> -t , isso deve imprimir TCP

Observe que -p , -m ou -t podem alternar colunas, portanto, imprimir com awk e escolher coluna por número não é uma opção.

Mais alguns fatos para que a análise fique mais fácil (eu sei que é possível que eu não tenha o conhecimento de ferramentas).

  • se uma opção não estiver presente, uma string vazia será retornada
  • as opções que serão analisadas sempre terão um argumento / valor nesse caso específico
por Tony Stark 02.06.2015 / 17:08

4 respostas

2

Que tal usar sed :

ps -e -o args | grep -e 'destiny.*UNIX' | sed -e 's/.*-t\s\([A-Z0-9]*\).*//'
ps -e -o args | grep -e 'destiny.*UNIX' | sed -e 's/.*-p\s\([A-Z0-9]*\).*//'
ps -e -o args | grep -e 'destiny.*UNIX' | sed -e 's/.*-m\s\([A-Z0-9]*\).*//'

sed -e 's/.*-t\s\([A-Z0-9]*\).*//'

  • s / search for / replace with / options
  • s é pesquisar.
  • . * corresponde a qualquer / todos os caracteres até chegarmos ao "-t".
  • \ s corresponde a qualquer espaço em branco.
  • (começa uma captura.
  • [A-Z0-9] * corresponde a qualquer letra maiúscula e qualquer número de qualquer tamanho.
  • ) termina a captura.
  • . * corresponde ao restante dos caracteres na linha (se houver algum).
  • \ 1 substitui tudo pela captura.
por 02.06.2015 / 17:33
5

Isso não é possível em geral porque somente o comando em si sabe como analisar seus próprios argumentos. Tomando seu exemplo:

/path/to/destiny -r -m UNIX -t TCP -p 1501

-p pode ser uma opção que não aceita argumentos (como um booleano: ativa ou desativa alguns comportamentos), nesse caso 1501 seria um argumento posicional (como um nome de arquivo ou algo assim). Ou -p pode ser uma opção que aceita um argumento e seu argumento é 1501 . Não há como saber qual é!

O vetor argumento é apenas uma lista de zero ou mais strings. Não há nenhum significado anexado àquelas strings indicando quais são as opções, quais são argumentos para essas opções, e quais são argumentos não-opcionais.

Mesmo a opção -r no seu exemplo não pode ser analisada genericamente com certeza. Dado que -r é seguido imediatamente por outra string que começa com - , é muito provável que -r seja uma opção que não aceita argumentos (como um booleano que ativa ou desativa algum comportamento), mas na verdade isso não é 100% certo . -r poderia ser uma opção que aceita um argumento e -m seria seu argumento. Ou o comando pode não seguir as convenções normais do UNIX, e -r não é uma opção!

    
por 02.06.2015 / 17:17
2

Você pode usar grep :

~$ echo "/path/to/destiny -r -m UNIX -t TCP -p 1501" | grep -oP -- '-t \K[^ ]+'
TCP
~$ echo "/path/to/destiny -r -m UNIX -t TCP -p 1501" | grep -oP -- '-p \K[^ ]+'
1501

(você pode / quer usar coisas como \s em vez de um espaço: grep -oP -- '-p\s\K[^\s]+' )

O -o significa "imprimir apenas a correspondência", o \K redefinirá o início.

Observe que isso tratará apenas de casos simples (consulte a resposta da Celada sobre o motivo).

Outra maneira de usar o look-behind:

grep -oP -- '(?<=-p )[^ ]+'
    
por 02.06.2015 / 17:21
1

Aqui está um one-liner de python. (Eu estou usando python porque perl e awk não tem uma maneira simples de obter a posição de um valor em uma lista).

ps -eo args | grep '/path/to/destiny' | 
     python -c 'x=input().split(); print(x[ x.index("-p")+1 ])'

Funcionará, desde que os argumentos que você está tentando extrair não contenham espaços.

    
por 02.06.2015 / 17:56