Come posso impedire a "grep" di apparire nei risultati ps?


304

Quando cerco un processo che non esiste, ad es

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

Ovviamente non mi importa di grep - ha senso tanto quanto cercare il psprocesso!

Come posso evitare che grep compaia nei risultati?


28
Se è necessario solo il PID di un processo, è possibile sostituirlo ps aux |grepcon pgrep(o pgrep -f).
jofel

6
Stessa domanda su Serverfault e Superuser .
Thor,

quell'output è legittimo? sembra che non ci sia nessun programma chiamato fnord in esecuzione ...
accolito il

4
@acolyte, è esattamente così - ma poiché sta eseguendo il piping dell'output in grep, grep è in esecuzione (in attesa dell'output di ps aux, mi aspetto). Quindi la domanda è: come evitare grep fnorddi apparire come un processo in esecuzione, perché ovviamente non sono interessato a quello .
Wayne Werner,

2
@acolyte non è una sorpresa che non riesci a vedere la linea "fnord". Non dovresti essere in grado di vederlo. Se hai 2 o 3 minuti da perdere, cercalo.
Francesco,

Risposte:


438

Si scopre che c'è una soluzione trovata nel portachiavi .

$ ps aux | grep "[f]nord"

Mettendo le parentesi attorno alla lettera e le virgolette attorno alla stringa si cerca il regex, che dice "Trova il carattere 'f' seguito da 'nord'."

Ma dato che hai inserito le parentesi nel modello 'f' ora è seguito da ']', quindi grepnon comparirà nell'elenco dei risultati. Neato!


26
@acolyte: l'output di ps includerà una riga che termina con grep [f]nord. Tuttavia, quella riga non verrà inserita attraverso il filtro grep, poiché la stringa [f]nordnon corrisponde all'espressione regolare [f]nord.
LarsH

9
@LarsH interessante, grazie! avrei suggerito ps aux | grep fnord | grep -v grep... che sembra essere già stato suggerito da alcune persone ... lol
accolito

5
@progo Sì, devi citare il [pari in bash. Provalo con un file chiamato fnordnella directory corrente.
Gilles

26
Il grepping dell'output pspotrebbe essere un vecchio trucco, ma non è affidabile. Utilizzarepgrep se disponibile.
Gilles

9
@naxa Immagina di avere una chiamata di programma fnorde un programma chiamato safnorde. Oppure c'è un utente chiamato bfnorde finisci per uccidere tutti i suoi processi. Ecc.
Gilles,

165

Un'altra opzione che uso (specialmente solo per vedere se un processo è in esecuzione) è il pgrep comando. Questo cercherà un processo di abbinamento, ma non elencherà una linea grep per la ricerca. Mi piace perché è un modo rapido di ricerca, senza regexare o sfuggire a nulla.

pgrep fnord

8
Vorranno che l' -fopzione sia più simile ps | grep.
Giordania,

@jordanm In realtà, pgrep -fsembrerà più simile ps -f | grep.
michelpm,

5
C'è anche l' -largomento per farlo mostrare il comando che viene abbinato.
Patrick

15
ps | grep '[f]nord'è intelligente e venerabile, ma pgrep ha ragione .
Kojiro,

3
Puoi sempre fare ps $(pgrep cmd) ...se `pgrep non ha opzioni (tuttavia non funzionerà con un set vuoto di comandi).
Maciej Piechotka,

63

La soluzione ideale è quella presentata da BriGuy

pgrep fnord 

Ma se non vuoi farlo, puoi semplicemente escludere tutte le righe che corrispondono a grep con:

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

7
ma cosa succede se la linea che sto cercando è "bash bash grep bash"?
Sparr,

1
@Sparr Allora dovresti usare la soluzione migliore: pgrepo trovarne un'altra;)
RSFalcon7

Fai attenzione al limite di lunghezza del nome con pgrep. Usa -f per ottenere il nome completo del percorso o potresti scoprire che le tue partite falliscono con nomi più lunghi. -l è anche bello elencare le partite
Neil McGill


24

Non è la soluzione più elegante ma potresti farlo:

$ ps aux | grep fnord | grep -v grep


È una cattiva risposta! Perché se ci fosse una parola grepnella tua frase. Non mostrerà quel processo. Ad esempio, supponiamo che un file chiamato foo_grep_bar.txtvenga modificato dal nanocomando. Quindi c'è un processo in esecuzione: root 14908 0.0 0.0 110012 1692 pts / 3 S + Oct31 0:00 nano foo_grep_bar.txtsecondo questa risposta, questo non funzionerà: $ ps aux | grep nano | grep -v grepPerché c'è una parola grep nel tuo nome file.
Nabi KAZ,

Preferisco questo come più esplicito riguardo alla sua intenzione rispetto alla risposta accettata e funziona in tutti i casi tranne uno.
Samaspin,

1
come da superuser.com/a/409658/450260 dovresti escludere l'intero grep fnordnon solo grepie $ ps aux | grep fnord | grep -v "grep fnord"
Davos,


14

In zsh, grep fnord =(ps aux).

L'idea è, prima di tutto ps aux, inserire il risultato in un file, quindi utilizzarlo grepsu quel file. Solo, non abbiamo un file, poiché utilizziamo la "sostituzione di processo" di zsh.

Per illustrare, prova

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

Il risultato dovrebbe essere lo stesso.

Commento generale su alcune delle altre risposte. Alcuni sono troppo complicati e / o lunghi da scrivere. Non si tratta solo di avere ragione, dovrebbe anche essere utilizzabile. Ma ciò non significa che alcune di quelle soluzioni siano cattive; solo, devono essere racchiusi in una mini-UI per renderli utilizzabili.


1
Non conoscendo la sostituzione dei processi di zsh, ma è certo che i due processi sono chiamati uno dopo l'altro e non in parallelo?
Paulo Ebermann

3
@ PaŭloEbermann: per parallelo è il <(command). grep grep =(ps aux)non mostra alcuna riga.
Maciej Piechotka,

Zsh può anche "abbinare" l'output di ps. print -l ${(M)${(f)¨$(ps aux)¨}:#*fnord*}
Friartek

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

3
questo sembra un IOCCC, ma per la riga di comando unix invece di C ^^ Non | grep $(echo fnord)era abbastanza? chiedi anche a sed di cercare e sostituire ogni carattere in "fnord" con il suo valore? ^^ congratulazioni. Scommetto che posso fare un ancora più lungo, ma probabilmente non sarà così divertente ^^
Olivier Dulac

1
Mi scuso perché il tono del mio commento sopra può sembrare offensivo (e non posso modificarlo dopo 5 minuti) ... La tua risposta è stata davvero una lettura gioiosa, e non stavo cercando di farti sembrare cattiva. Penso davvero che tu l'abbia fatto così apposta ^^
Olivier Dulac il

1
Non scusarti, la tua risposta è stata davvero divertente da leggere (e anche azzeccata). Intendevo pgrep -l $ 1 comunque;)
yil

3
@OlivierDulac: non si limita a sostituire il primo carattere con il suo valore; lo sostituisce con la concatenazione del suo valore tra parentesi quadre. (Quelle parentesi quadre non sono speciali, sono letterali.) Fondamentalmente, si sta generalizzando sulla risposta di Wayne Werner, in modo che il processo di mettere parentesi quadre attorno al primo personaggio possa essere scritto. +1
LarsH

2
ps aux | grep '[^]]fnord'eviterei quella ginnastica.
Stéphane Chazelas,

6

Questa risposta è specifica per GNU . Vedi la risposta di Wayne per una soluzione più generale.

Alla ricerca di processi

Se stai solo cercando i fnordprocessi, puoi utilizzare l' -Copzione per selezionare in base al nome del comando:

ps -C fnord

Questo può essere combinato con le opzioni di formato stile BSD e POSIX a proprio piacimento. Vedi la pagina man di ps per un elenco completo.

Cerchi qualcos'altro?

Se hai bisogno di qualcosa di più avanzato di una ricerca esatta di un nome di comando, non perdere la speranza! Questo può ancora essere fatto sul pslato del tubo. Tutto quello che dobbiamo fare è dire psdi escludere i grepprocessi dal risultato:

ps -NC grep | grep 'fnord'

-C grepseleziona tutti i processi grep e -Nannulla la selezione. Questo può essere usato per cercare argomenti di comando, parte di un nome di comando o espressioni regolari più complesse.


1
Questo va bene con GNU psma -Cnon è specificato da POSIX e ha un significato completamente diverso su BSD
Eric Renouf

È davvero un peccato che non ci sia equivalente a BSD (il che significa anche che non funzionerà su un mac). L'uso di ps -C è di gran lunga la risposta più semplice di una di queste.
Christopher Hunter,

3

La mia risposta è una variazione della risposta tipica per la ricerca di "foobar" in un elenco "ps". L'argomento di "-A" "ps" è più portabile di "aux", credo, ma questo cambiamento è irrilevante per la risposta. La risposta tipica è questa:

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

Invece uso questo modello:

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

Il vantaggio principale è che è più semplice scrivere script basati su questi schemi perché concateni semplicemente una stringa statica "[^]]" con qualsiasi modello tu stia cercando. Non è necessario rimuovere la prima lettera della stringa, quindi inserirla tra le parentesi quadre e quindi concatenarla nuovamente insieme. Quando si esegue lo scripting in shell, è più semplice incollare "[^]]" davanti al modello che stavi cercando. Il taglio delle corde in Bash è una cosa brutta, quindi la mia variazione lo evita. Questa variazione dice mostra le linee in cui il modello corrisponde SENZA una parentesi quadra di destra]. Poiché il modello di ricerca per escludere una parentesi quadra aggiunge effettivamente la parentesi quadra al modello, allora non corrisponderà mai a se stesso.

Quindi potresti scrivere un comando 'psgrep' portatile come segue. Qui, tengo conto delle differenze tra Linux, OS X BSD e altri. Questo aggiunge le intestazioni di colonna da 'ps', fornisce un formato 'ps' più personalizzato che si adatta alle mie esigenze di scommettitori e mostra i processi che elencano extra, extra larghi in modo che nessuno degli argomenti della riga di comando venga perso. Bene, molti non sono mancati. Essendo Java, spesso fa le cose nel modo peggiore possibile, quindi alcuni servizi Java correranno oltre la lunghezza massima consentita degli argomenti che la tabella dei processi terrà traccia. Credo che questo sia 1024 caratteri. La lunghezza della sola riga di comando consentita per avviare un processo è molto più lunga, ma la tabella dei processi del kernel non si preoccupa di tenere traccia di qualsiasi lunghezza superiore a 1 KB. Una volta avviato il comando, l'elenco dei nomi dei comandi e degli argomenti non è '

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

Il modo più semplice agnostico di shell per farlo sarebbe quello di memorizzarlo prima in una variabile:

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

Call-out: la grep fnord =(ps aux)risposta di @ EmanuelBerg è di gran lunga la più elegante, anche se richiede zsh. L'ho avuto brevemente nei miei file rc, ma bash si lamenta di quella sintassi, nonostante un condizionale che dovrebbe impedirne la valutazione.


Dai miei file rc, ho una versione senza distinzione tra maiuscole e minuscole che prende gli argomenti di 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, un punto elenco per riga di codice:

  • Cattura l' psoutput dettagliato (in una localvariabile in modo che scompaia quando la funzione ritorna)
  • Visualizza la prima riga (il titolo) in errore standard in modo che i risultati possano essere ulteriormente filtrati senza influire sul titolo. La sostituzione dice: prendi $PS_OUTPUTe rimuovi tutto dopo il feed della prima riga (regex equiv:) s/\n.*$//msg. Questo ci impedisce di aggirare il titolo
  • Mostra l' psoutput con tutto tranne la prima riga (regex equiv:) s/^.*\n//me grep il suo contenuto con -imaiuscole e minuscole e con tutti gli argomenti consegnati a questa funzione (nel caso di nessun argomento ^, che corrisponde all'inizio di qualsiasi riga per abbinare qualunque cosa)

0

Forse è il momento di usare una sequenza reale questa volta. L'uso di tubi lo rende parallelo.

ps aux >f && grep tmpfs <f

Brutto perché ci sarà un file f, ma non è colpa mia se non c'è sintassi per i processi sequenziali in cui si desidera ancora utilizzare l'output di un processo precedentemente eseguito.

Suggerimento per la sintassi di un operatore sequenziale:

ps aux ||| grep tmpfs

L'incapacità della gente comune di filtrare facilmente un flusso non è certo una ragione per cui l'élite si basi su sequenze. Sarebbe un passo indietro nell'informatica.
Acumenus,

@ABB en.wikipedia.org/wiki/Communicating_sequential_processes hanno molti più operatori rispetto a quelli che sono finiti nella shell Thompson. Potrebbe esserci stato solo un operatore sequenziale e che ha comunicato il suo risultato al processo successivo nella sequenza non appena esce. Un "passo indietro nell'informatica" fornendo un operatore aggiuntivo sembra un po 'duro.
Anne van Rossum,

Bel collegamento, ma ovviamente l'elaborazione sequenziale è peggiore sia nell'uso della CPU che della memoria (o del disco), rispetto all'elaborazione parallela. In questo caso, se devo prima memorizzare tutto l' psoutput prima di me grep, sto usando più memoria (o disco) più a lungo.
Acumenus,

0

Il comando pgrep, come altri hanno affermato, restituirà il PID (ID processo) dei processi in base al nome e ad altri attributi. Per esempio,

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

ti fornirà i PID, delimitati da una virgola (,) di tutti i processi il cui nome corrisponde all'esecuzione dell'utente <username>. È possibile utilizzare l'opzione -x prima di restituire solo corrispondenze esatte.

Se vuoi ottenere maggiori informazioni su questi processi (come implica l'esecuzione delle opzioni aux da ps), puoi usare l'opzione -p con ps, che corrisponde in base al PID. Quindi, per esempio,

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

fornirà informazioni dettagliate su tutti i PID associati al comando pgrep.


psfallisce se pgreprestituisce un set vuoto. Ho una risposta che si basa sulla tua e cerca di risolvere questo problema.
Acumenus,

0

Ecco un semplice esempio per trovare PID di ssh-agentper username senza mostrare PID del grepprocesso stesso:

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

Se ad esempio vuoi uccidere ssh-agentper l'utente corrente puoi usare il seguente comando:

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

Per creare un pratico alias aggiungi al tuo file ~ / .bashrc o ~ / .zshrc il seguente codice:

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

E per usare l'alias qui ci sono esempi che obbligano tutti a imparare espressioni regolari:

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

PS Ho testato solo questi comandi su Ubuntu e Gentoo.


(1) La domanda non dice che l'utente sta cercando uno dei propri processi: l'utente potrebbe non conoscere il proprietario del processo che sta cercando. (2) Per quanto elegante sia questa risposta, fallirebbe comunque se lo avessi detto "${USER}.* /usr/bin/ssh-agent". Funziona perché hai detto [ ]; cioè, stai solo usando il meccanismo della risposta accettata. Potresti anche solo grep "[s]sh-agent".
G-Man,

Hai ragione. (1) Ho condiviso ciò che potrebbe essere utile quando mi sono ritrovato ad affrontare questa pagina di tanto in tanto (2) Sì, ho usato l'espressione regolare come nella risposta accettata. (3) Ho aggiornato la mia risposta per accettarla come quella migliore, ma ho anche mostrato come fare e alias da usare con il nome utente fornito o senza di essa. (4) Ha anche mostrato come definire la funzione, anche se non è necessario ma funziona in modo interessante poiché $ 1 e $ 2 non si sovrappongono. Thx # G-Man
Constantin Zagorsky,

0

Ecco una versione estesa della grep -v grepsoluzione, che filtra tutti i grepprocessi che non sono in esecuzione da più di un secondo, il che rappresenta un miglioramento rispetto a "scartare tutte le occorrenze di grep".

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

rispettivamente

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

Potrebbe non essere portatile e dipende dal formato di output effettivo del pscomando locale .

Potresti voler combinare questo con un grepoutput colorato per comodità:

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

-1

L'uso dell'opzione -x (corrispondenza esatta) ha funzionato per me. L'ho combinato con -f (riga di comando completa), quindi ho potuto abbinare il mio processo precisamente con:

pgrep -x -f "path_i_used_when_starting/cmd params_i_used"

Chiunque stia facendo il downvoting drive-by si spiegherà? Questo ha funzionato per risolvere questo problema per me senza fallo per anni.
moodboom

-3

Puoi farlo facilmente, semplicemente definendo un ALIAS .bashrc come questo:

alias grep='grep -v grep | grep'

Non sei sicuro di chi abbia votato per difetto o perché, ma ciò ti consente di utilizzare appieno ps che pgrep non ha.
ottico

1
Non solo ciò esclude inavvertitamente altri processi grep; interrompe anche l' greputilizzo in altri casi. Prova echo I love grep | grep love.
trosos,

@trosos Quasi 11 anni sono stato * nix-ing .. e non ho mai usato quel modello mai ... forse il prossimo anno - chi lo sa bene.
a20
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.