पीएस: मैं किसी दिए गए पिड के लिए सभी बच्चे की प्रक्रिया को कैसे पुन: प्राप्त कर सकता हूं


43

मैं एक पेड़ के रूप में प्रदर्शित की गई एक प्रक्रिया और पूरी तरह से उस पेड़ यानी किसी अन्य प्रक्रिया से पूरी पेड़ को कैसे प्राप्त कर सकता हूं?

आउटपुट जैसे दिख सकता है

 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

मैं मापदंडों के साथ विशुद्ध रूप से वांछित परिणाम प्राप्त नहीं कर सका ps

निम्नलिखित वांछित परिणाम देता है, लेकिन इसमें थोड़ा सा शामिल लगता है:

#!/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`

क्या किसी के पास इसका आसान हल है?


उत्तर नहीं, लेकिन शुरुआत करें ps auxf
jftuga

3
@jtfuga वास्तव में यह वह जगह है जहां मैंने शुरुआत की थी, लेकिन इससे मुझे सभी प्रक्रियाएं मिलती हैं, जो कि वास्तव में मैं नहीं चाहता।
kynan

जवाबों:


38

pstreeएक बहुत अच्छा समाधान है, लेकिन यह एक छोटा सा मितभाषी है। मैं ps --forestइसके बजाय का उपयोग करें । लेकिन ए PID( -p) के लिए नहीं क्योंकि यह केवल विशिष्ट प्रक्रिया को प्रिंट करता है, लेकिन सत्र के लिए ( -g)। यह विकल्प psको परिभाषित करने वाले फैंसी ASCII आर्ट ट्री में कोई भी जानकारी प्रिंट कर -oसकता है।

तो इस समस्या के लिए मेरा सुझाव:

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

यदि प्रक्रिया सत्र का नेता नहीं है, तो थोड़ी अधिक चाल लागू करनी होगी:

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

इससे वर्तमान प्रक्रिया का सेशन आईडी (SID) पहले हो जाता है और फिर उस साइड से पुन: PS को कॉल किया जाता है।

यदि कॉलम हेडर की जरूरत नहीं है, तो '-o' विकल्पों में प्रत्येक कॉलम परिभाषा के बाद '=' जोड़ें, जैसे:

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

एक उदाहरण रन और परिणाम:

$ 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

दुर्भाग्य से यह काम नहीं करता है screenक्योंकि यह प्रत्येक बाल स्क्रीन और सभी पोते के लिए बैश सेट करता है।

एक प्रक्रिया द्वारा पैदा की गई सभी प्रक्रियाओं को प्राप्त करने के लिए पूरे पेड़ को बनाने की आवश्यकता होती है। मैंने उसके लिए इस्तेमाल किया । सबसे पहले यह सभी को समाहित करने के लिए एक हैश सरणी बनाता है PID => ,child,child...। अंत में यह किसी दिए गए प्रक्रिया के सभी बच्चे को निकालने के लिए एक पुनरावर्ती कार्य को बुलाता है। परिणाम psको प्रारूपित करने के लिए परिणाम दूसरे को दिया जाता है । वास्तविक पीआईडी के लिए एक तर्क के रूप में लिखा जाना है के बजाय <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)}')

स्क्रीन प्रक्रिया (pid = 8041) के लिए उदाहरण आउटपुट इस तरह दिखता है:

  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

इस मुद्दे के साथ (मुझे पता है, यह एक पुराना जवाब है) - सबसे अच्छा विकल्प केवल लिनक्स (या अन्य ग्नू आधारित "पीएस" कमांड) पर काम करता है। सोलारिस, और मैकओएस इसे पसंद नहीं करते हैं।
आर्मंड

@ क्या आपको C C के बारे में पता है जो ऐसा कर सकता है? धन्यवाद
Bionix1441

Bionix नहीं, क्षमा करें ... मैं उस पेड़ को बनाने के लिए / खरीद / <PID> निर्देशिकाएं पढ़ सकता हूं।
सच्चे

1
ऐसा लगता है कि अगर psएक PID के सभी वंशजों को फ़िल्टर करने के लिए एक फ़िल्टर ध्वज विकल्प होता है तो यह सरल होना चाहिए ।
CMCDragonkai

27
pstree ${pid}

${pid}माता-पिता की प्रक्रिया का मार्ग कहाँ है।

Gentoo लिनक्स पर, pstreeपैकेज "psmisc," जाहिरा तौर पर स्थित हैhttp://psmisc.sourceforge.net/


9
धन्यवाद, उल्लेख करना चाहिए कि मैंने देखा था pstree, लेकिन एक अधिक वर्बोज़ आउटपुट स्वरूप से चूक गया। हालाँकि, pstree -p <pid>कम से कम उन प्रिंट्स को प्रिंट करें जो यथोचित करीब हों।
kynan 10

2
मुझे भी यह समस्या है, मुझे सभी बच्चे को पुनरावर्ती रूप से इकट्ठा करने की आवश्यकता है, लेकिन मुझे केवल pids की आवश्यकता है, इसलिए मुझे यह sedसब करना होगा .. mmm यह काम करता है :)pstree -pn 4008 |grep -o "([[:digit:]]*)" |grep -o "[[:digit:]]*"
कुंभ राशि

12

यहां मेरा संस्करण है जो तुरंत चलता है (क्योंकि psकेवल एक बार निष्पादित किया गया है)। बाश और zsh में काम करता है।

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
यह वर्तमान प्रक्रिया के पृष्ठ को भी प्रिंट करता है, जिसे आप चाहते हैं या नहीं कर सकते हैं। मैं वर्तमान प्रक्रिया को सूचीबद्ध नहीं करना चाहता था (वर्तमान प्रक्रिया के वंशज), इसलिए मैंने echo $1लूप के लिए पहले के अंदर जाकर और इसे बदलकर स्क्रिप्ट को बदल दिया echo $i
निशान लता

1
जब मैं ऐसा पाया तो मैं ऐसा फंक्शन लिखने वाला था। यह एकमात्र समाधान है जो मैकओएस, लिनक्स और सोलारिस पर काम करता है। अच्छा कार्य। प्यार कि आप स्मृति में काम पाने के लिए ps के एक रन पर भरोसा करते हैं।
आर्मंड

3

मैंने माता-पिता के बच्चे की प्रक्रिया की सूची बनाने के लिए एक छोटी सी बैश स्क्रिप्ट बनाई है। पुनरावृत्ति तक यह अंतिम बच्चे की प्रक्रिया का पता लगाता है जिसमें कोई चिल्ड नहीं है। यह आपको एक पेड़ का दृश्य नहीं देता है। यह सिर्फ सभी pid को सूचीबद्ध करता है।

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 का पहला तर्क पैरेंट पिड है


1
पहले से ही कई अन्य उत्तर हैं जो एक बश लिपि देते हैं जो वास्तविक पेड़ को प्रिंट नहीं करता है, जिसमें एक प्रश्न में ही शामिल है। आपके (आंशिक) उत्तर के मौजूदा (आंशिक) जवाबों के क्या फायदे हैं?
डेविड रिचेर्बी

मैंने पुनरावृत्ति का उपयोग किया और कुछ स्पष्टीकरण जोड़ा। सोचा कि यह किसी की मदद कर सकता है। यह वही करता है जो शीर्षक पूछता है।
मेराज १n

मुझे यहाँ pgrep का उपयोग पसंद है, क्योंकि ps यूनिक्स वेरिएंट के बीच भिन्न हो सकता है।
जॉन स्ज़ेकमिस्टर

3

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

प्रति पेड़ एक पेड़ नहीं जोड़ता है, यह सिर्फ प्रक्रियाओं की सूची है।

उदाहरण के लिए देता है

COMMAND
bash
  nvim
    python

-Hविकल्प के लिए एक प्रक्रिया पेड़ या प्रदर्शित करने के लिए प्रयोग किया जाता है "प्रक्रिया पदानुक्रम (वन)"
न्याय के लिए मोनिका - एंथोनी जी

2

मैं ठीक उसी समस्या का हल खोजने के लिए काम कर रहा हूं। मूल रूप से, ps manpage किसी भी विकल्प को दस्तावेज करने की अनुमति नहीं देता है जो हम एक ही कमांड के साथ चाहते हैं। निष्कर्ष: एक स्क्रिप्ट की जरूरत है।

मैं तुम्हारी जैसी ही स्क्रिप्ट लेकर आया हूं। मैंने इसे अपने ~ / .bashrc में चिपकाया है ताकि मैं इसे किसी भी शेल से उपयोग कर सकूं।

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

कमांड लाइन पर रास्ते में:

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

यह आउटपुट:

    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

उस तरीके से और अधिक सुरुचिपूर्ण तरीके से एक फ़ंक्शन को परिभाषित करना है .bashrc:

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

तब कमांड-लाइन रन पर:

subps bash

1

यह केवल एक लाइन पर प्रत्येक बच्चे को pid ​​+ pids देता है जो आगे की प्रक्रिया के लिए उपयोगी है।

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

0

मैंने फिलिप के ऊपर आधारित एक समान स्क्रिप्ट बनाई

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"
}

यह सभी बच्चों, पोते, आदि को अंतरिक्ष-सीमांकित प्रारूप में ग्रिड करता है। यह, बदले में, पीएस को खिलाया जा सकता है, जैसे कि

ps -p $ (पिडलिस्ट pid )


हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.