mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-11-09 20:02:20 +08:00
Reinstall an existing Service while keeping its enabled, runtime-masked and active state. Detect, from the journal, a running Service removed by a previous deb prerm and reinstall it with its recorded group. Package script output never reaches the app, so leave a /run marker that makes the app offer a reinstall once when the Service is not ready. Hold the core lifecycle until the package manager exits, even after the startup install times out, so no core start overlaps the Service reinstall; restart the app once a late install succeeds. Refs #8515 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
98 lines
3.9 KiB
Bash
98 lines
3.9 KiB
Bash
#!/bin/bash
|
|
set -e
|
|
|
|
chmod +x /usr/bin/clash-verge-service-install
|
|
chmod +x /usr/bin/clash-verge-service-uninstall
|
|
chmod +x /usr/bin/clash-verge-service
|
|
|
|
SERVICE_UNIT="clash-verge-service.service"
|
|
SERVICE_UNIT_FILE="/etc/systemd/system/$SERVICE_UNIT"
|
|
# Read by the app, which offers a reinstall when the package could not keep the Service.
|
|
UPGRADE_MARKER="/run/clash-verge-service-upgrade"
|
|
|
|
write_upgrade_marker() {
|
|
(umask 022 && printf 'gid=%s\nid=%s\n' "$1" "$(date +%s%N)" >"$UPGRADE_MARKER")
|
|
}
|
|
|
|
existing_service_gid() {
|
|
local group
|
|
group="$(sed -n 's/^Group=//p' "$SERVICE_UNIT_FILE" | head -n 1)"
|
|
if [ -n "$group" ]; then
|
|
getent group "$group" | cut -d: -f3
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
# Failures only warn: dpkg and rpm cannot restore the previous Service from a failed postinst,
|
|
# and a failing script would leave the package unconfigured or make the app report a failed update.
|
|
# The installer always enables and starts the unit, so the previous enablement and activity are restored.
|
|
reinstall_existing_service() {
|
|
local gid="$1" enabled active=no
|
|
enabled="$(systemctl is-enabled "$SERVICE_UNIT" 2>/dev/null)"
|
|
if systemctl is-active --quiet "$SERVICE_UNIT"; then
|
|
active=yes
|
|
fi
|
|
if [ "$enabled" = "masked-runtime" ]; then
|
|
systemctl unmask --runtime --quiet "$SERVICE_UNIT"
|
|
fi
|
|
local status=0
|
|
if ! CLASH_VERGE_SERVICE_GID="$gid" /usr/bin/clash-verge-service-install --install-service; then
|
|
echo "Warning: reinstalling Clash Verge Service failed; Clash Verge will offer to reinstall it." >&2
|
|
status=1
|
|
fi
|
|
case "$enabled" in
|
|
disabled) systemctl disable --quiet "$SERVICE_UNIT" ;;
|
|
masked-runtime) systemctl mask --runtime --quiet "$SERVICE_UNIT" ;;
|
|
esac
|
|
if [ "$active" = "no" ]; then
|
|
systemctl stop "$SERVICE_UNIT"
|
|
fi
|
|
return "$status"
|
|
}
|
|
|
|
# Upgrades keep an existing Service current; first installs and explicit removals never add one.
|
|
# A symlinked unit is masked or managed by the administrator and is left alone.
|
|
# The marker is written first: a previous package whose %preun uninstalls unconditionally
|
|
# still removes the Service after this script, and the app only acts on it if the Service is not ready.
|
|
if [ "$1" -ge 2 ] && [ -d /run/systemd/system ] && [ -f "$SERVICE_UNIT_FILE" ] && [ ! -L "$SERVICE_UNIT_FILE" ]; then
|
|
gid="$(existing_service_gid)"
|
|
write_upgrade_marker "$gid"
|
|
if [ -z "$gid" ]; then
|
|
echo "Warning: the Clash Verge Service group could not be resolved; Clash Verge will offer to reinstall the Service." >&2
|
|
else
|
|
reinstall_existing_service "$gid" || true
|
|
fi
|
|
fi
|
|
|
|
# The enforcement file exists in both Enforcing and Permissive mode.
|
|
if [ ! -e /sys/fs/selinux/enforce ]; then
|
|
exit 0
|
|
fi
|
|
|
|
if [ ! -x /usr/sbin/semanage ] || [ ! -x /usr/sbin/restorecon ]; then
|
|
echo "Warning: persistent SELinux rules were not installed; install policycoreutils and policycoreutils-python-utils, then reinstall this package. The service installer repairs executable labels, but a system relabel can reset them." >&2
|
|
exit 0
|
|
fi
|
|
|
|
# Keep these local rules on removal: they may predate this package or serve a standalone development service.
|
|
for service in clash-verge-service clash-verge-service-dev; do
|
|
for directory in bin cores; do
|
|
target="/var/lib/$service/$directory"
|
|
if [ -L "/var/lib/$service" ] || [ -L "$target" ]; then
|
|
echo "Refusing to relabel a symlinked service directory: $target" >&2
|
|
exit 1
|
|
fi
|
|
spec="$target(/.*)?"
|
|
# Older semanage versions reject -a when an exact rule already exists.
|
|
if ! add_error="$(/usr/sbin/semanage fcontext -a -t bin_t "$spec" 2>&1)"; then
|
|
if ! /usr/sbin/semanage fcontext -m -t bin_t "$spec"; then
|
|
printf '%s\n' "$add_error" >&2
|
|
exit 1
|
|
fi
|
|
fi
|
|
if [ -d "$target" ]; then
|
|
/usr/sbin/restorecon -R "$target"
|
|
fi
|
|
done
|
|
done
|