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:
@@ -550,9 +550,16 @@ const SERVICE_BINARIES = [
|
||||
'clash-verge-service-uninstall',
|
||||
]
|
||||
|
||||
// Linux packages install the uninstaller under /usr/lib behind a wrapper sidecar; see
|
||||
// src-tauri/packages/linux/service-uninstall.sh and the files entries in tauri.linux.conf.json.
|
||||
const LINUX_UNINSTALLER_FILE = 'clash-verge-service-uninstall-bin'
|
||||
|
||||
function serviceFileInfo(name) {
|
||||
const ext = platform === 'win32' ? '.exe' : ''
|
||||
const suffix = platform === 'linux' ? `-${SIDECAR_HOST}` : ''
|
||||
if (platform === 'linux' && name === 'clash-verge-service-uninstall') {
|
||||
return { sourceFile: name, targetFile: LINUX_UNINSTALLER_FILE }
|
||||
}
|
||||
return {
|
||||
sourceFile: `${name}${ext}`,
|
||||
targetFile: `${name}${suffix}${ext}`,
|
||||
@@ -573,6 +580,22 @@ async function findExtractedFile(dir, fileName) {
|
||||
}
|
||||
|
||||
async function resolveServiceBundle() {
|
||||
await fetchServiceBundle()
|
||||
if (platform === 'linux') {
|
||||
const wrapper = path.join(
|
||||
SERVICE_DIR,
|
||||
`clash-verge-service-uninstall-${SIDECAR_HOST}`,
|
||||
)
|
||||
await fsp.copyFile(
|
||||
path.join(cwd, 'src-tauri', 'packages', 'linux', 'service-uninstall.sh'),
|
||||
wrapper,
|
||||
)
|
||||
await fsp.chmod(wrapper, 0o755)
|
||||
await updateHashCache(wrapper)
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchServiceBundle() {
|
||||
const files = SERVICE_BINARIES.map((name) => {
|
||||
const info = serviceFileInfo(name)
|
||||
return {
|
||||
|
||||
@@ -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" "$@"
|
||||
@@ -11,7 +11,10 @@
|
||||
"conflicts": ["clash-verge"],
|
||||
"replaces": ["clash-verge"],
|
||||
"postInstallScript": "./packages/linux/post-install.sh",
|
||||
"preRemoveScript": "./packages/linux/pre-remove.sh"
|
||||
"preRemoveScript": "./packages/linux/pre-remove.sh",
|
||||
"files": {
|
||||
"/usr/lib/clash-verge-rev/clash-verge-service-uninstall": "./sidecar/clash-verge-service-uninstall-bin"
|
||||
}
|
||||
},
|
||||
"rpm": {
|
||||
"depends": ["openssl", "libayatana-appindicator-gtk3"],
|
||||
@@ -21,7 +24,10 @@
|
||||
"conflicts": ["clash-verge"],
|
||||
"obsoletes": ["clash-verge"],
|
||||
"postInstallScript": "./packages/linux/post-install-rpm.sh",
|
||||
"preRemoveScript": "./packages/linux/pre-remove.sh"
|
||||
"preRemoveScript": "./packages/linux/pre-remove.sh",
|
||||
"files": {
|
||||
"/usr/lib/clash-verge-rev/clash-verge-service-uninstall": "./sidecar/clash-verge-service-uninstall-bin"
|
||||
}
|
||||
}
|
||||
},
|
||||
"externalBin": [
|
||||
|
||||
Reference in New Issue
Block a user