Wie kann ich verhindern, dass "grep" in ps-Ergebnissen angezeigt wird?


304

Wenn ich nach einem Prozess suche, der nicht existiert, z

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

Grep interessiert mich natürlich nicht - das ist genauso sinnvoll wie die Suche nach dem psProzess!

Wie kann ich verhindern, dass grep in den Ergebnissen angezeigt wird?


28
Wenn Sie nur die PID eines Prozesses benötigen, können Sie ersetzen ps aux |grepmit pgrep(oder pgrep -f).
Jofel

6
Gleiche Frage zu Serverfault und Superuser .
Thor

Ist diese Ausgabe legitim? Es scheint, dass es kein Programm namens fnord gibt, das läuft ...
Akolyth

4
@acolyte, genau das ist es - aber weil es die Ausgabe in grep umleitet, läuft grep ( ps auxich erwarte das Warten auf die Ausgabe von ). Die Frage ist also , wie man verhindert , dass nicht grep fnordangezeigt werden , als ein laufenden Prozess , weil offensichtlich ich nicht interessiert bin , dass ein.
Wayne Werner

2
@acolyte Es ist keine Überraschung, dass Sie die "fnord" -Zeile nicht sehen können. Du sollst es nicht sehen können. Wenn Sie 2 oder 3 Minuten Zeit haben, suchen Sie danach.
Francesco

Antworten:


438

Es stellte sich heraus, dass es eine Lösung im Schlüsselbund gibt .

$ ps aux | grep "[f]nord"

Indem Sie die Klammern um den Buchstaben und die Anführungszeichen um die Zeichenfolge setzen, suchen Sie nach dem regulären Ausdruck, der lautet: "Suchen Sie das Zeichen 'f', gefolgt von 'nord'."

Da Sie jedoch die Klammern in das Muster 'f' gesetzt haben, folgt jetzt ']', sodass grepes nicht in der Ergebnisliste angezeigt wird. Neato!


26
@acolyte: Die Ausgabe von ps enthält eine Zeile, die mit endet grep [f]nord. Diese Zeile wird jedoch nicht über den grep-Filter eingehen, da die Zeichenfolge [f]nordnicht mit dem regulären Ausdruck übereinstimmt [f]nord.
LarsH

9
@ LarsH interessant, danke! ich hätte vorgeschlagen ps aux | grep fnord | grep -v grep... was anscheinend schon von ein paar Leuten vorgeschlagen wurde ... lol
acolyte

5
@progo Ja, Sie müssen das [Even in Bash zitieren . Probieren Sie es mit einer Datei aus, die fnordim aktuellen Verzeichnis aufgerufen wird .
Gilles

26
Das Greifen der Ausgabe von psist zwar ein alter Trick, aber unzuverlässig. Verwenden Sie,pgrep falls verfügbar.
Gilles

9
@naxa Stellen Sie sich vor, Sie haben einen Programmaufruf fnordund ein Programm namens safnorde. Oder es wird ein Benutzer angerufen bfnord, und Sie beenden alle seine Prozesse. Etc.
Gilles

165

Eine andere Option, die ich verwende (insbesondere, um zu sehen, ob ein Prozess ausgeführt wird), ist der pgrep Befehl. Dies sucht nach einem passenden Prozess, listet jedoch keine grep-Zeile für die Suche auf. Ich mag es, weil es eine schnelle Art der Suche ist, ohne regexen oder irgendetwas entgehen zu müssen.

pgrep fnord

8
Sie wollen, dass die -fOption mehr wird ps | grep.
Jordanm

@jordanm Eigentlich pgrep -fwird eher so aussehen ps -f | grep.
Michelpm

5
Es gibt auch das -lArgument, mit dem der übereinstimmende Befehl angezeigt werden soll.
Patrick

15
ps | grep '[f]nord'ist klug und ehrwürdig, aber pgrep ist richtig .
Kojiro

3
Sie können dies immer tun, ps $(pgrep cmd) ...wenn in `pgrep Optionen fehlen (dies funktioniert jedoch nicht für leere Befehlssätze).
Maciej Piechotka

63

Die ideale Lösung ist die von BriGuy vorgestellte

pgrep fnord 

Aber wenn Sie das nicht wollen, können Sie einfach alle Zeilen ausschließen, die mit grep mit übereinstimmen :

ps aux | grep -v grep | grep "fnord"

7
aber was ist, wenn die gesuchte Zeile "bash bash grep bash" ist?
Sparr

1
@Sparr Dann sollten Sie die beste Lösung verwenden: pgrepoder eine andere finden;)
RSFalcon7

Achten Sie mit pgrep auf die maximale Länge des Namens. Verwenden Sie -f, um den vollständigen Pfadnamen abzurufen, oder finden Sie heraus, dass Ihre Übereinstimmungen mit längeren Namen fehlschlagen. -l ist auch nett, um die Spiele
Neil McGill


24

Nicht die eleganteste Lösung, aber Sie könnten dies tun:

$ ps aux | grep fnord | grep -v grep


Es ist eine schlechte Antwort! Denn wenn es ein Wort grepin deiner Phrase gäbe . Dieser Vorgang wird nicht angezeigt. Angenommen, eine aufgerufene Datei foo_grep_bar.txtwird vom nanoBefehl bearbeitet . Es läuft also ein Prozess: root 14908 0.0 0.0 110012 1692 pts / 3 S + Oct31 0:00 nano foo_grep_bar.txtLaut dieser Antwort wird dies nicht funktionieren: $ ps aux | grep nano | grep -v grepWeil Ihr Dateiname ein Grep-Wort enthält.
Nabi KAZ

Ich bevorzuge dies, da es expliziter in Bezug auf seine Absicht ist als die akzeptierte Antwort und nur in einem Fall funktioniert.
Samaspin

1
wie pro superuser.com/a/409658/450260 sollten Sie den vollständigen Ausschluss sein grep fnordnicht nur das grepheißt $ ps aux | grep fnord | grep -v "grep fnord"
Davos


14

In zsh grep fnord =(ps aux).

Die Idee ist, zuerst ps auxdas Ergebnis in eine Datei zu schreiben und dann grepfür diese Datei zu verwenden. Nur haben wir keine Datei, da wir die "Prozessersetzung" von zsh verwenden.

Versuchen Sie es zur Veranschaulichung

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

Das Ergebnis sollte dasselbe sein.

Allgemeiner Kommentar zu einigen der anderen Antworten. Einige sind viel zu kompliziert und / oder lang zu tippen. Es ist nicht nur eine Frage der Richtigkeit, es sollte auch brauchbar sein. Dies bedeutet jedoch nicht, dass einige dieser Lösungen schlecht sind. Sie müssen nur in eine Mini-Benutzeroberfläche eingebunden werden, damit sie verwendet werden können.


1
Sie kennen die Prozesssubstitution von zsh nicht, aber ist es sicher, dass die beiden Prozesse nacheinander und nicht parallel aufgerufen werden?
Paŭlo Ebermann

3
@ PaŭloEbermann: Denn parallel ist das <(command). grep grep =(ps aux)zeigt keine Linie.
Maciej Piechotka

Zsh kann auch die Ausgabe von ps "angleichen". print -l ${(M)${(f)¨$(ps aux)¨}:#*fnord*}
Friartek

6
ps aux | grep $(echo fnord | sed "s/^\(.\)/[\1]/g")

3
Das sieht aus wie ein IOCCC, aber für Unix-Kommandozeile anstelle von C ^^ Einfach | grep $(echo fnord)nicht genug? Sie bitten sed auch, jedes Zeichen in "fnord" durch seinen eigenen Wert zu suchen und zu ersetzen? ^^ Glückwunsch. Ich wette, ich kann eine noch längere machen, aber es wird wahrscheinlich nicht so lustig sein ^^
Olivier Dulac

1
Ich entschuldige mich dafür, dass der Ton meines obigen Kommentars beleidigend klingt (und ich kann ihn nach 5 Minuten nicht mehr bearbeiten). Ihre Antwort war wirklich eine freudige Lektüre, und ich habe nicht versucht, Sie schlecht aussehen zu lassen. Ich denke wirklich, Sie haben es absichtlich so gemacht ^^
Olivier Dulac

1
Entschuldigen Sie sich nicht, Ihre Antwort hat wirklich Spaß gemacht (und stimmt auch). Ich meinte pgrep -l $ 1 sowieso;)
yPhil

3
@OlivierDulac: Er ersetzt nicht nur den ersten Buchstaben durch einen eigenen Wert. er ersetzt es durch die Verkettung seines Wertes in eckigen Klammern. (Diese eckigen Klammern sind nichts Besonderes, sie sind wörtlich.) Im Grunde verallgemeinert er Wayne Werners Antwort, so dass der Vorgang, eckige Klammern um das erste Zeichen zu setzen, skriptiert werden kann. +1
LarsH

2
ps aux | grep '[^]]fnord'würde diese Gymnastik vermeiden.
Stéphane Chazelas

6

Diese Antwort ist GNU-spezifisch . Siehe Waynes Antwort für eine allgemeinere Lösung.

Prozesse suchen

Wenn Sie nur nach fnordProzessen suchen , können Sie diese über den -CBefehlsnamen auswählen:

ps -C fnord

Dies kann mit BSD- und POSIX-ähnlichen Formatoptionen gemischt werden. Eine vollständige Liste finden Sie auf der ps-Manpage .

Auf der Suche nach etwas anderem?

Wenn Sie etwas Fortgeschritteneres als die exakte Suche nach einem Befehlsnamen benötigen, verlieren Sie nicht die Hoffnung! Dies kann immer noch an der psSeite des Rohrs erfolgen. Alles, was wir tun müssen, ist zu sagen ps, dass grepProzesse vom Ergebnis ausgeschlossen werden sollen:

ps -NC grep | grep 'fnord'

-C grepWählt alle grep-Prozesse aus und -Nnegiert die Auswahl. Dies kann verwendet werden, um nach Befehlsargumenten, Teilen eines Befehlsnamens oder komplexeren regulären Ausdrücken zu suchen.


1
Dies ist gut mit GNU ps, -Cwird aber nicht von POSIX spezifiziert und hat unter BSD eine völlig andere Bedeutung
Eric Renouf

Es ist wirklich ein Mist, dass es kein BSD-Äquivalent gibt (was auch bedeutet, dass es auf einem Mac nicht funktioniert). Die Verwendung von ps-C ist bei weitem die einfachste Antwort von allen.
Christopher Hunter

3

Meine Antwort ist eine Variation der typischen Antwort für die Suche nach "foobar" in einer "ps" -Auflistung. Ich glaube, das Argument "-A" "ps" ist portabler als "aux", aber diese Änderung ist für die Antwort irrelevant. Die typische Antwort sieht so aus:

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

Stattdessen benutze ich dieses Muster:

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

Der Hauptvorteil ist, dass es einfacher ist, Skripte basierend auf diesen Mustern zu schreiben, da Sie einfach eine statische Zeichenfolge "[^]]" mit dem gewünschten Muster verketten. Sie müssen den ersten Buchstaben der Zeichenfolge nicht abstreifen, ihn dann zwischen die eckigen Klammern einfügen und ihn dann wieder zusammenfügen. Wenn Sie Skripte in der Shell schreiben, ist es einfacher, "[^]]" vor das gesuchte Muster zu kleben. Das Aufschneiden von Saiten in Bash ist eine hässliche Sache, also vermeidet meine Variante das. Diese Variante besagt, dass die Linien angezeigt werden, in denen das Muster OHNE führende eckige Klammer stimmt. Da das Suchmuster zum Ausschließen einer eckigen Klammer tatsächlich die eckige Klammer zum Muster hinzufügt, entspricht es sich selbst nie.

Sie können also einen portablen Befehl 'psgrep' wie folgt schreiben. Hier berücksichtige ich einige Unterschiede zwischen Linux, OS X BSD und anderen. Dies fügt die Spaltenüberschriften von 'ps' hinzu, stellt ein benutzerdefinierteres 'ps'-Format bereit, das meinen Anforderungen entspricht, und zeigt Prozesse an, die eine zusätzliche Breite aufweisen, sodass keines der Befehlszeilenargumente übersehen wird. Nun, die meisten werden nicht vermisst. Da Java Java ist, werden die Dinge oft auf die schlimmste Art und Weise ausgeführt, sodass einige Java-Services über die maximal zulässige Länge von Argumenten ausgeführt werden, die in der Prozesstabelle aufgezeichnet werden. Ich glaube das sind 1024 Zeichen. Die befehlsübergreifende Länge, die zum Starten eines Prozesses zulässig ist, ist viel länger, aber die Kernel-Prozesstabelle kümmert sich nicht darum, etwas über 1 KB Länge zu verfolgen. Sobald der Befehl gestartet ist, sind der Befehlsname und die Argumentliste nicht mehr vorhanden.

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
}

2

Die einfachste Methode zur Shell-Agnostik besteht darin, sie zuerst in einer Variablen zu speichern:

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

Aufruf: @ EmanuelBergs grep fnord =(ps aux)Antwort ist bei weitem die eleganteste, obwohl es erfordert zsh. Ich hatte es kurz in meinen rc-Dateien, aber bash beschwert sich über diese Syntax, auch wenn eine Bedingung dies verhindern sollte.


Aus meinen rc-Dateien habe ich eine Version, bei der die Groß- und Kleinschreibung nicht berücksichtigt wird.

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, eine Kugel pro Codezeile:

  • Erfassen Sie die ausführliche psAusgabe (in einer localVariablen, damit sie verschwindet, wenn die Funktion zurückkehrt).
  • Zeigen Sie die erste Zeile (den Titel) in Standardfehlern an, damit die Ergebnisse weiter gefiltert werden können, ohne den Titel zu beeinflussen. Die Ersetzung lautet: $PS_OUTPUTAlles nach dem ersten Zeilenvorschub nehmen und entfernen (regex equiv:) s/\n.*$//msg. Dies hindert uns daran, den Titel zu begreifen
  • Zeigen Sie die psAusgabe mit allem außer der ersten Zeile an (regex equiv:) s/^.*\n//mund prüfen Sie deren Inhalt mit, -ium die Groß- und Kleinschreibung zu ignorieren und alle Argumente zu berücksichtigen, denen diese Funktion übergeben wurde (im Falle, dass keine Argumente vorhanden sind ^, die mit dem Anfang einer übereinstimmenden Zeile übereinstimmen) alles)

1

Hier ist eine erweiterte Version der grep -v grepLösung, in der alle grepProzesse herausgefiltert werden, die nicht länger als eine Sekunde ausgeführt wurden. Dies ist eine Verbesserung gegenüber "Verwerfen aller Vorkommen von grep".

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

beziehungsweise

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

Dies ist möglicherweise nicht portierbar und hängt vom tatsächlichen Ausgabeformat Ihres lokalen psBefehls ab.

Möglicherweise möchten Sie dies mit einer farbigen grepAusgabe kombinieren :

$ alias grep='grep --color=auto'

0

Vielleicht ist es diesmal an der Zeit, eine echte Sequenz zu verwenden. Die Verwendung von Rohren macht es parallel.

ps aux >f && grep tmpfs <f

Hässlich, weil es eine Datei geben wird f, aber es ist nicht meine Schuld, dass es keine Syntax für sequentielle Prozesse gibt, bei denen Sie immer noch die Ausgabe eines zuvor ausgeführten Prozesses verwenden möchten.

Vorschlag für die Syntax eines sequentiellen Operators:

ps aux ||| grep tmpfs

Die Unfähigkeit der einfachen Leute, einen Strom leicht zu filtern, ist kaum ein Grund für die Elite, sich auf Sequenzen zu stützen. Es wäre ein Rückschritt in der Datenverarbeitung.
Acumenus

@ABB en.wikipedia.org/wiki/Communicating_sequential_processes hat viel mehr Operatoren als diejenigen, die in der Thompson-Shell landeten. Es könnte nur einen Operator geben, der sequentiell ist und dessen Ergebnis dem nächsten Prozess in der Sequenz mitteilt, sobald er beendet wird. Ein "Rückschritt beim Rechnen" durch die Bereitstellung eines zusätzlichen Operators scheint etwas hart zu sein.
Anne van Rossum

Netter Link, aber die sequentielle Verarbeitung ist sowohl bei der CPU- als auch bei der Speicher- (oder Festplatten-) Nutzung schlechter als bei der parallelen Verarbeitung. Wenn ich in diesem Fall zuerst die gesamte psAusgabe speichern muss, bevor ich sie abspeichere grep, verwende ich länger mehr Speicher (oder eine Festplatte).
Acumenus

0

Der Befehl pgrep gibt, wie andere angegeben haben, die PID (Prozess-ID) von Prozessen basierend auf dem Namen und anderen Attributen zurück. Zum Beispiel,

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

gibt die PIDs an, die durch ein Komma (,) von allen Prozessen getrennt sind, deren Name mit der Ausführung durch den Benutzer übereinstimmt <username>. Sie können die Option -x zuvor verwenden, um nur exakte Übereinstimmungen zurückzugeben.

Wenn Sie weitere Informationen zu diesen Prozessen erhalten möchten (wie das Ausführen der Aux-Optionen von ps impliziert), können Sie die Option -p mit ps verwenden, die auf der Grundlage der PID übereinstimmt. So zum Beispiel

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

Gibt detaillierte Informationen zu allen PIDs aus, die mit dem Befehl pgrep übereinstimmen.


psschlägt fehl, wenn pgrepein leerer Satz zurückgegeben wird. Ich habe eine Antwort, die auf Ihrer aufbaut und versucht, dieses Problem anzugehen.
Acumenus

0

Hier ist ein einfaches Beispiel, um die PID ssh-agentfür den Benutzernamen zu finden, ohne die PID des grepProzesses selbst anzuzeigen :

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

Wenn Sie zum Beispiel ssh-agentfür den aktuellen Benutzer töten möchten, können Sie den folgenden Befehl verwenden:

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

Fügen Sie Ihrer ~ / .bashrc- oder ~ / .zshrc-Datei den folgenden Code hinzu, um einen praktischen Alias ​​zu erstellen:

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

Und um hier einen Alias ​​zu verwenden, sind Beispiele, mit denen jeder gezwungen wird, reguläre Ausdrücke zu lernen:

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

PS Ich habe diese Befehle nur unter Ubuntu und Gentoo getestet.


(1) Die Frage besagt nicht, dass der Benutzer nach einem seiner eigenen Prozesse sucht - der Benutzer kennt möglicherweise nicht den Eigentümer des Prozesses, den er sucht. (2) So ausgefallen diese Antwort auch ist, es würde immer noch scheitern, wenn Sie gesagt hätten "${USER}.* /usr/bin/ssh-agent". Es funktioniert, weil du gesagt hast [ ]; Sie verwenden also nur den Mechanismus der akzeptierten Antwort. Du könntest es genauso gut grep "[s]sh-agent".
G-Man

Du hast recht. (1) Ich teilte mit, was nützlich sein könnte, da ich gelegentlich auf diese Seite stieß. (2) Ja, ich habe reguläre Ausdrücke wie in der akzeptierten Antwort verwendet. (3) Ich habe meine Antwort so aktualisiert, dass sie mit der angenommenen übereinstimmt, da die Antwort besser ist, aber ich habe auch gezeigt, wie sie mit oder ohne Benutzernamen erstellt und als Alias ​​verwendet werden kann. (4) Auch gezeigt, wie man eine Funktion definiert, obwohl dies nicht notwendig ist, aber auf interessante Weise funktioniert, da sich $ 1 und $ 2 nicht überlappen. Thx # G-Man
Constantin Zagorsky

-2

Die Option -x (genaue Übereinstimmung) hat bei mir funktioniert. Ich habe es mit -f (vollständige Befehlszeile) kombiniert, damit ich meinen Prozess genau mit den folgenden Kriterien abgleichen kann:

pgrep -x -f "path_i_used_when_starting/cmd params_i_used"

Erklärt sich, wer auch immer das Drive-by-Downvoting durchführt? Dies hat jahrelang daran gearbeitet, dieses Problem für mich zu lösen.
Moodboom

-3

Sie können dies ganz einfach tun, indem Sie ein ALIAS .bashrc wie folgt definieren :

alias grep='grep -v grep | grep'

Ich bin mir nicht sicher, wer abstimmt oder warum, aber dies ermöglicht es Ihnen, ps vollständig zu nutzen, was pgrep nicht tut.
Opticyclic

1
Nicht nur, dass dies versehentlich andere grep-Prozesse ausschließt; es bricht auch die grepVerwendung in anderen Fällen. Versuchen Sie es echo I love grep | grep love.
Trosos

@trosos Fast 11 Jahre war ich * nix-ing .. und habe dieses Muster noch nie benutzt ... vielleicht nächstes Jahr aber - wer weiß, richtig.
a20
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.