Linux / terminate process tree

Csoport azonosítóval (groupid, gid) lehet leállítani folyamatot és alfolyamatait, viszont nem biztos hogy a leállítandó folyamatunk a legmagasabb szülő, és így a csoport kilövésével nem kívántakat is leállíthatunk.

Arra kerestem megoldást, hogy egy folyamatot úgy állítsak le, hogy csak erre és az összes gyermek folyamatára vonatkozzon.

Megoldás itt:
http://stackoverflow.com/questions/392022/best-way-to-kill-all-child-pr…

Vagyis:

kill -- -$( ps opgid= $PID | tr -d ' ' )

Érdemes elolvasni a magyarázatot amit az emberke ír, mert elsőre nem egyértelmű.

Nekem viszont olyan megoldás kellett, ahol a shell script-em nevét megadva, az összes ilyen futó példányt kilövi a gyermek folyamatokkal együtt. Ilyet követtem el:

function STOP {
    PIDS=$(pgrep script.sh)
    if ! [ -z "$PIDS" ]; then
        echo "$PIDS" | while read PP; do
            kill -- -$( ps opgid= "$PP" | tr -d ' ' )
        done
    fi
}

Megjegyzem, hogy "pgrep script.sh" csak olyan esetben működik, ha a script neve nem túl hosszú, mivel a proc alrendszerben csak adott karakter számig jegyzi a folyamat nevet. Ekkor használható a pgrep a -f kapcsolóval, viszont ezzel figyázni kell, mert a folyamatok teljes parancssorában keresi ezt a script nevet. Ilyenkor általában ellátom egy egyedi azonosítóval a nevet.

Más rendszereken ez hogy működik? BSD, OS X vagy Win? Egyszerűbb megoldás?

Szerk.: közben szívtam több órát a kérdéssel, a fenti kód és megoldás nem jó, úgyhogy sajátot írtam a "pgrep -P" parancssal, amely a folyamat közvetlen gyermek folyamatainak PID-jét adja vissza, és ezért rekurzívan be kell járni az összeset. 1 óra bash szívás után inkább ruby mellett döntöttem, ez ne zavarjon senkit ;)


function STOP {
ruby -e '''
        pold = `pgrep "$1"`.split("\n")
        pres = []
        while true
                pnew = []
                
                # get all child
                pold.each { |x|
                        pchild = `pgrep -P #{x}`.split("\n")
                        pnew += pchild if pchild.size > 0
                }

                # terminate all and exit if no more child         
                if pnew.size == 0
                        pres.each { |x| `kill #{x}` }
                        break
                end

                # store results
                pres += pnew
                
                # run recursively on results
                pold = pnew
        end
'''
}

STOP script.sh

Hozzászólások