【问题标题】:Trim a binary process tree level by level starting from the leafs从叶子开始逐级修剪二叉进程树
【发布时间】:2019-09-22 01:20:21
【问题描述】:

我需要编写一个 bash 脚本来运行一个 C 程序,该程序使用 fork() 生成一个 n 深度的进程二叉树,然后从树的叶子到根逐级修剪它。

制作进程树的 C 代码非常简单。 You can see the full code here,不过是 TL;DR 版本如下:

void tree(int n):
   if (n==0) exit
   rchild=fork()
   if (parent)
      lchild=fork()
      if (left child)
         tree(n-1)
   else //right child
      tree(n-1)
sleep(1000)

查看pstree -pn PID 输出,我注意到子进程的PID 是连续的,因此我决定根据第一个实例的PID 通过数值终止进程。但可能是因为命令占用了 PID 值或另一个系统进程,在脚本中运行代码会敲掉 PID 的值,所以我的方法不再有效。我正在尝试使用 pstree 的输出直接获取 PID,但目前看来,为了获得一级 PID,sedawk 的调用会很混乱。

这是我目前拥有的 bash 脚本:

#!/bin/bash

if [ ! -f "./fork.run" ]
then
    >&2 echo 'Error: binary mising'
    >&2 echo 'Generate it with "gcc -o fork.run fork.c"'
    exit
fi

if [ "$1" == "" ]
then
    >&2 echo "Error: you need to indicate the depth of the tree"
    exit
fi

./fork.run $(( $1 - 1 )) &
fork=$! #store tree's PID
n=$1

echo "fork started with PID $fork"


while [ $n -gt 1 ]
do

    echo "Tree of the process $fork:"
    pstree -pn $fork

    sleep 1

    #calculation based on properties of the binary tree
    min=$(( 2 ** (n - 1) + $fork ))
    max=$(( (2 ** n) - 1 + $fork ))

    echo "starting trim: level $n"


    for i in `seq $min $max`
    do
        echo "killing $i"
        kill $i #I also tried kill -9 $i, but it's the same.
    done

    sleep 1

    echo "processes from $min to $max trimmed"

    let n--
done

pstree -pn $fork

sleep 1

echo "starting trim: level $n (final)"

kill $fork

sleep 1

echo "initial process ($fork) trimmed"

【问题讨论】:

    标签: c linux bash


    【解决方案1】:

    看来,为了获得一级 PID,sed 和 awk 调用将是一团糟。

    好吧,awk 并不算太乱。以下替换您的while 循环使用awk 脚本处理pstree 输出,该脚本确定(根据每行中的位置)包含的进程所属的树级别并杀死所选进程的树级别等级n

    while [ $n -gt 1 ]
    do
        echo "Tree of the process $fork:"
        pstree -p $fork
        sleep 1
        echo "starting trim: level $n"
        pstree -pl $fork |
        gawk -vn=$n '
        /^[^ ]/ { level = 1; start[1] = 1 }             # line starting with non-space has top level
        /^ /    { level = trats[match($0, "[|`]-")] }   # determine first level of line from position of |- or `-
        {   while (i = match(substr($0, start[level]), ")-[-+]-"))
            { start[level+1] = start[level]+i+1; ++level; trats[start[level]] = level } # hash level by position
            if (match(substr($0, start[n]), "^.-[^(]+.([0-9]+)", p)) { print "killing "p[1]; system("kill "p[1]) }
        }   '
        sleep 1
        echo "processes trimmed"
        let n--
    done
    

    【讨论】:

    • 事情是我是一个 KISS 情人,这不是愚蠢的'n'简单。但会考虑。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-03
    • 2010-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多