dev-services.sh
Rama main · réplica de lectura del repositorio original.
#!/bin/sh
# Starts and stops the KiloCenter development services that start-dev.sh runs.
#
# dev-services.sh start NAME start one service and print its PID
# dev-services.sh stop stop every service this checkout started
# dev-services.sh log NAME print the path of the service's log
#
# NAME is kc-core, kc-identity, kc-gateway or kc-web. A service runs through
# exec, so its pid file holds the service's own PID. Stop ends the process a
# pid file names and every process it started, and only while that process
# still runs the service's command: a stale pid file never kills anything.
KC_ROOT=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd)
KC_PID_DIR="$KC_ROOT/../logs/pids"
KC_LOG_DIR="$KC_ROOT/../logs/runtime"
# Seconds a service gets to exit after SIGTERM before it is killed.
KC_STOP_TIMEOUT="${KC_STOP_TIMEOUT:-10}"
# The web server and the gateway stop before KC-Identity and KC-Core, so the
# gateway cannot reconnect to them while they shut down; a reconnecting
# gateway leaves port 50052 in TIME_WAIT.
KC_STOP_ORDER="kc-web kc-gateway kc-identity kc-core"
usage() {
echo "usage: $0 start NAME | stop | log NAME (NAME: kc-core, kc-identity, kc-gateway, kc-web)" >&2
exit 2
}
service_dir() {
case "$1" in
kc-core) echo "$KC_ROOT/KC-Core" ;;
kc-identity) echo "$KC_ROOT/KC-Identity" ;;
kc-gateway) echo "$KC_ROOT/KC-Gateway" ;;
kc-web) echo "$KC_ROOT/KC-Web" ;;
*) return 1 ;;
esac
}
# service_command is the command line a service runs as, as ps reports it.
service_command() {
case "$1" in
kc-core) echo "./kilocenter -config config.yaml" ;;
kc-identity) echo "./identity -config config.yaml" ;;
kc-gateway) echo "./gateway -config config.yaml" ;;
kc-web) echo "bun run dev" ;;
*) return 1 ;;
esac
}
start_service() {
dir=$(service_dir "$1") || usage
mkdir -p "$KC_PID_DIR" "$KC_LOG_DIR"
# The command is split into its words on purpose.
(cd "$dir" && exec $(service_command "$1")) >"$KC_LOG_DIR/$1.log" 2>&1 &
echo "$!" >"$KC_PID_DIR/$1.pid"
echo "$!"
}
# descendants prints the PID of every process below the process $1.
descendants() {
ps -A -o pid= -o ppid= | awk -v root="$1" '
{ kids[$2] = kids[$2] " " $1 }
END {
n = split(kids[root], stack, " ")
while (n > 0) {
pid = stack[n--]
print pid
m = split(kids[pid], more, " ")
for (i = 1; i <= m; i++) stack[++n] = more[i]
}
}'
}
any_alive() {
for pid in "$@"; do
kill -0 "$pid" 2>/dev/null && return 0
done
return 1
}
# signal_and_wait sends the signal $1 to the processes that follow and waits
# up to KC_STOP_TIMEOUT seconds for them to exit; it fails if one outlives it.
signal_and_wait() {
signal=$1
shift
kill -s "$signal" "$@" 2>/dev/null
waited=0
while any_alive "$@"; do
[ "$waited" -ge "$KC_STOP_TIMEOUT" ] && return 1
sleep 1
waited=$((waited + 1))
done
}
stop_service() {
name=$1
pidfile="$KC_PID_DIR/$name.pid"
[ -f "$pidfile" ] || return 0
pid=$(cat "$pidfile")
rm -f "$pidfile"
if [ "$(ps -o args= -p "$pid" 2>/dev/null)" != "$(service_command "$name")" ]; then
echo "$name was not running"
return 0
fi
echo "Stopping $name (PID $pid)..."
set -- "$pid" $(descendants "$pid")
signal_and_wait TERM "$@" || signal_and_wait KILL "$@"
echo "$name stopped"
}
case "$1" in
start)
[ $# -eq 2 ] || usage
start_service "$2"
;;
stop)
[ $# -eq 1 ] || usage
for name in $KC_STOP_ORDER; do
stop_service "$name"
done
;;
log)
[ $# -eq 2 ] && service_dir "$2" >/dev/null || usage
echo "$KC_LOG_DIR/$2.log"
;;
*) usage ;;
esac