improved kt and ku

This commit is contained in:
fatalerrors
2026-05-21 11:08:46 +02:00
parent 5f8800ab44
commit 6bacb03687
2 changed files with 145 additions and 21 deletions

View File

@@ -71,7 +71,7 @@ version-bump.
**[easy]** **[easy]**
### processes ### processes
- [ ] **`ku` dry-run flag** — add `-n` / `--dry-run` to print what would be - [X] **`ku` dry-run flag** — add `-n` / `--dry-run` to print what would be
killed without acting. **[easy]** killed without acting. **[easy]**
### pwd ### pwd

View File

@@ -190,23 +190,88 @@ export -f gpid
# Usage: ku <username1 [username2 ...]> # Usage: ku <username1 [username2 ...]>
ku() ku()
{ {
if [[ "$1" == "-h" || "$1" == "--help" ]]; then local dry_run=0
printf "ku: Kill all processes owned by the given users.\n\n" local -a signal_opt=()
printf "Usage: ku <username1 [username2 ...]>\n\n"
printf "Options:\n" while [[ $# -gt 0 ]]; do
printf "\t-h, --help\t\tDisplay this help screen\n" case "$1" in
return 0 -h|--help)
fi printf "ku: Kill all processes owned by the given users.\n\n"
printf "Usage: ku [options] <username1 [username2 ...]>\n\n"
printf "Options:\n"
printf "\t-h, --help\t\tDisplay this help screen\n"
printf "\t-n, --dry-run\t\tDisplay commands without executing them\n"
printf "\t-s, --signal SIG\tSignal to send (overrides KU_DEFAULT_SIGNAL)\n"
printf "\t --signal=SIG\tSame as above\n"
printf "\t -SIG / -NUM\tSignal format compatible with kill\n"
return 0
;;
-n|--dry-run)
dry_run=1
shift
;;
-s|--signal)
if [[ -z "${2:-}" || "$2" == -* ]]; then
disp E "--signal requires a value."
return 1
fi
signal_opt=(-s "$2")
shift 2
;;
--signal=*)
if [[ -z "${1#*=}" ]]; then
disp E "--signal requires a value."
return 1
fi
signal_opt=(-s "${1#*=}")
shift
;;
-[0-9]*|-SIG*|-[[:alpha:]]*)
signal_opt=("$1")
shift
;;
--)
shift
break
;;
-*)
disp E "Unknown option: $1, use \"ku --help\" to display usage."
return 1
;;
*)
break
;;
esac
done
if [[ -z "$1" ]]; then if [[ -z "$1" ]]; then
disp E "Usage: ku <username1 [username2 ...]>" disp E "Usage: ku [options] <username1 [username2 ...]>"
return 1 return 1
fi fi
local u
for u in "$@"; do for u in "$@"; do
if ! id "$u" >/dev/null 2>&1; then if ! id "$u" >/dev/null 2>&1; then
disp E "User '$u' does not exist." disp E "User '$u' does not exist."
return 1 return 1
else else
killall ${KU_DEFAULT_SIGNAL:+-${KU_DEFAULT_SIGNAL}} -u "$u" local cmd=(killall)
if [[ ${#signal_opt[@]} -gt 0 ]]; then
cmd+=("${signal_opt[@]}")
elif [[ -n "${KU_DEFAULT_SIGNAL:-}" ]]; then
cmd+=("-${KU_DEFAULT_SIGNAL}")
fi
cmd+=(-u "$u")
if (( dry_run )); then
printf "DRY-RUN: "
printf "%q " "${cmd[@]}"
printf "\n"
else
"${cmd[@]}"
fi
fi fi
done done
} }
@@ -219,32 +284,91 @@ export -f ku
# Usage: kt <pid> [kill_options] # Usage: kt <pid> [kill_options]
kt() kt()
{ {
if [[ "$1" == "-h" || "$1" == "--help" ]]; then local dry_run=0
printf "kt: Kill all children of a process then the process (kill tree).\n\n" local -a pre_kill_opts=()
printf "Usage: kt <pid> [kill_options]\n\n"
printf "Options:\n" while [[ $# -gt 0 ]]; do
printf "\t-h, --help\t\tDisplay this help screen\n" case "$1" in
return 0 -h|--help)
fi printf "kt: Kill all children of a process then the process (kill tree).\n\n"
printf "Usage: kt [options] <pid> [kill_options]\n\n"
printf "Options:\n"
printf "\t-h, --help\t\tDisplay this help screen\n"
printf "\t-n, --dry-run\t\tDisplay kill commands without executing them\n"
printf "\t-s, --signal SIG\tSignal to send to process tree\n"
printf "\t --signal=SIG\tSame as above\n"
printf "\t -SIG / -NUM\tSignal format compatible with kill\n"
return 0
;;
-n|--dry-run)
dry_run=1
shift
;;
-s|--signal)
if [[ -z "${2:-}" || "$2" == -* ]]; then
disp E "--signal requires a value."
return 1
fi
pre_kill_opts+=(-s "$2")
shift 2
;;
--signal=*)
if [[ -z "${1#*=}" ]]; then
disp E "--signal requires a value."
return 1
fi
pre_kill_opts+=(-s "${1#*=}")
shift
;;
-[0-9]*|-SIG*|-[[:alpha:]]*)
pre_kill_opts+=("$1")
shift
;;
--)
shift
break
;;
*)
break
;;
esac
done
if [[ -z "$1" ]]; then if [[ -z "$1" ]]; then
disp E "Usage: kt <pid>" disp E "Usage: kt [options] <pid> [kill_options]"
return 1 return 1
fi fi
local parent_pid="$1" local parent_pid="$1"
shift shift
local -a kill_opts=("${pre_kill_opts[@]}" "$@")
if [[ "$parent_pid" == "0" || "$parent_pid" == "1" ]]; then if [[ "$parent_pid" == "0" || "$parent_pid" == "1" ]]; then
disp E "Safety abort: Refusing to kill PID $parent_pid (system critical)." disp E "Safety abort: Refusing to kill PID $parent_pid (system critical)."
return 1 return 1
fi fi
local children_pids local children_pids
children_pids=$(pgrep -P "$parent_pid") children_pids=$(pgrep -P "$parent_pid" 2>/dev/null || true)
local pid
for pid in $children_pids; do for pid in $children_pids; do
kt "$pid" "$@" || break if (( dry_run )); then
kt --dry-run "$pid" "${kill_opts[@]}" || break
else
kt "$pid" "${kill_opts[@]}" || break
fi
done done
kill "$@" "$parent_pid"
if (( dry_run )); then
local cmd=(kill "${kill_opts[@]}" "$parent_pid")
printf "DRY-RUN: "
printf "%q " "${cmd[@]}"
printf "\n"
else
kill "${kill_opts[@]}" "$parent_pid"
fi
} }
export -f kt export -f kt
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------