#!/usr/bin/env bash # Build socktop + socktop_agent from source and install them. # # Works on Linux (x86_64, arm64/armv7, riscv64) and macOS. Handles fresh # installs and upgrades; if a systemd socktop-agent service is present, its # binary is replaced in place and the service restarted. # # ./scripts/install.sh # build HEAD of the repo you're in # ./scripts/install.sh --ref v1.60.0 # build a tag/branch (clones if needed) # ./scripts/install.sh --ref housekeeping-p2 # ./scripts/install.sh --prefix ~/.local/bin --no-service # set -euo pipefail REPO_URL="https://github.com/jasonwitty/socktop.git" REF="" PREFIX="" NO_SERVICE=0 SRC_DIR="${SOCKTOP_SRC_DIR:-$HOME/.cache/socktop-src}" while [ $# -gt 0 ]; do case "$1" in --ref) REF="$2"; shift 2 ;; --prefix) PREFIX="$2"; shift 2 ;; --no-service) NO_SERVICE=1; shift ;; -h|--help) grep '^#' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;; *) echo "unknown argument: $1" >&2; exit 2 ;; esac done say() { printf '\033[1;36m==>\033[0m %s\n' "$*"; } warn() { printf '\033[1;33mwarn:\033[0m %s\n' "$*" >&2; } die() { printf '\033[1;31merror:\033[0m %s\n' "$*" >&2; exit 1; } OS="$(uname -s)" ARCH="$(uname -m)" # ---------- toolchain ---------- command -v git >/dev/null || die "git is required" if ! command -v cargo >/dev/null; then # rustup may be installed but not on PATH in this shell [ -f "$HOME/.cargo/env" ] && . "$HOME/.cargo/env" fi if ! command -v cargo >/dev/null; then say "Rust toolchain not found — installing via rustup (stable, default profile)" curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal . "$HOME/.cargo/env" fi command -v cc >/dev/null || warn "no C compiler found (apt: build-essential / brew: xcode-select --install) — the build may fail" case "$ARCH" in riscv64*) # protoc-bin-vendored ships no riscv64 binary; the build falls back to # the system protoc (see build.rs). command -v protoc >/dev/null || die "riscv64 needs a system protoc: sudo apt install protobuf-compiler" ;; esac # ---------- source ---------- # If run from inside a socktop checkout and no --ref given, build that tree # as-is (whatever is checked out, including local changes). if [ -z "$REF" ] && git rev-parse --show-toplevel >/dev/null 2>&1 \ && grep -qs '^name = "socktop"' "$(git rev-parse --show-toplevel)/socktop/Cargo.toml" 2>/dev/null; then SRC_DIR="$(git rev-parse --show-toplevel)" say "Building the current checkout: $SRC_DIR ($(git -C "$SRC_DIR" describe --always --dirty 2>/dev/null))" else REF="${REF:-master}" if [ ! -d "$SRC_DIR/.git" ]; then say "Cloning $REPO_URL -> $SRC_DIR" git clone "$REPO_URL" "$SRC_DIR" fi say "Checking out $REF" git -C "$SRC_DIR" fetch --tags origin git -C "$SRC_DIR" checkout -q "$REF" # fast-forward when REF is a branch git -C "$SRC_DIR" merge --ff-only "origin/$REF" >/dev/null 2>&1 || true fi # ---------- build ---------- say "Building release binaries (this can take a while on SBCs)" ( cd "$SRC_DIR" && cargo build --release -p socktop -p socktop_agent ) CLIENT="$SRC_DIR/target/release/socktop" AGENT="$SRC_DIR/target/release/socktop_agent" # ---------- install ---------- if [ -z "$PREFIX" ]; then PREFIX="/usr/local/bin" fi SUDO="" if [ ! -w "$PREFIX" ]; then if command -v sudo >/dev/null; then SUDO="sudo"; else PREFIX="$HOME/.local/bin"; mkdir -p "$PREFIX" warn "no sudo — installing to $PREFIX (ensure it is on your PATH)" fi fi say "Installing to $PREFIX" $SUDO install -m 755 "$CLIENT" "$PREFIX/socktop" $SUDO install -m 755 "$AGENT" "$PREFIX/socktop_agent" # ---------- systemd service (Linux only) ---------- if [ "$OS" = "Linux" ] && [ "$NO_SERVICE" -eq 0 ] \ && command -v systemctl >/dev/null \ && systemctl list-unit-files 2>/dev/null | grep -q '^socktop-agent\.service'; then # The deb package's unit points at its own binary path; replace it in place # so the running service picks up this build. UNIT_BIN="$(systemctl show -p ExecStart socktop-agent.service 2>/dev/null \ | sed -n 's/.*path=\([^ ;]*\).*/\1/p' | head -1)" if [ -n "$UNIT_BIN" ] && [ "$UNIT_BIN" != "$PREFIX/socktop_agent" ]; then say "Refreshing systemd service binary at $UNIT_BIN" $SUDO systemctl stop socktop-agent.service $SUDO install -m 755 "$AGENT" "$UNIT_BIN" $SUDO systemctl start socktop-agent.service else say "Restarting socktop-agent.service" $SUDO systemctl restart socktop-agent.service fi sleep 1 systemctl --no-pager -l status socktop-agent.service | head -5 || true fi say "Installed:" "$PREFIX/socktop" --version "$PREFIX/socktop_agent" --version