How do I kill background processes / jobs when my

2020-01-23 03:03发布

I am looking for a way to clean up the mess when my top-level script exits.

Especially if I want to use set -e, I wish the background process would die when the script exits.

标签: shell
13条回答
【Aperson】
2楼-- · 2020-01-23 03:42

To be on the safe side I find it better to define a cleanup function and call it from trap:

cleanup() {
        local pids=$(jobs -pr)
        [ -n "$pids" ] && kill $pids
}
trap "cleanup" INT QUIT TERM EXIT [...]

or avoiding the function altogether:

trap '[ -n "$(jobs -pr)" ] && kill $(jobs -pr)' INT QUIT TERM EXIT [...]

Why? Because by simply using trap 'kill $(jobs -pr)' [...] one assumes that there will be background jobs running when the trap condition is signalled. When there are no jobs one will see the following (or similar) message:

kill: usage: kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l [sigspec]

because jobs -pr is empty - I ended in that 'trap' (pun intended).

查看更多
地球回转人心会变
3楼-- · 2020-01-23 03:44

Another option is it to have the script set itself as the process group leader, and trap a killpg on your process group on exit.

查看更多
Evening l夕情丶
4楼-- · 2020-01-23 03:47

A nice version that works under Linux, BSD and MacOS X. First tries to send SIGTERM, and if it doesn't succeed, kills the process after 10 seconds.

KillJobs() {
    for job in $(jobs -p); do
            kill -s SIGTERM $job > /dev/null 2>&1 || (sleep 10 && kill -9 $job > /dev/null 2>&1 &)

    done
}

TrapQuit() {
    # Whatever you need to clean here
    KillJobs
}

trap TrapQuit EXIT

Please note that jobs does not include grand children processes.

查看更多
欢心
5楼-- · 2020-01-23 03:47

jobs -p does not work in all shells if called in a sub-shell, possibly unless its output is redirected into a file but not a pipe. (I assume it was originally intended for interactive use only.)

What about the following:

trap 'while kill %% 2>/dev/null; do jobs > /dev/null; done' INT TERM EXIT [...]

The call to "jobs" is needed with Debian's dash shell, which fails to update the current job ("%%") if it is missing.

查看更多
Luminary・发光体
6楼-- · 2020-01-23 03:48
function cleanup_func {
    sleep 0.5
    echo cleanup
}

trap "exit \$exit_code" INT TERM
trap "exit_code=\$?; cleanup_func; kill 0" EXIT

# exit 1
# exit 0

Like https://stackoverflow.com/a/22644006/10082476, but with added exit-code

查看更多
放我归山
7楼-- · 2020-01-23 03:48

Just for diversity I will post variation of https://stackoverflow.com/a/2173421/102484 , because that solution leads to message "Terminated" in my environment:

trap 'test -z "$intrap" && export intrap=1 && kill -- -$$' SIGINT SIGTERM EXIT
查看更多
登录 后发表回答