特定のプロセスによって生成されたプロセスツリー全体をツリーとして表示し、そのツリーのみを表示する方法、つまり他のプロセスを表示しない方法を教えてください。
出力は、例えば、のように見える
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`
誰かがより簡単な解決策を持っていますか?
pstree
は非常に良い解決策ですが、それは少し謙虚です。代わりにps --forest
を使用します。しかしPID
(-p
)には適していません。特定のプロセスだけを表示するのであり、セッション(-g
)には表示しないためです。 ps
が-o
オプションを定義する派手なASCIIアートツリーに印刷できる任意の情報を印刷できます。
だからこの問題について私の提案:
ps --forest -o pid,tty,stat,time,cmd -g 2795
プロセスがセッションリーダーではない場合は、もう少しトリックを適用する必要があります。
ps --forest -o pid,tty,stat,time,cmd -g $(ps -o sid= -p 2795)
これは最初に現在のプロセスのセッションID(SID)を取得してから、その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
残念ながら、これはそれぞれの子スクリーンとすべての孫のbashのsidを設定するのでscreen
には機能しません。
プロセスによって生成されたすべてのプロセスを取得するには、ツリー全体を構築する必要があります。そのために awk を使用しました。最初にすべてのPID => ,child,child...
を含むようにハッシュ配列を構築します。最後に、与えられたプロセスのすべての子プロセスを抽出するために再帰関数を呼び出します。結果を別のps
に渡して結果をフォーマットします。実際のPIDは<PID>
の代わりに awk への引数として書く必要があります。
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)}')
SCREENプロセス(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
pstree ${pid}
$ {pid}は親プロセスのPIDです。
Gentooでは、pstreeは "psmisc"パッケージ内にあり、明らかに http://psmisc.sourceforge.netにあります。 /
これは私のバージョンです(ps
は一度だけ実行されるので)すぐに実行されます。 bashと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
)
ps -H -g "$pid" -o comm
ツリー自体を追加するのではなく、単なるプロセスのリストです。
例えば
COMMAND
bash
nvim
python
私はまったく同じ問題に対する解決策を見つけるために努力してきました。基本的に、psのマンページには、1つのコマンドで必要なことを実行できるオプションが記載されていません。結論:スクリプトが必要です。
私はあなたのものと非常によく似たスクリプトを思い付きました。私はそれを私の〜/ .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
}
私は親の子プロセスのリストpidを作成するための小さなbashスクリプトを作成しました。子を持たない最後の子プロセスが見つかるまで再帰的にツリービューにはなりません。それはただすべての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の最初の引数は親pidです
これはpid + children pidのみをそれぞれ1行に与えます。
pidtree() {
for _pid in "$@"; do
echo $_pid
pidtree `ps --ppid $_pid -o pid h`
done
}
コマンドラインでの作業中:
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
上記のPhilippeに基づいて同様のスクリプトを作成しました。
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"
}
これは、すべての子、孫などのpidをスペース区切り形式で出力します。これは、次に示すように、psに入力することができます。
ps -p $(pidlistpid)