Ps può visualizzare solo processi non kernel su Linux?


Risposte:


37

Questo dovrebbe fare (sotto Linux):

ps --ppid 2 -p 2 --deselect

kthreadd(PID 2) ha PPID 0 ( su Linux 2.6+ ) ma psnon consente di filtrare per PPID 0; quindi questo aggirare.


Bello, ma quanto è garantito che kthreaddsia sempre PID 2?
l0b0

@ l0b0 Non ne ho idea :-) Potresti farlo in due passaggi: determina il PID di kthreadd, quindi crea la pschiamata corrispondente. Quanto è garantito che questa cosa sarà "sempre" chiamata "kthreadd"? Una soluzione sicura sarebbe più complicata, funzionerebbe psnormalmente e analizzerebbe l'output, magari facendo alcuni test.
Hauke ​​Laging,

2
Almeno in Linux 2.4 su arco x86, quei processi avevano ppid 1, quindi non potevano essere distinti in quel modo.
Stéphane Chazelas,

1
essere come "ps -ef" fai "ps --ppid 2 -p 2 --deselect -f" e farlo come "ps aux" fai "ps --ppid 2 -p 2 --deselect u"
Peter

1
@Totor Ho controllato e sembra che sia la xbandiera che non funziona con questo. ps au --ppid 2 -p 2 --deselectfunziona bene.
Sankalp

9

Un modo per riconoscere i processi del kernel è che non usano alcuna memoria utente, quindi il campo vsz è 0. Questo cattura anche gli zombi (grazie a Stephane Chazelas per questa osservazione), che possono essere eliminati in base al loro stato.

ps axl | awk '$7 != 0 && $10 !~ "Z"'

Per elencare solo i PID:

ps -e -o pid= -o state= -o vsize= | awk '$2 != "Z" && $3 != 0 {print $1}'

Come la mia soluzione, includerà anche processi di zombi.
Stéphane Chazelas,

1
@StephaneChazelas Buon punto, ho aggiunto una condizione al filtro.
Gilles 'SO- smetti di essere malvagio' il

9

In pratica ho trovato abbastanza il seguente linguaggio:

ps auxf | grep -v ]$

Filtra le linee che terminano con parentesi, che potrebbe comportare l'omissione di voci indesiderate, ma è molto improbabile. In cambio è abbastanza facile da ricordare e relativamente veloce da digitare.

Alcuni processi come avahi-daemon aggiungono tra parentesi le informazioni sul nome del processo (il nome host nel caso di avahi-daemon) e verranno filtrati da questo comando.


8

Una delle particolarità di questi processi è che non sono supportati da un file eseguibile, quindi potresti farlo ( in zsh ):

ps /proc/[0-9]*/exe(^-@:h:t)

O con qualsiasi shell POSIX:

ps -p "$(find -L /proc/[0-9]*/exe ! -type l | cut -d / -f3 | paste -sd , -)"

Cioè controlla i processi il cui /proc/<pid>/exeè un collegamento a un file.

Ciò significa che devi essere un superutente per poter controllare lo stato del /proc/<pid>/exelink simbolico.

Modifica : Come accade, i processi di zombi (almeno) soddisfano la stessa condizione, quindi se non li vuoi escludere, dovresti aggiungerli di nuovo. Piace:

ps -p "$(
  { find -L /proc/[0-9]*/exe ! -type l | cut -d / -f3
    ps -Ao pid=,state= | sed -n 's/ Z//p'
  } | paste -sd , -)"

Nota che ps -fmostra quei nomi di processo tra parentesi quadre non perché sono processi del kernel, ma perché hanno un vuoto argv[](quindi ps mostra il nome del processo anziché argv[0]lì). Puoi avere un processo dello spazio utente anche con un vuoto argv[]e puoi avere un nome di processo con una argv[0]forma che è [some-string]quindi un filtro psdell'output basato su quelle parentesi quadre non è un'opzione infallibile.


Questa è una sintassi di shell non standard, credo.
Totor

1
@Totor, come ho detto, il primo è la zshsintassi. Il secondo è la sintassi POSIX standard sh(e pse finde cute paste). Ovviamente /procnon è specificato da POSIX.
Stéphane Chazelas,

Accettare questa risposta perché è universale (grazie per la modifica). Tuttavia, la risposta di Hauke ​​Laging è anche piuttosto carina e semplice purché non si tratti di un kernel 2.4.
Totor,

@Totor, la risposta di Hauke ​​ha anche il vantaggio di non richiedere il privilegio di un superutente. La mia risposta funziona con i kernel 2.4 e 2.6 / 3, ma suppongo che non ci sia garanzia che funzionerà comunque in 4.x.
Stéphane Chazelas,

Hmm, hai ragione, non ho pensato ai privilegi di root. Può portare a errori poiché ricevi ancora una risposta quando non sei root, ma è diverso (quindi devi essere cauto quando li conti, diciamo wc -l). Bene, accetterò la risposta di Hauke ​​Laging e ti darò un voto. ;)
Totor

1

Puoi anche analizzare l' psoutput e cercare i nomi dei processi che non sono tra parentesi:

ps aux | awk '$NF!~/^\[.+\]$/'

Un modo leggermente meno inaffidabile per ottenere l'elenco degli utenti che ti interessano: awk -F: '$7 ~ home { print $1 }' /etc/passwd- ma otterrai comunque processi che menzionano un tale nome utente e lascerai il file temporaneo in giro. Ritiro il mio voto negativo, ma solo perché la tua terza soluzione è ragionevole.
Keith Thompson,

Bah, hai ragione, @KeithThompson, rimosso gli altri, non ne valgono la pena. Potresti aiutarmi a ripulire i commenti (ora) obsoleti?
terdon

2
Si noti che $NFè l'ultima parola della riga di comando ps auxnell'output. I processi non kernel possono avere [...]lì. Come ho detto nella mia risposta, la [xxx]notazione non è perché sono processi del kernel, ma perché non hanno una riga di comando (nessun argomento) che è consentita anche per i processi non kernel.
Stéphane Chazelas,

1

Per chiunque provi questo in busybox dove psè fortemente semplificato e l'output è diverso, questa variante della grande risposta di Gilles funziona bene:

ps -o pid,user,comm,vsz,stat | awk '$4 != 0 && $5 !~ "Z"'

Secondo la risposta di Gilles, la metodologia qui è quella di trovare processi che non usano alcuna memoria utente (`vsz col == 0) e filtrare i processi zombie (lo stato col non è 'Z').

Le colonne di output possono essere regolate facilmente, purché i numeri dei campi awk basati su 1 siano adeguati di conseguenza. Vedi le opzioni che il tuo ps ha a disposizione inserendo un valore falso e te lo dirà. Per esempio:

$ ps -o foo
ps: bad -o argument 'foo', supported arguments: user,group,comm,args,pid,ppid,pgid,tty,vsz,stat,rss

0

Se hai solo bisogno dei conteggi ... Avevo un'analoga necessità di filtrare i processi kernel vs user, ma avevo solo bisogno dei rispettivi conteggi di ciascuno. Questa era la mia soluzione:

ps -eo vsize | awk '{p[$1==0]++} END {printf "%-16s %6d\n%-16s %6d\n%-16s %6d\n", "Kernel processes", p[1], "User processes", p[0], "Total processes", p[0]+p[1]}'

Uscita campione :

Kernel processes    353
User processes       52
Total processes     405

Spiegazione : Sto usando l'hacking che i processi VSZ = 0 possono essere considerati processi del kernel. Quindi awk, valuto un confronto su VSZ (da ps -eo vsize), sia uguale a zero. Il risultato del confronto sarà uno 0 booleano o 1. Faccio un array p[]e, mentre corro l'elenco dei processi, se è un processo del kernel, incremento p[1]++. Altrimenti, come processo utente, aumento p[0]++. Dopo tutto l'incremento, etichetta e stampa i valori (ovvero i conteggi) per p [0] e p [1] nel END { }blocco.


0

Quello che stai cercando, amico mio, non lo è ps, mapstree .

Innanzitutto, identifica il primo processo del kernel. Il suo PID è comunemente 1 sul sistema senza systemd e 2 con systemd.

Quindi utilizzare questo comando:

$ pstree -p <1 or 2> | grep -o '([0-9]\+)' | grep -o '[0-9]\+'

La risposta selezionata (una con ✅) sta usando un altro comando:

$ ps --ppid 2 -p 2 --deselect

Il problema con questo pscomando è che include solo figli diretti ma non tutti i discendenti. Il pstreecomando include tutti i discendenti. Puoi confrontare e contare l'output di questi due comandi (un modo semplice sta usando | wc) per verificare.


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.