#!/usr/bin/env bash # # Pulse Unified Agent Installer # Supports: Linux (systemd), macOS (launchd), Synology (upstart) # # Usage: # curl -fsSL http://pulse/install.sh | bash -s -- --url http://pulse --token [options] # # Options: # --enable-host Enable host metrics (default: true) # --enable-docker Enable docker metrics (default: false) # --interval Reporting interval (default: 30s) # --uninstall Remove the agent set -euo pipefail # --- Check Root --- if [[ $EUID -ne 0 ]]; then echo "This script must be run as root. Please use sudo." exit 1 fi # --- Configuration --- AGENT_NAME="pulse-agent" BINARY_NAME="pulse-agent" INSTALL_DIR="/usr/local/bin" LOG_FILE="/var/log/${AGENT_NAME}.log" # Defaults PULSE_URL="" PULSE_TOKEN="" INTERVAL="30s" ENABLE_HOST="true" ENABLE_DOCKER="false" UNINSTALL="false" INSECURE="false" # --- Helper Functions --- log_info() { printf "[INFO] %s\n" "$1"; } log_warn() { printf "[WARN] %s\n" "$1"; } log_error() { printf "[ERROR] %s\n" "$1"; } fail() { log_error "$1" if [[ -t 0 ]]; then read -p "Press Enter to exit..." elif [[ -e /dev/tty ]]; then read -p "Press Enter to exit..." < /dev/tty fi exit 1 } # --- Parse Arguments --- while [[ $# -gt 0 ]]; do case $1 in --url) PULSE_URL="$2"; shift 2 ;; --token) PULSE_TOKEN="$2"; shift 2 ;; --interval) INTERVAL="$2"; shift 2 ;; --enable-host) ENABLE_HOST="true"; shift ;; --disable-host) ENABLE_HOST="false"; shift ;; --enable-docker) ENABLE_DOCKER="true"; shift ;; --disable-docker) ENABLE_DOCKER="false"; shift ;; --insecure) INSECURE="true"; shift ;; --uninstall) UNINSTALL="true"; shift ;; *) fail "Unknown argument: $1" ;; esac done # --- Uninstall Logic --- if [[ "$UNINSTALL" == "true" ]]; then log_info "Uninstalling ${AGENT_NAME}..." # Systemd if command -v systemctl >/dev/null 2>&1; then systemctl stop "${AGENT_NAME}" 2>/dev/null || true systemctl disable "${AGENT_NAME}" 2>/dev/null || true rm -f "/etc/systemd/system/${AGENT_NAME}.service" systemctl daemon-reload 2>/dev/null || true fi # Launchd (macOS) if [[ "$(uname -s)" == "Darwin" ]]; then PLIST="/Library/LaunchDaemons/com.pulse.agent.plist" launchctl unload "$PLIST" 2>/dev/null || true rm -f "$PLIST" fi # Upstart (Synology) if [[ -f "/etc/init/${AGENT_NAME}.conf" ]]; then initctl stop "${AGENT_NAME}" 2>/dev/null || true rm -f "/etc/init/${AGENT_NAME}.conf" fi rm -f "${INSTALL_DIR}/${BINARY_NAME}" log_info "Uninstallation complete." exit 0 fi # --- Validation --- if [[ -z "$PULSE_URL" || -z "$PULSE_TOKEN" ]]; then fail "Missing required arguments: --url and --token" fi # --- Download --- OS=$(uname -s | tr '[:upper:]' '[:lower:]') ARCH=$(uname -m) case "$ARCH" in x86_64) ARCH="amd64" ;; aarch64|arm64) ARCH="arm64" ;; *) fail "Unsupported architecture: $ARCH" ;; esac DOWNLOAD_URL="${PULSE_URL}/download/${BINARY_NAME}?os=${OS}&arch=${ARCH}" log_info "Downloading agent from ${DOWNLOAD_URL}..." # Create temp file TMP_BIN=$(mktemp) chmod +x "$TMP_BIN" CURL_ARGS="-fsSL" if [[ "$INSECURE" == "true" ]]; then CURL_ARGS="-k $CURL_ARGS"; fi if ! curl $CURL_ARGS -o "$TMP_BIN" "$DOWNLOAD_URL"; then fail "Download failed. Check URL and connectivity." fi # Install Binary log_info "Installing binary to ${INSTALL_DIR}/${BINARY_NAME}..." mkdir -p "$INSTALL_DIR" mv "$TMP_BIN" "${INSTALL_DIR}/${BINARY_NAME}" # --- Legacy Cleanup --- # Remove old agents if they exist to prevent conflicts log_info "Checking for legacy agents..." # Legacy Host Agent if command -v systemctl >/dev/null 2>&1; then if systemctl is-active --quiet pulse-host-agent 2>/dev/null || systemctl is-enabled --quiet pulse-host-agent 2>/dev/null; then log_warn "Removing legacy pulse-host-agent..." systemctl stop pulse-host-agent 2>/dev/null || true systemctl disable pulse-host-agent 2>/dev/null || true rm -f /etc/systemd/system/pulse-host-agent.service rm -f /usr/local/bin/pulse-host-agent fi if systemctl is-active --quiet pulse-docker-agent 2>/dev/null || systemctl is-enabled --quiet pulse-docker-agent 2>/dev/null; then log_warn "Removing legacy pulse-docker-agent..." systemctl stop pulse-docker-agent 2>/dev/null || true systemctl disable pulse-docker-agent 2>/dev/null || true rm -f /etc/systemd/system/pulse-docker-agent.service rm -f /usr/local/bin/pulse-docker-agent fi systemctl daemon-reload 2>/dev/null || true fi # Legacy macOS if [[ "$OS" == "darwin" ]]; then if launchctl list | grep -q "com.pulse.host-agent"; then log_warn "Removing legacy com.pulse.host-agent..." launchctl unload /Library/LaunchDaemons/com.pulse.host-agent.plist 2>/dev/null || true rm -f /Library/LaunchDaemons/com.pulse.host-agent.plist rm -f /usr/local/bin/pulse-host-agent fi fi # --- Service Installation --- # 1. macOS (Launchd) if [[ "$OS" == "darwin" ]]; then PLIST="/Library/LaunchDaemons/com.pulse.agent.plist" log_info "Configuring Launchd service at $PLIST..." cat > "$PLIST" < Label com.pulse.agent ProgramArguments ${INSTALL_DIR}/${BINARY_NAME} --url ${PULSE_URL} --token ${PULSE_TOKEN} --interval ${INTERVAL} --enable-host=${ENABLE_HOST} --enable-docker=${ENABLE_DOCKER} --insecure=${INSECURE} RunAtLoad KeepAlive StandardOutPath ${LOG_FILE} StandardErrorPath ${LOG_FILE} EOF chmod 644 "$PLIST" launchctl unload "$PLIST" 2>/dev/null || true launchctl load -w "$PLIST" log_info "Service started." exit 0 fi # 2. Synology (Upstart) if [[ -d /usr/syno/etc/rc.sysv ]]; then CONF="/etc/init/${AGENT_NAME}.conf" log_info "Configuring Upstart service at $CONF..." cat > "$CONF" <> ${LOG_FILE} 2>&1 EOF initctl stop "${AGENT_NAME}" 2>/dev/null || true initctl start "${AGENT_NAME}" log_info "Service started." exit 0 fi # 3. Linux (Systemd) if command -v systemctl >/dev/null 2>&1; then UNIT="/etc/systemd/system/${AGENT_NAME}.service" log_info "Configuring Systemd service at $UNIT..." cat > "$UNIT" <