mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-11-09 20:02:20 +08:00
fix(linux): keep the Service through released rpm %preun via uninstaller wrapper
Refs #8515 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -3,17 +3,28 @@ set -e
|
||||
|
||||
chmod +x /usr/bin/clash-verge-service-install
|
||||
chmod +x /usr/bin/clash-verge-service-uninstall
|
||||
chmod +x /usr/lib/clash-verge-rev/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"
|
||||
# Read by /usr/bin/clash-verge-service-uninstall to keep the Service through the previous %preun.
|
||||
TRANSACTION_RECORD="/run/clash-verge-service-rpm-upgrade"
|
||||
|
||||
write_upgrade_marker() {
|
||||
(umask 022 && printf 'gid=%s\nid=%s\n' "$1" "$(date +%s%N)" >"$UPGRADE_MARKER")
|
||||
}
|
||||
|
||||
# Scriptlets run as children of the process running the rpm transaction; its start time
|
||||
# keeps a stale record from matching a later process that reuses the PID.
|
||||
record_transaction() {
|
||||
local start
|
||||
start="$(sed 's/.*) //' "/proc/$PPID/stat" | cut -d' ' -f20)"
|
||||
(umask 022 && printf '%s %s\n' "$PPID" "$start" >"$TRANSACTION_RECORD")
|
||||
}
|
||||
|
||||
existing_service_gid() {
|
||||
local group
|
||||
group="$(sed -n 's/^Group=//p' "$SERVICE_UNIT_FILE" | head -n 1)"
|
||||
@@ -52,9 +63,10 @@ reinstall_existing_service() {
|
||||
|
||||
# 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.
|
||||
# The previous %preun runs after this script; the record keeps it from removing the Service.
|
||||
# The marker stays as a fallback should it still be removed; 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
|
||||
record_transaction || true
|
||||
gid="$(existing_service_gid)"
|
||||
write_upgrade_marker "$gid"
|
||||
if [ -z "$gid" ]; then
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#!/bin/bash
|
||||
chmod +x /usr/bin/clash-verge-service-install
|
||||
chmod +x /usr/bin/clash-verge-service-uninstall
|
||||
chmod +x /usr/lib/clash-verge-rev/clash-verge-service-uninstall
|
||||
chmod +x /usr/bin/clash-verge-service
|
||||
|
||||
SERVICE_UNIT="clash-verge-service.service"
|
||||
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
#!/bin/sh
|
||||
# Installed as /usr/bin/clash-verge-service-uninstall. During an rpm upgrade the new %post
|
||||
# reinstalls an existing Service before the previous package's %preun runs, and released
|
||||
# %preun scripts uninstall it unconditionally through this path. Skip only that call: one
|
||||
# made by a scriptlet of the transaction that %post recorded.
|
||||
RECORD=/run/clash-verge-service-rpm-upgrade
|
||||
UNINSTALLER=/usr/lib/clash-verge-rev/clash-verge-service-uninstall
|
||||
|
||||
# Fields after the parenthesised command name, which may itself contain spaces.
|
||||
stat_field() {
|
||||
sed 's/.*) //' "/proc/$1/stat" 2>/dev/null | cut -d' ' -f"$2"
|
||||
}
|
||||
|
||||
if [ -f "$RECORD" ] && [ ! -L "$RECORD" ] && read -r txn_pid txn_start <"$RECORD"; then
|
||||
pid=$PPID
|
||||
depth=0
|
||||
while [ "$depth" -lt 4 ] && [ -n "$pid" ] && [ "$pid" -gt 1 ]; do
|
||||
if [ "$pid" = "$txn_pid" ] && [ "$(stat_field "$pid" 20)" = "$txn_start" ]; then
|
||||
rm -f "$RECORD"
|
||||
echo "Keeping the Clash Verge Service reinstalled by this upgrade."
|
||||
exit 0
|
||||
fi
|
||||
pid="$(stat_field "$pid" 2)"
|
||||
depth=$((depth + 1))
|
||||
done
|
||||
fi
|
||||
|
||||
exec "$UNINSTALLER" "$@"
|
||||
Reference in New Issue
Block a user