Comment extraire une paire clé-valeur de la commande ps

10

J'essaie d'extraire le nom de l'application à partir d'une pscommande comme celle-ci:

ps -af -u sas |grep "java"| grep -v "grep"

et il produit ce qui suit:

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

J'ai essayé d'utiliser egrepmais ne semble pas fonctionner:

ps -af -u sas|grep "java"| grep -v "grep"| egrep -o "-Dapp.name"

Comment puis-je obtenir uniquement la -Dapp.namevaleur "myApp"?

Sas
la source
si le grepmotif commence par -, vous devez le mettre après l' -eoption. Sinon, il sera traité comme une option. Mais cela correspondra simplement au mot -Dapp.name, pas à la partie qui le suit.
Barmar
alternativement:grep -o -- -Dapp.name
strugee
vous pouvez utiliser grep [j]avapour éviter la commande grep -v "grep"(testé sur bash)
HVNSweeting

Réponses:

7

Avec awk:

ps -af -u sas | awk 'BEGIN {RS=" "}; /-Dapp.name/'
jasonwryan
la source
8

Vous n'affichez pas le message d'erreur que vous obtenez, mais il est probablement

grep: méthode des périphériques inconnus

C'est parce que, comme tous ou au moins la plupart des autres programmes de ligne de commande, grepsuppose que tout ce qui commence par un -est une option et essaie de l'analyser en tant que tel. Dans ce cas, -Dest utilisé pour indiquer grepcomment traiter un fichier de périphérique (voir man greppour plus de détails). Une façon de contourner ce problème consiste à utiliser --ce qui indique grepque tout ce qui suit n'est pas un indicateur d'option.

En combinant cela avec la capacité PCRE de GNU grep, vous pouvez faire:

ps -af -u sas | grep -v grep | grep -Po -- '*-\KDapp.name=[^\s]+'

L'expression régulière recherche un -et le supprime ( \K), puis la chaîne Dapp.name=suivie du plus grand nombre de caractères non espace possible. La sortie est:

Dapp.name=myApp

Si vous voulez que la myApppartie soit enregistrée dans une variable, je rechercherais cela seul:

ps -af -u sas | grep -v grep | grep -Po -- '-Dapp.name=\K[^\s]+'

Pour l'affecter à une variable:

$ app="$(ps -af -u sas | grep -v grep | grep -Po -- '-Dapp.name=\K[^\s]+')"
$ echo $app
myApp

Cependant, vous ne devriez jamais grepproduire de sortie pspour ce genre de chose, c'est pour ça pgrep:

app="$(pgrep -a java | grep -Po -- '^Dapp.name=\K[^\s]+')"
terdon
la source
4
ps -af -u sas | sed -n '/[j]ava/s/.*-Dapp\.name=\([^ ]*\).*/\1/p'
Barmar
la source
3

Chaque fois que vous utilisez ps … | grep …et devez exclure grep des résultats, vous vous trompez.

La règle zéro pour analyser la sortie de psest d'utiliser des outils plus fiables, comme pgreps'ils étaient disponibles. Si vous avez pgrep, pgrep -f javarépertorie tous les processus exécutant la commande java. L'option -lajoute la ligne de commande pour chaque processus.

Pour extraire l'argument de -Dapp.name, vous pouvez utiliser sed. Faites correspondre la ligne entière, arrangez pour remplir la partie intéressante dans un groupe et imprimez ce groupe.

pgrep -lf java | sed -n 's/^.*-Dapp\.name=\([^ ]*\).*$/\1/p'

La première règle d'analyse de la sortie de psconsiste à utiliser l'option -opour sélectionner les champs dont vous avez besoin. Ici, vous n'êtes intéressé que par les arguments de la commande, alors n'imprimez que cela.

ps -e -o args= | sed -n 's/^.*-Dapp\.name=\([^ ]*\).*$/\1/p'
Gilles 'SO- arrête d'être méchant'
la source
3

Plus compliqué que les autres réponses, mais cela permet getoptde gérer l'analyse pour vous. Encore une autre alternative.

getopt -aql 'Dapp.name:' $(\
    ps -af -u sas | grep java | grep -v grep | tr -s ' ' | cut -d' ' -f8-\
) | cut -d"'" -f2
  1. votre commande: ps -af -u sas | grep java | grep -v grep
  2. tr -s ' ' "comprime" plusieurs espaces en un seul espace en préparation de cut
  3. cut -d' ' -f8- divise la ligne par des espaces et saisit tous les champs après 8 inclus, le résultat est /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
  4. getopts -aql 'Dapp.name:' $(...)analyse les options de commande et affiche uniquement le nom long qui correspond à Dapp.namequi a une valeur (indiquée par le :), le résultat est--Dapp.name 'myApp' --
  5. cut -d"'" -f2 attrape le truc dans les guillemets simples
  6. Le résultat est: myApp
zamnuts
la source
0

J'utiliserais pgrepau lieu de pscomme ça:

$ pgrep -fa java | grep -op "(<=-Dapp.name=)\w+"

Cela renverra tous les processus qui correspondent java, puis filtrera ceux qui ne montreront que ceux qui en contiennent -Dapp.name=. Le dernier bit \w+affichera le nom du programme, en supposant qu'il ne contient aucun espace.

REMARQUE: le -Pcommutateur vers greppermet de spécifier des éléments à l'aide d' expressions régulières compatibles PCRE - Perl . Toutes les versions ne le grepprennent pas en charge, mais la plupart le font avec des versions plus modernes de Linux.

Si vous voulez la sortie clé / valeur entière, changez les choses comme ceci:

$ pgrep -fa java | grep -oP -- "-Dapp.name=\w+"
slm
la source