#!@BASH_PATH@ # A simple reimplementation of killall5 from sysvinit-tools get_my_tree() { local my_pid read my_pid garbage < "/proc/self/stat" child="$my_pid" while [[ "$parent" != 1 ]]; do read a b c parent d < "/proc/$child/stat"; child="$parent" echo "$parent" done } get_all_procs() { local processlist for i in /proc/*/exe; do process_dir="${i%/*}" process_pid="${process_dir##*/}" readlink -e "$i" &>/dev/null && { echo "$process_pid" } done } get_procs_to_kill() { for i in "${all_procs[@]}"; do unset skip for p in "${my_tree[@]}"; do [[ "$i" == "$p" ]] && { skip=1; } done [[ "$skip" ]] || { echo "$i"; } done } pids_exist() { for i in "$@"; do if [[ -d "/proc/$i" ]]; then return 0 fi done return 1 } pid_wait() { declare counter while pids_exist "$@"; do if (( counter == timeout )); then return 1 fi sleep 1 (( counter++ )) done } main() { timeout=30 signal=15 while (( $# )); do case $1 in -w) flag_wait=1 timeout=$2 shift ;; -s) signal=$2 shift ;; esac shift done my_tree=( $(get_my_tree) self thread-self ) all_procs=( $(get_all_procs) ) procs_to_kill=( $(get_procs_to_kill) ) kill -n "$signal" "${procs_to_kill[@]}" 2>/dev/null if (( flag_wait )); then pid_wait "${procs_to_kill[@]}" fi return 0 } main "$@"