rmyorston / busybox-w32

WIN32 native port of BusyBox.
https://frippery.org/busybox
Other
677 stars 124 forks source link

How kill all descendant processes? #334

Closed ale5000-git closed 1 year ago

ale5000-git commented 1 year ago

Hi, this is just a question.

For this simple case: sleep 20 && echo doh & it is enough to do this: pkill -KILL -P "${$}"

But for more complicate cases like this:

var="$({
  cat &
} | hexdump -d -n 32)"

How to kill it?

I have found this: kill $(ps -s $$ -o pid=) and this:

list_descendants ()
{
  local children=$(ps -o pid= --ppid "$1")

  for pid in $children
  do
    list_descendants "$pid"
  done

  echo "$children"
}

kill $(list_descendants $$)

but they do not work due to limitations in the BusyBox version of them.

Any suggestion? Thanks in advance.

ale5000-git commented 1 year ago

I have noticed this doesn't work: pgrep -a -s 0

Have I done something worng?

rmyorston commented 1 year ago

Use a negative pid to kill all children or use the job id:

~ $ sh -c 'sleep 10' &
[1] 2080
~ $ kill -- -2080
[1]+  Terminated                 sh -c "sleep 10"
~ $ sh -c 'sleep 10' &
[1] 3600
~ $ kill %1
[1]+  Terminated                 sh -c "sleep 10"
~ $

pgrep -a -s 0

Have I done something worng?

No, it's just that session ids aren't supported on Windows.

ale5000-git commented 1 year ago

I need to kill all descendants but not the main script. I'm not expert about this but where do I get the negative pid or the job id? It isn't interactive, and I cannot use $! since it is executed under a subshell.

Example of what I need:

( sleep 100 && echo doh & )
( sleep 100 && echo doh & )
( sleep 100 && echo doh & )

kill all (except the main script)
rmyorston commented 1 year ago

If it isn't interactive you won't have a job id. Use ps to get the pid? I don't know.

ale5000-git commented 1 year ago

This list descendants but it seems not the ones inside the subshell:

_list_descendants()
{
  local _children="$(pgrep -P "${1?}")"

  for _pid in ${_children?}
  do
    printf '%s ' "${_pid?}"
    _list_descendants "${_pid?}"
  done
}
_list_descendants "${$}"
rmyorston commented 1 year ago

You need the pids of the background jobs. They're children of the subshells, not the current process.

( sleep 100 && echo doh & echo $! >pids )
( sleep 100 && echo doh & echo $! >>pids )
( sleep 100 && echo doh & echo $! >>pids )
( sleep 100 && echo doh & echo $! >>pids )
cat pids
ale5000-git commented 1 year ago

It works, thanks :)