Files
tools-legacy/tools/public/fpagent/install.sh
T
adebisi-fa 0698a9c9a9 fix(fpagent): sweep scratch left by a SIGKILLed installer run
The EXIT trap cannot run on SIGKILL, so a killed run could leave its
fpagent-install.* temp dir behind. Sweep those before any network work,
scoped to our prefix and this user and only dirs older than a day so a
concurrent install is never touched.
2026-10-02 10:49:07 +01:00

111 lines
4.2 KiB
Bash
Executable File

#!/usr/bin/env bash
# install.sh — download and install the latest YOUreka Fingerprint Agent
# (fpagent) release on this machine.
#
# Hosted at https://tools.yrka.app/fpagent/install.sh and meant to be piped
# straight into bash on a field laptop:
#
# curl -fsSL https://tools.yrka.app/fpagent/install.sh | bash
#
# It downloads the bundle, verifies its sha256, then hands off to the bundle's
# own installer, which handles libfprint, the udev rule, plugdev and the
# systemd service. Every flag is forwarded to that installer, e.g.:
#
# curl -fsSL https://tools.yrka.app/fpagent/install.sh | bash -s -- --enable-service
# curl -fsSL https://tools.yrka.app/fpagent/install.sh | bash -s -- --check
#
# The private release is reached through the tools app, so no credentials are
# needed here.
set -euo pipefail
BASE="${FPAGENT_BASE_URL:-https://tools.yrka.app/fpagent}"
say() { printf '%s\n' "$*"; }
die() { printf '[FAIL] %s\n' "$*" >&2; exit 1; }
usage() {
cat <<EOF
Usage: curl -fsSL ${BASE}/install.sh | bash -s -- [installer options]
Downloads the latest fpagent release, verifies it, and runs its installer.
Options are forwarded to that installer:
--check preflight and report only; change nothing
--offline never touch the network; fail if dependencies are missing
--enable-service install and enable a systemd service (starts at boot)
--service-user NAME user for the service (default: the invoking user)
--install-path PATH binary destination (default: /usr/local/bin/fpagent)
--uninstall remove the binary, the udev rule and the service
-h, --help the installer's help
Environment:
FPAGENT_BASE_URL override the download base (default: ${BASE})
EOF
}
for arg in "$@"; do
case "$arg" in
-h | --help)
usage
exit 0
;;
esac
done
for cmd in curl tar sha256sum python3 find; do
command -v "$cmd" >/dev/null 2>&1 || die "$cmd is required but not installed"
done
tmpbase="${TMPDIR:-/tmp}"
# Sweep scratch left by an earlier run that was SIGKILLed: the EXIT trap cannot
# run then (that is the one signal it cannot catch). Scoped to our own prefix,
# this user, and dirs older than a day, so a concurrent install is never touched.
# Runs before any network work so cleanup is not skipped when the fetch fails.
find "$tmpbase" -maxdepth 1 -mindepth 1 -type d -uid "$(id -u)" \
-name 'fpagent-install.*' -mtime +0 -exec rm -rf {} + 2>/dev/null || true
# Offline bundles ship the libfprint .deb closure for a specific Ubuntu
# release; prefer the one matching this machine, else fall back to the generic
# online bundle (whose installer apt-get's the dependency).
codename="$(sed -n 's/^VERSION_CODENAME=//p' /etc/os-release 2>/dev/null | tr -d '"')"
say "Fetching the latest Fingerprint Agent release..."
meta="$(curl -fsSL "${BASE}/releases/latest")" || die "could not fetch the release list from ${BASE}"
readout="$(python3 -c '
import json, sys
codename = sys.argv[1]
release = json.loads(sys.argv[2])
assets = [a["name"] for a in release.get("assets", [])]
def pick(suffix):
return next((n for n in assets if n.endswith(suffix) and not n.endswith(".sha256")), "")
name = pick("-ubuntu-" + codename + "-x86_64.tar.gz") if codename else ""
if not name:
name = pick("-linux-x86_64.tar.gz")
print(release.get("tag", "") + "\t" + name)
' "$codename" "$meta")" || die "could not parse the release metadata"
tag="${readout%%$'\t'*}"
asset="${readout#*$'\t'}"
[ -n "$tag" ] && [ -n "$asset" ] || die "no compatible bundle in the latest release (x86_64 required)"
say " release ${tag}"
say " bundle ${asset}"
tmp="$(mktemp -d "$tmpbase/fpagent-install.XXXXXXXX")"
trap 'rm -rf "$tmp"' EXIT
get() { curl -fsSL "$1" -o "$2" || die "download failed: $1"; }
say "Downloading and verifying..."
get "${BASE}/releases/download/${tag}/${asset}" "${tmp}/${asset}"
get "${BASE}/releases/download/${tag}/${asset}.sha256" "${tmp}/${asset}.sha256"
(cd "$tmp" && sha256sum -c "${asset}.sha256") || die "checksum verification failed for ${asset}"
tar xzf "${tmp}/${asset}" -C "$tmp" || die "could not extract ${asset}"
[ -x "${tmp}/install.sh" ] || die "the bundle does not contain install.sh"
say "Running the installer (pass --enable-service to start at boot)..."
"${tmp}/install.sh" "$@"