Comment puis-je empêcher "grep" d'apparaître dans les résultats ps?

304

Lorsque je recherche un processus qui n'existe pas, par exemple

$ ps aux | grep fnord                          
wayne    15745  0.0  0.0  13580   928 pts/6    S+   03:58   0:00 grep fnord

De toute évidence, je me fiche de grep - cela a autant de sens que de chercher le psprocessus!

Comment puis-je empêcher que grep apparaisse dans les résultats?

Wayne Werner
la source
28
Si vous n'avez besoin que du PID d'un processus, vous pouvez le remplacer ps aux |greppar pgrep(ou pgrep -f).
Jofel
6
Même question sur Serverfault et Superuser .
Thor
cette sortie est-elle légitime? il semble qu'il n'y ait pas de programme nommé fnord en cours d'exécution ...
acolyte
4
@acolyte, c'est précisément cela - mais comme il redirige la sortie vers grep, grep est en cours d'exécution (en attente de la sortie de ps aux, je m'attends). La question est donc de savoir comment éviter grep fnordde s’afficher comme un processus en cours car je ne suis évidemment pas intéressé par celui- ci.
Wayne Werner
2
@ acolyte ce n'est pas une surprise que vous ne puissiez pas voir la ligne "fnord". Vous n'êtes pas censé pouvoir le voir. Si vous disposez de 2 ou 3 minutes, cherchez-le.
Francesco

Réponses:

438

Il s'avère qu'une solution a été trouvée dans le trousseau .

$ ps aux | grep "[f]nord"

En mettant les crochets autour de la lettre et les guillemets autour de la chaîne, vous recherchez l'expression régulière, qui dit: "Recherchez le caractère" f "suivi de" nord "."

Mais puisque vous mettez les crochets dans le motif 'f' est maintenant suivi de ']', grepne sera donc pas affiché dans la liste des résultats. Neato!

Wayne Werner
la source
26
@acolyte: La sortie de ps inclura une ligne se terminant par grep [f]nord. Cependant, cette ligne [f]nordn'interviendra pas via le filtre grep, car la chaîne ne correspond pas à l'expression régulière [f]nord.
LarsH
9
@LarsH intéressant, merci! j'aurais suggéré ps aux | grep fnord | grep -v grep... ce qui semble avoir déjà été suggéré par quelques personnes ... lol
acolyte
5
@progo Oui, vous devez citer le [même en bash. Essayez-le avec un fichier appelé fnorddans le répertoire en cours.
Gilles
26
Grepping le résultat de pspeut être un vieux truc, mais ce n’est pas fiable. Utilisezpgrep si disponible.
Gilles
9
@naxa Imaginez que vous avez un appel de programme fnordet un programme appelé safnorde. Ou il y a un utilisateur appelé bfnord, et vous finissez par tuer tous ses processus. Etc.
Gilles
165

Une autre option que j'utilise (en particulier pour vérifier si un processus est en cours d'exécution) est la pgrep commande. Cela recherchera un processus correspondant, mais ne listera pas une ligne grep pour la recherche. J'aime ça parce que c'est un moyen rapide de chercher, sans regexing ni échapper à rien.

pgrep fnord
BriGuy
la source
8
Ils voudront que l' -foption soit plus semblable ps | grep.
Jordanie
@jordanm En fait, pgrep -fressemblera plus ps -f | grep.
michelpm
5
Il y a aussi l' -largument pour faire apparaître la commande qui correspond.
Patrick
15
ps | grep '[f]nord'est intelligent et vénérable, mais pgrep a raison .
Kojiro
3
Vous pouvez toujours le faire ps $(pgrep cmd) ...si `pgrep manque d’options (cela ne fonctionnera pas pour un ensemble de commandes vide).
Maciej Piechotka
63

La solution idéale est celle présentée par BriGuy

pgrep fnord 

Mais si vous ne voulez pas faire cela, vous pouvez simplement exclure toutes les lignes qui correspondent à grep avec:

ps aux | grep -v grep | grep "fnord"
RSFalcon7
la source
7
mais que se passe-t-il si la ligne que je cherche est "bash bash grep bash"?
Sparr
1
@Sparr Ensuite, vous devriez utiliser la meilleure solution: pgrepou en trouver une autre;)
RSFalcon7
Surveillez la limite de longueur de nom avec pgrep. Utilisez -f pour obtenir le nom de chemin complet ou vous pourriez trouver que vos correspondances échouent avec des noms plus longs. -l est bien aussi de lister les matchs
Neil McGill
24

Ce n'est pas la solution la plus élégante mais vous pouvez le faire:

$ ps aux | grep fnord | grep -v grep

Brandon Kreisel
la source
C'est une mauvaise réponse! Parce que s'il y avait un mot grepdans votre phrase. Cela ne montrera pas ce processus. Par exemple, supposons qu'un fichier appelé foo_grep_bar.txtsoit en cours de modification par la nanocommande. Donc, il y a un processus en cours d'exécution: root 14908 0.0 0.0 110012 1692 pts / 3 S + Oct31 0:00 nano foo_grep_bar.txtselon cette réponse, cela ne fonctionnera pas: $ ps aux | grep nano | grep -v grepcar il y a un mot grep dans votre nom de fichier.
Nabi KAZ
Je préfère ceci car son intention est plus explicite que la réponse acceptée et fonctionne dans tous les cas sauf un.
samaspin
1
selon superuser.com/a/409658/450260 , vous devriez être hors pleinement grep fnordnon seulement à grepsavoir $ ps aux | grep fnord | grep -v "grep fnord"
Davos
14

En zsh, grep fnord =(ps aux).

L'idée est, tout d'abord ps aux, de placer le résultat dans un fichier, puis de l'utiliser grepsur ce fichier. Seulement, nous n'avons pas de fichier, car nous utilisons la "substitution de processus" de zsh.

Pour illustrer, essayez

ps aux > ps.txt
grep fnord ps.txt
rm ps.txt

Le résultat devrait être le même.

Commentaire général sur certaines des autres réponses. Certains sont trop compliqués et / ou longs à taper. Ce n’est pas seulement une question d’avoir raison, cela devrait aussi être utilisable. Mais cela ne signifie pas que certaines de ces solutions sont mauvaises; seulement, ils doivent être enveloppés dans une mini-interface utilisateur pour les rendre utilisables.

Emanuel Berg
la source
1
Ne sachant pas la substitution de processus de zsh, mais est-il certain que les deux processus s'appellent l'un après l'autre et non en parallèle?
Paŭlo Ebermann
3
@ PaŭloEbermann: Par parallèle, c'est le <(command). grep grep =(ps aux)ne montre aucune ligne.
Maciej Piechotka
Zsh peut également «correspondre» à la sortie de ps. print -l ${(M)${(f)¨$(ps aux)¨}:#*fnord*}
Friartek
6
ps aux | grep $(echo fnord | sed "s/^\(.\)/[\1]/g")
yPhil
la source
3
cela ressemble à un IOCCC, mais pour la ligne de commande unix au lieu de C ^^, cela | grep $(echo fnord)ne suffisait pas? vous demandez également à sed de rechercher et de remplacer chaque caractère dans "fnord" par sa propre valeur? ^^ félicitations. Je parie que je peux en faire encore plus, mais ce ne sera probablement pas aussi drôle ^^
Olivier Dulac
1
Je m'excuse car le ton de mon commentaire ci-dessus peut paraître offensant (et je ne peux pas le modifier après 5mn) ... Votre réponse était vraiment une lecture joyeuse, et je n'essayais pas de vous faire mal paraître. Je pense vraiment que tu l'as fait exprès ^^
Olivier Dulac
1
Ne vous excusez pas, votre réponse était vraiment amusante à lire (et à suivre aussi). Je voulais dire pgrep -l 1 $ quand même;)
yPhil
3
@OlivierDulac: Il ne remplace pas simplement le premier caractère avec sa propre valeur; il la remplace par la concaténation de sa valeur entre crochets. (Ces crochets ne sont pas spéciaux, ils sont littéraux.) Fondamentalement, il généralise la réponse de Wayne Werner, de sorte que le processus consistant à mettre des crochets autour du premier caractère puisse être scripté. +1
LarsH
2
ps aux | grep '[^]]fnord'éviterait cette gymnastique.
Stéphane Chazelas
6

Cette réponse est spécifique GNU . Voir la réponse de Wayne pour une solution plus générale.

Recherche de processus

Si vous recherchez uniquement des fnordprocessus, vous pouvez utiliser l' -Coption pour sélectionner par nom de commande:

ps -C fnord

Cela peut être mélangé avec les options de format de style BSD et POSIX à votre convenance. Voir la page de manuel ps pour une liste complète.

Vous cherchez autre chose?

Si vous avez besoin de quelque chose de plus avancé que la recherche exacte d'un nom de commande, ne perdez pas espoir! Cela peut encore être fait sur le pscôté du tuyau. Tout ce que nous avons à faire est de dire psd'exclure les grepprocessus du résultat:

ps -NC grep | grep 'fnord'

-C grepsélectionne tous les processus grep et -Nannule la sélection. Cela peut être utilisé pour rechercher des arguments de commande, une partie d'un nom de commande ou des expressions régulières plus complexes.

Morgan
la source
1
C’est bien avec GNU psmais -Cn’est pas spécifié par POSIX et a une signification complètement différente sous BSD
Eric Renouf
C'est vraiment dommage qu'il n'y ait pas d'équivalent BSD (ce qui signifie également que cela ne fonctionnera pas sur un mac). L'utilisation de psC est de loin la réponse la plus simple.
Christopher Hunter
3

Ma réponse est une variation de la réponse typique pour la recherche de "foobar" dans une liste "ps". L'argument de "-A" "ps" est plus portable que "aux", je crois, mais ce changement n'a aucune incidence sur la réponse. La réponse typique ressemble à ceci:

$ ps -A -ww | grep [f]oobar

Au lieu de cela, j'utilise ce modèle:

$ ps -A -ww | grep [^]]foobar

L'avantage principal est qu'il est plus facile d'écrire des scripts basés sur ces modèles, car vous concaténez simplement une chaîne statique "[^]]" avec le modèle que vous recherchez. Vous n'avez pas besoin de retirer la première lettre de la chaîne, de l'insérer entre les accolades puis de la concaténer à nouveau. Lors de la création de scripts dans un shell, il est plus simple de coller "[^]]" devant le motif recherché. Le tranchage de cordes dans Bash est une chose laide, ma variante l’évite donc. Cette variation indique de montrer les lignes où le motif correspond SANS un crochet de droite]. Etant donné que le modèle de recherche pour exclure un crochet ajoute le crochet au modèle, il ne se correspondra jamais.

Ainsi, vous pourriez écrire une commande 'psgrep' portable comme suit. Ici, je tiens compte des différences entre Linux, OS X BSD et d’autres. Cela ajoute les en-têtes de colonne à partir de 'ps', fournit un format 'ps' plus personnalisé qui convient mieux à mes besoins et affiche les processus listant extra, extra wide afin qu'aucun des arguments de ligne de commande ne manque. Eh bien, la plupart ne sont pas manqués. Java étant Java, il fait souvent les choses de la pire façon possible, de sorte que certains services java fonctionneront au-delà de la longueur maximale autorisée des arguments que la table de processus va suivre. Je crois que c'est 1024 caractères. La longueur autorisée par commande permettant de démarrer un processus est beaucoup plus longue, mais la table des processus du noyau ne prend pas la peine de garder trace de tout ce qui dépasse 1K. Une fois la commande lancée, le nom de la commande et la liste des arguments isn '

psgrep ()
{
    pattern=[^]]${1};
    case "$(uname -s)" in
        Darwin)
            ps -A -ww -o pid,ppid,nice,pri,pcpu,pmem,etime,user,wchan,stat,command | grep -i -e "^[[:space:]]*PID" -e ${pattern}
        ;;
        Linux)
            ps -A -ww -o pid,ppid,tid,nice,pri,pcpu,pmem,etime,user,wchan:20,stat,command | grep -i -e "^[[:space:]]*PID" -e ${pattern}
        ;;
        *)  # other UNIX flavors get a minimalist version.
            ps -A -ww | grep -i -e ${pattern}
        ;;
    esac
}
Noah Spurrier
la source
2

La manière la plus simple, agnostique vis-à-vis du shell, serait de le stocker dans une variable:

PS_OUTPUT="$(ps aux)"; echo "$PS_OUTPUT" |grep fnord

Call-out: @ La grep fnord =(ps aux)réponse d'EmanuelBerg est de loin la plus élégante, bien qu'elle soit nécessaire zsh. Je l'ai brièvement eu dans mes fichiers rc, mais bash se plaint de cette syntaxe même malgré une condition qui empêcherait son évaluation.


De mes fichiers rc, j'ai une version non sensible à la casse qui prend l'argument de grep:

psl() {
  local PS_OUTPUT="$(ps auxww)"
  echo "${PS_OUTPUT%%$'\n'*}" >&2  # title, in stderr to avoid pipes
  echo "${PS_OUTPUT#*$'\n'}" |grep -i "${@:-^}"
}

Code walk, une balle par ligne de code:

  • Capturez la pssortie commentée (dans une localvariable afin qu'elle disparaisse lorsque la fonction retourne)
  • Affiche la première ligne (le titre) en erreur standard afin que les résultats puissent être filtrés sans affecter le titre. La substitution dit: prenez $PS_OUTPUTet supprimez tout après le premier saut de ligne (regex equiv:) s/\n.*$//msg. Cela nous empêche de grepper le titre
  • Afficher la pssortie avec tout sauf la première ligne (regex equiv:) s/^.*\n//met grep son contenu avec -ipour insensible à la casse et avec tous les arguments transmis cette fonction (dans le cas d'aucun argument ^, qui correspond au début de toute ligne tout)
Adam Katz
la source
1

Voici une version étendue de la grep -v grepsolution, filtrant tous les grepprocessus qui n'exécutent pas depuis plus d'une seconde, ce qui constitue une amélioration par rapport à "supprime simplement toutes les occurrences de grep".

$ ps -ef | grep -vw "00:00:00 grep" | grep <searchTerm>

respectivement

$ ps aux | grep -vw "0:00 grep" | grep <searchTerm>

Cela peut ne pas être portable et dépend du format de sortie réel de votre pscommande locale .

Vous voudrez peut-être combiner cela avec une grepsortie colorée pour plus de commodité:

$ alias grep='grep --color=auto'
Murphy
la source
0

Peut-être le temps d'utiliser une vraie séquence cette fois. L'utilisation de tuyaux le rend parallèle.

ps aux >f && grep tmpfs <f

C'est moche, car il y aura un fichier f, mais ce n'est pas de ma faute s'il n'y a pas de syntaxe pour les processus séquentiels pour lesquels vous souhaitez toujours utiliser le résultat d'un processus exécuté précédemment.

Suggestion pour la syntaxe d'un opérateur séquentiel:

ps aux ||| grep tmpfs
Anne van Rossum
la source
L'incapacité des gens du peuple à filtrer facilement un flux n'est pas une raison pour que l'élite se base sur des séquences. Ce serait un pas en arrière en informatique.
Acumenus
@ABB en.wikipedia.org/wiki/Communicating_sequential_processes ont beaucoup plus d'opérateurs que ceux qui se sont retrouvés dans le shell Thompson. Il se peut qu’il n’y ait qu’un opérateur séquentiel qui communique son résultat au processus suivant de la séquence dès sa sortie. Un "retour en arrière dans l'informatique" en fournissant un opérateur supplémentaire semble un peu dur.
Anne van Rossum
Un bon lien, mais bien sûr, le traitement séquentiel est pire en utilisation CPU et mémoire (ou disque) - par rapport au traitement parallèle. Dans ce cas, si je dois d'abord stocker toutes les pssorties avant moi grep, j'utilise plus de mémoire (ou de disque) plus longtemps.
Acumenus
0

Comme d'autres l'ont indiqué, la commande pgrep renverra le PID (ID de processus) des processus en fonction du nom et d'autres attributs. Par exemple,

pgrep -d, -u <username> <string>

vous donnera les PID, délimités par une virgule (,) de tous les processus dont les noms correspondent exécutés par l'utilisateur <username>. Vous pouvez utiliser le commutateur -x avant pour ne renvoyer que des correspondances exactes.

Si vous souhaitez obtenir plus d'informations sur ces processus (comme le fait d'exécuter les options aux depuis ps implique), vous pouvez utiliser l'option -p avec ps, qui correspond au PID. Donc, par exemple,

ps up $(pgrep -d, -u <username> <string>)

donnera des informations détaillées sur tous les PID associés à la commande pgrep.

eToThePiIPower
la source
pséchoue si pgrepretourne un ensemble vide. J'ai une réponse qui s'appuie sur la vôtre et tente de résoudre ce problème.
Acumenus
0

Voici un exemple simple pour trouver le PID de ssh-agentnom d'utilisateur sans afficher le PID du grepprocessus lui-même:

ps xu | grep "${USER}.*[ ]/usr/bin/ssh-agent" | awk '{print $1 $2;}'

Si vous voulez par exemple tuer ssh-agentpour l'utilisateur actuel, vous pouvez utiliser la commande suivante:

kill `ps xu | grep "${USER}.*[ ]/usr/bin/ssh-agent" | awk '{print $2;}'`

Pour créer un alias pratique, ajoutez à votre fichier ~ / .bashrc ou ~ / .zshrc le code suivant:

function function1 () {
    ps xu | grep "$1.*$2" | awk '{print $1" "$2" "$11;}'
}
alias mygrep="function1"

Et pour utiliser alias, voici des exemples pour forcer tout le monde à apprendre les expressions régulières:

. /etc/profile #to make alias usable
mygrep ${USER} ${PROCESS_PATH}
mygrep ${USER} "[f]nord"
mygrep "[f]nord"
mygrep ".*[s]shd"

PS Je n’ai testé ces commandes que sur Ubuntu et Gentoo.

Constantin Zagorsky
la source
(1) La question ne dit pas que l'utilisateur recherche l'un de ses propres processus - il se peut qu'il ne connaisse pas le propriétaire du processus qu'il recherche. (2) Aussi sophistiquée soit-elle, elle échouerait quand même si vous l'aviez dit "${USER}.* /usr/bin/ssh-agent". Cela fonctionne parce que vous avez dit [ ]; vous utilisez simplement le mécanisme de la réponse acceptée. Vous pourriez aussi bien juste grep "[s]sh-agent".
G-Man
Tu as raison. (1) J'ai partagé ce qui pourrait être utile car je me suis retrouvé face à cette page de temps en temps (2) Oui, j'ai utilisé l'expression régulière comme dans la réponse acceptée. (3) J'ai mis à jour ma réponse pour qu'elle soit la même que celle acceptée, celle-ci étant meilleure, mais j'ai également montré comment créer un alias avec un nom d'utilisateur fourni ou non. (4) Également montré comment définir une fonction, bien que cela ne soit pas nécessaire, mais fonctionne de manière intéressante car $ 1 et $ 2 ne se chevauchent pas. Thx # G-Man
Constantin Zagorsky
-2

L'utilisation de l'option -x (correspondance exacte) a fonctionné pour moi. Je l'ai combiné avec -f (ligne de commande complète) afin de pouvoir assortir mon processus précisément avec:

pgrep -x -f "path_i_used_when_starting/cmd params_i_used"
moodboom
la source
Est-ce que les personnes qui votent à la va-vite, en passant, vont-elles s'expliquer? Cela a fonctionné pour résoudre ce problème pour moi sans échec pendant des années.
moodboom
-3

Vous pouvez le faire facilement, simplement en définissant un ALIAS dans votre .bashrc genre:

alias grep='grep -v grep | grep'
Keivan Beigi
la source
Vous ne savez pas qui a voté à la baisse ni pourquoi, mais cela vous permet d'utiliser pleinement ps, contrairement à pgrep.
optique
1
Non seulement cela exclut par inadvertance d'autres processus grep; cela rompt également l' greputilisation dans d'autres cas. Essayez echo I love grep | grep love.
Trosos
@trosos Presque 11 ans que je suis * nix-ing ... et que je n'ai jamais utilisé ce modèle ... peut-être l'année prochaine - qui sait.
a20