|
|
@@ -1,55 +1,118 @@
|
|
|
#!/bin/sh
|
|
|
# useful functions
|
|
|
# 2013-09-26 11:00 created by niujiuru
|
|
|
+# 2026-01-05 13:40 updated by niujiuru
|
|
|
|
|
|
# export envionment variables
|
|
|
export_env()
|
|
|
{
|
|
|
PATH="/bin:/sbin:/usr/bin:/usr/sbin"
|
|
|
-
|
|
|
- CWD=$(dirname $0)
|
|
|
- [ "${CWD%%[^/]*}" != "/" ] && CWD="${PWD}/${CWD}"
|
|
|
-
|
|
|
+ CWD=$(cd "$(dirname "$0")" && pwd) || exit 1
|
|
|
export PATH CWD
|
|
|
}
|
|
|
|
|
|
# load module by name
|
|
|
# pass THIS_MODULE to module
|
|
|
-# $1: module name
|
|
|
+# $1: module name (no path, no '..')
|
|
|
load_module()
|
|
|
{
|
|
|
local module="$1"
|
|
|
+
|
|
|
+ [ -n "$module" ] || return 1
|
|
|
+
|
|
|
+ case "$module" in
|
|
|
+ */*|*..*) return 1 ;;
|
|
|
+ esac
|
|
|
+
|
|
|
THIS_MODULE="${module}"
|
|
|
- . ${CWD}/modules/${module}
|
|
|
+ [ -f "${CWD}/modules/${module}" ] || return 1
|
|
|
+
|
|
|
+ . "${CWD}/modules/${module}"
|
|
|
}
|
|
|
|
|
|
# load module & call module's method
|
|
|
# $1: module name
|
|
|
-# $2: method name
|
|
|
+# $2: method name (function defined in module)
|
|
|
# $...: method params
|
|
|
call_module()
|
|
|
{
|
|
|
+ [ $# -ge 2 ] || return 1
|
|
|
+
|
|
|
local module="$1"
|
|
|
local method="$2"
|
|
|
+
|
|
|
shift 2
|
|
|
- load_module "$module" && "$method" $*
|
|
|
+ load_module "$module" || return 1
|
|
|
+ type "$method" >/dev/null 2>&1 || return 1
|
|
|
+ "$method" "$@"
|
|
|
+
|
|
|
return $?
|
|
|
}
|
|
|
|
|
|
# return true if program is running
|
|
|
-# $1: program's name
|
|
|
+# $1: program's executable path
|
|
|
+# return 0 if running, 1 otherwise
|
|
|
is_running()
|
|
|
{
|
|
|
- ps | grep -w "$1" | grep -v "grep" &>/dev/null
|
|
|
+ local target="$1" pid exe
|
|
|
+
|
|
|
+ [ -n "$target" ] || return 1
|
|
|
+
|
|
|
+ for pid in /proc/[0-9]*; do
|
|
|
+ [ -r "$pid/exe" ] || continue
|
|
|
+ exe=$(readlink "$pid/exe" 2>/dev/null) || continue
|
|
|
+ [ "$exe" = "$target" ] && return 0
|
|
|
+ done
|
|
|
+
|
|
|
+ return 1
|
|
|
}
|
|
|
|
|
|
# kill program(s) by name
|
|
|
-# $1: program name
|
|
|
+# $1: program's executable path
|
|
|
+# $2: signal to send (default: 15)
|
|
|
kill_programs()
|
|
|
{
|
|
|
+ local target="$1" pid exe
|
|
|
local sig=${2:-15}
|
|
|
- for p in $(ps | grep -w "$1" | grep -v "grep" | awk '{print $1}')
|
|
|
- do
|
|
|
- kill -$sig $p
|
|
|
+
|
|
|
+ [ -n "$target" ] || return 1
|
|
|
+
|
|
|
+ case "$sig" in
|
|
|
+ ''|*[!0-9]*) return 1 ;;
|
|
|
+ esac
|
|
|
+ [ "$sig" -ge 1 -a "$sig" -le 64 ] 2>/dev/null || return 1
|
|
|
+
|
|
|
+ for pid in /proc/[0-9]*; do
|
|
|
+ [ -r "$pid/exe" ] || continue
|
|
|
+ exe=$(readlink "$pid/exe" 2>/dev/null) || continue
|
|
|
+ if [ "$exe" = "$target" ]; then
|
|
|
+ kill -$sig "${pid##*/}" 2>/dev/null
|
|
|
+ fi
|
|
|
+ done
|
|
|
+}
|
|
|
+
|
|
|
+# gracefully terminate program by executable path
|
|
|
+# send SIGTERM and wait, then SIGKILL if timeout
|
|
|
+# $1: program's executable path
|
|
|
+# $2: timeout in seconds (default: 5)
|
|
|
+# return 0 if terminated gracefully
|
|
|
+# return 2 if force killed after timeout
|
|
|
+graceful_kill() {
|
|
|
+ local target="$1" timeout="${2:-5}" waited=0
|
|
|
+
|
|
|
+ [ -n "$target" ] || return 1
|
|
|
+
|
|
|
+ kill_programs "$target" 15 || return 1
|
|
|
+
|
|
|
+ while is_running "$target" && [ "$waited" -lt "$timeout" ]; do
|
|
|
+ sleep 1
|
|
|
+ waited=$((waited + 1))
|
|
|
done
|
|
|
+
|
|
|
+ if is_running "$target"; then
|
|
|
+ kill_programs "$target" 9
|
|
|
+ return 2
|
|
|
+ fi
|
|
|
+
|
|
|
+ return 0
|
|
|
}
|