ps: Belirli bir ücret karşılığında tüm alt süreci yinelemeli olarak nasıl alabilirim


43

Bir ağaç olarak görüntülenen belirli bir işlemle tüm işlem ağacını nasıl doğurabilirim, sadece o ağaç yani başka bir işlem yok?

Çıktı örneğin benziyor olabilir

 4378 ?        Ss     0:10 SCREEN
 4897 pts/16   Ss     0:00  \_ -/bin/bash
25667 pts/16   S+     0:00  |   \_ git diff
25669 pts/16   S+     0:00  |       \_ less -FRSX
11118 pts/32   Ss+    0:00  \_ -/bin/bash
11123 pts/32   S+     0:00      \_ vi

Sadece istenen parametrelerle istenen sonucu alamadım ps.

Aşağıdaki istenen sonucu verir ancak biraz dahil görünüyor:

#!/bin/bash

pidtree() {
  echo -n $1 " "
  for _child in $(ps -o pid --no-headers --ppid $1); do
    echo -n $_child `pidtree $_child` " "
  done
}

ps f `pidtree 4378`

Daha kolay bir çözümü olan var mı?


Cevap değil, ama başla ps auxf.
jftuga

3
@jtfuga Bu başladığım aslında, ama bu bana veriyor bütün ı tam olarak ne olduğu, süreçleri yok istiyorum.
11:59

Yanıtlar:


38

Bu pstreeçok iyi bir çözüm, ancak biraz suskun. Onun ps --forestyerine kullanıyorum. Ancak PID( -p) için değil, yalnızca belirli bir işlemi basar, ancak oturum için ( -g). Herhangi bir bilgiyi psyazdırabilir ve -oseçeneği tanımlayan süslü bir ASCII resim ağacında yazdırabilir .

Öyleyse bu sorun için önerim:

ps --forest -o pid,tty,stat,time,cmd -g 2795

Eğer süreç bir oturum lideri değilse, o zaman biraz daha fazla numara uygulanmalıdır:

ps --forest -o pid,tty,stat,time,cmd -g $(ps -o sid= -p 2795)

Bu işlem ilk önce o anki işlemin oturum kimliğini (SID) alır ve ardından bu sid ile tekrar ps çağrısı yapar.

Sütun başlıklarına gerek yoksa, '-o' seçeneklerinde her bir sütun tanımından sonra '=' ekleyin, örneğin:

ps --forest -o pid=,tty=,stat=,time=,cmd= -g $(ps -o sid= -p 2795)

Bir örnek çalışma ve sonuç:

$ ps --forest -o pid=,tty=,stat=,time=,cmd= -g $(ps -o sid= -p 30085)
27950 pts/36   Ss   00:00:00 -bash
30085 pts/36   S+   00:00:00  \_ /bin/bash ./loop.sh
31888 pts/36   S+   00:00:00      \_ sleep 5

Ne yazık ki bu, screenher çocuk perdesi ve tüm torun bash için sid ayarlar olarak işe yaramaz .

Bir sürecin doğduğu tüm süreçleri elde etmek için bütün ağacın yapılması gerekir. Bunun için kullandım . İlk başta hepsini içermek için bir karma dizisi oluşturur PID => ,child,child.... Sonunda, belirli bir sürecin tüm alt süreçlerini çıkarmak için özyinelemeli bir işlev çağırır. Sonuç, psformatlamak için sonuç bir başkasına iletilir . Gerçek PID, yerine bir argüman olarak yazılmalıdır <PID>:

ps --forest $(ps -e --no-header -o pid,ppid|awk -vp=<PID> 'function r(s){print s;s=a[s];while(s){sub(",","",s);t=s;sub(",.*","",t);sub("[0-9]+","",s);r(t)}}{a[$2]=a[$2]","$1}END{r(p)}')

Bir SCREEN işlemi için (pid = 8041) örnek çıktı şöyle görünür:

  PID TTY      STAT   TIME COMMAND
 8041 ?        Ss     0:00 SCREEN
 8042 pts/8    Ss     0:00  \_ /bin/bash
 8092 pts/8    T      0:00      \_ vim test_arg test_server
12473 pts/8    T      0:00      \_ vim
12972 pts/8    T      0:00      \_ vim

Bununla ilgili sorun (eski bir cevap olduğunu biliyorum) --forest seçeneği yalnızca Linux'ta (ya da diğer gnu tabanlı "ps" komutlarıyla) çalışıyor. Solaris ve MacOS bundan hoşlanmıyor.
Armand,

@TrueY bunu yapabilen bir C API biliyor musunuz? Teşekkür ederim
Bionix1441 20:17

Bionix Hayır, üzgünüm ... Bu ağacı yapmak için / proc / <PID> dizinlerini okuyabilirim.
TrueY

1
PID'nin pstüm soyundan gelenleri filtrelemek için bir filtre bayrağı seçeneği varsa , bunun basit olması gerektiği gibi görünüyor .
CMCDragonkai 17:18

27
pstree ${pid}

${pid}Ana sürecin pid nerede .

Gentoo Linux'ta, pstreegörünüşe göre bulunduğu "psmisc" paketindehttp://psmisc.sourceforge.net/


9
Teşekkürler, baktığımı söylemeliydim pstree, ancak daha ayrıntılı çıktı formatını kaçırdım. Bununla birlikte, pstree -p <pid>en azından makul ölçüde yakın olan pideleri yazdırın.
kynan

2
Ben yinelemeli tüm alt pids toplamak gerekir, çok bu sorun var ama olurdu bu yüzden, sadece pids gerekmez sed.. Bu eser :) mmm hepsipstree -pn 4008 |grep -o "([[:digit:]]*)" |grep -o "[[:digit:]]*"
Kova Güç

12

İşte anında çalışan sürümüm ( psyalnızca bir kez çalıştırıldığından). Bash ve zsh olarak çalışır.

pidtree() (
    [ -n "$ZSH_VERSION"  ] && setopt shwordsplit
    declare -A CHILDS
    while read P PP;do
        CHILDS[$PP]+=" $P"
    done < <(ps -e -o pid= -o ppid=)

    walk() {
        echo $1
        for i in ${CHILDS[$1]};do
            walk $i
        done
    }

    for i in "$@";do
        walk $i
    done
)

1
Bu aynı zamanda isteyebileceğiniz ya da istemeyeceğiniz mevcut sürecin pid'ini de basar. Mevcut sürecin listelenmesini istemedim (sadece mevcut sürecin torunları), bu yüzden betiği echo $1ilk döngü içinde hareket ettirip değiştirerek değiştirdim echo $i.
Mark Lakata

1
Bunu bulduğumda hemen hemen böyle bir fonksiyon yazmak üzereydim. MacOS, Linux ve Solaris'te çalışan tek çözüm budur. Harika iş. İşi bellekte yapmak için tek bir ps çalıştırmaya güvenmenizi seviyorum.
Armand,

3

Bir ebeveynin alt sürecinin bir liste yardımcısını oluşturmak için küçük bir bash betiği oluşturdum. Tekrarlı bir şekilde, hiç çocuğu olmayan son çocuk sürecini bulana kadar. Size ağaç görüntüsü vermiyor. Bu sadece tüm pid'leri listeler.

function list_offspring {
  tp=`pgrep -P $1`          #get childs pids of parent pid
  for i in $tp; do          #loop through childs
    if [ -z $i ]; then      #check if empty list
      exit                  #if empty: exit
    else                    #else
      echo -n "$i "         #print childs pid
      list_offspring $i     #call list_offspring again with child pid as the parent
    fi;
  done
}
list_offspring $1

list_offspring'in ilk argümanı ana pid'dir


1
Gerçek bir ağacı basmayan bash betiğini veren, sorunun kendisinde biri de dahil olmak üzere birkaç yanıt daha var. (Kısmi) yanıtınızın mevcut (kısmi) cevaplar üzerindeki avantajları nelerdir?
David Richerby

Özyineleme kullandım ve biraz açıklama ekledim. Birine yardım edebileceğini düşündüm. Bu tam olarak unvanın ne istediğini yapar.
Merijn

Burada pgrep kullanımını seviyorum, çünkü ps unix değişkenleri arasında farklılık gösterebilir.
John Szakmeister

3

ps -H -g "$pid" -o comm

kendi başına bir ağaç eklemiyor, sadece süreçlerin listesi.

örneğin verir

COMMAND
bash
  nvim
    python

Bu -Hseçenek, bir işlem ağacını veya "işlem hiyerarşisini (orman)" görüntülemek için kullanılır
Anthony G - Monica adaleti,

2

Aynı soruna bir çözüm bulmak için çalışıyorum. Temel olarak, ps manpage istediklerimizi tek bir komutla yapmamıza izin veren herhangi bir seçeneği belgelendirmez. Sonuç: bir senaryo gereklidir.

Seninkine çok benzeyen bir senaryo yazdım. ~ / .Bashrc dizinine yapıştırarak herhangi bir kabuktan kullanabiliyorum.

pidtree() {
  local parent=$1
  local list=
  while [ "$parent" ] ; do     
    if [ -n "$list" ] ; then
      list="$list,$parent"
    else
      list="$parent"
    fi
    parent=$(ps --ppid $parent -o pid h)
  done
  ps -f -p $list f
}

1

Komut satırında:

ps -o time,pid,ppid,cmd --forest -g -p $(pgrep -x bash)

çıktı:

    TIME   PID  PPID CMD
00:00:00  5484  5480 bash
00:00:01  5531  5484  \_ emacs -nw .bashrc
00:00:01  2986  2984 /bin/bash
00:00:00  4731  2986  \_ redshift
00:00:00  5543  2986  \_ ps -o time,pid,ppid,cmd --forest -g -p 2986 5484

bu yolla daha şık bir yol, bir işlevi tanımlamaktır .bashrc:

function subps()                                                                                    
{                                                                                                   
    process=$(pgrep -x $1)                                                                                                                                                                     
    ps -o time,pid,ppid,cmd --forest -g -p $process                                                 
}    

sonra komut satırında çalıştırın:

subps bash

1

Bu, sadece pid + çocuklara her birisini bir satırda verir; bu, daha sonraki işlemler için faydalıdır.

pidtree() {
    for _pid in "$@"; do
        echo $_pid
        pidtree `ps --ppid $_pid -o pid h`
    done
}

0

Philippe'nin yukarıdakilerine dayanarak benzer bir senaryo yazdım.

pidlist() {
local thispid=$1
local fulllist=
local childlist=
childlist=$(ps --ppid $thispid -o pid h)
for pid in $childlist
do
  fulllist="$(pidlist $pid) $fulllist"
done
echo "$thispid $fulllist"
}

Bu, tüm çocuk, torun vb. Alanların sınırlandırılmış biçimde çıktılarını verir. Bu da, ps'de olduğu gibi ps'ye beslenebilir.

ps -p $ (pidlist pid )


-2

tüm işlemler için - pstree - bir kullanıcı tarafından göster - pstree kullanıcı


2
Lütfen bunun neden soruyu cevapladığını biraz daha açıklayın.
kullanıcı 99572,
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.