b330faff03
Make the service build, run, and install on Linux as a first-class target while keeping the Windows Service + Event Log behaviour intact. - Build: drop the hardcoded win-x64 RID — single-file publish now works for any RID. publish.ps1 gains -Rid; new publish.sh for Linux hosts. - Diagnostics: DiagnosticSinkSelector picks the Error+ sink per host — Windows Event Log under the SCM, local syslog under systemd (Serilog.Sinks.SyslogMessages), none for interactive runs. The EventLog truncation helper is extracted so it is testable cross-OS. - Host: Program.cs registers AddSystemd() alongside AddWindowsService(). - Config: a RID-conditioned appsettings template ships Windows or Unix paths; both templates are schema-validated by a test. - Install: systemd unit (Type=exec) plus install.sh / uninstall.sh. Also fixes two cross-platform bugs found while testing: install.ps1 and uninstall.ps1 used New-EventLog / Remove-EventLog (absent in PowerShell 7), and the E2E sim launcher hardcoded Windows venv paths. - Docs updated across README, CLAUDE.md, and docs/ for dual-platform. 413 tests pass on Windows; 374 (all non-simulator) on Linux. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
135 lines
5.8 KiB
Bash
135 lines
5.8 KiB
Bash
#!/usr/bin/env bash
|
|
#
|
|
# install.sh — install the mbproxy service on a Linux / systemd host.
|
|
#
|
|
# The Linux counterpart of install.ps1. Copies the published binary to
|
|
# /opt/mbproxy, seeds the config at /etc/mbproxy/appsettings.json (preserving any
|
|
# existing one), creates the log and bundle-cache directories and the mbproxy
|
|
# service account, installs the systemd unit, and enables + starts the service.
|
|
#
|
|
# Re-running on an already-installed service is safe (idempotent): the binary is
|
|
# refreshed, an existing /etc/mbproxy/appsettings.json is preserved, and the
|
|
# service is restarted.
|
|
#
|
|
# Usage:
|
|
# sudo ./install.sh [--publish-dir DIR] [--no-start]
|
|
#
|
|
# --publish-dir DIR directory containing the published Mbproxy binary.
|
|
# Default: <repo>/publish-out/self-contained
|
|
# --no-start install and enable the unit but do not start it.
|
|
#
|
|
set -euo pipefail
|
|
|
|
# ── 0. Settings ──────────────────────────────────────────────────────────────
|
|
SERVICE_NAME="mbproxy"
|
|
SERVICE_USER="mbproxy"
|
|
INSTALL_DIR="/opt/mbproxy"
|
|
CONFIG_DIR="/etc/mbproxy"
|
|
LOG_DIR="/var/log/mbproxy"
|
|
CACHE_DIR="/var/cache/mbproxy"
|
|
UNIT_DEST="/etc/systemd/system/${SERVICE_NAME}.service"
|
|
|
|
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
repo_root="$(dirname "$script_dir")"
|
|
publish_dir="${repo_root}/publish-out/self-contained"
|
|
start_service=1
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--publish-dir) publish_dir="$2"; shift 2 ;;
|
|
--no-start) start_service=0; shift ;;
|
|
*) echo "Unknown argument: $1" >&2; exit 2 ;;
|
|
esac
|
|
done
|
|
|
|
# ── 1. Pre-flight checks ─────────────────────────────────────────────────────
|
|
if [[ "$(id -u)" -ne 0 ]]; then
|
|
echo "install.sh must run as root (use sudo)." >&2
|
|
exit 1
|
|
fi
|
|
|
|
binary_src="${publish_dir}/Mbproxy"
|
|
if [[ ! -f "$binary_src" ]]; then
|
|
echo "Mbproxy binary not found at '${binary_src}'." >&2
|
|
echo "Run install/publish.sh first, or pass --publish-dir." >&2
|
|
exit 1
|
|
fi
|
|
|
|
unit_src="${script_dir}/mbproxy.service"
|
|
config_src="${publish_dir}/appsettings.json"
|
|
if [[ ! -f "$unit_src" ]]; then
|
|
echo "Unit file not found at '${unit_src}'." >&2
|
|
exit 1
|
|
fi
|
|
|
|
echo "Installing ${SERVICE_NAME} service..."
|
|
echo " Publish dir : ${publish_dir}"
|
|
echo " Install dir : ${INSTALL_DIR}"
|
|
echo " Config dir : ${CONFIG_DIR}"
|
|
|
|
# ── 2. Service account ───────────────────────────────────────────────────────
|
|
if ! id -u "$SERVICE_USER" >/dev/null 2>&1; then
|
|
echo "Creating service account '${SERVICE_USER}'..."
|
|
useradd --system --no-create-home --shell /usr/sbin/nologin "$SERVICE_USER"
|
|
else
|
|
echo "Service account '${SERVICE_USER}' already exists."
|
|
fi
|
|
|
|
# ── 3. Stop the service if running (so the binary can be replaced) ───────────
|
|
if systemctl is-active --quiet "$SERVICE_NAME" 2>/dev/null; then
|
|
echo "Stopping running service '${SERVICE_NAME}'..."
|
|
systemctl stop "$SERVICE_NAME"
|
|
fi
|
|
|
|
# ── 4. Directories ───────────────────────────────────────────────────────────
|
|
install -d -m 0755 "$INSTALL_DIR"
|
|
install -d -m 0755 "$CONFIG_DIR"
|
|
install -d -m 0750 -o "$SERVICE_USER" -g "$SERVICE_USER" "$LOG_DIR"
|
|
install -d -m 0750 -o "$SERVICE_USER" -g "$SERVICE_USER" "$CACHE_DIR"
|
|
|
|
# ── 5. Binary ────────────────────────────────────────────────────────────────
|
|
echo "Copying binary to '${INSTALL_DIR}/Mbproxy'..."
|
|
install -m 0755 "$binary_src" "${INSTALL_DIR}/Mbproxy"
|
|
|
|
# ── 6. Config (preserve an existing one) ─────────────────────────────────────
|
|
config_dest="${CONFIG_DIR}/appsettings.json"
|
|
if [[ -f "$config_dest" ]]; then
|
|
echo "Preserving existing config at '${config_dest}'."
|
|
elif [[ -f "$config_src" ]]; then
|
|
echo "Seeding config template to '${config_dest}'..."
|
|
install -m 0644 "$config_src" "$config_dest"
|
|
else
|
|
echo "WARNING: no appsettings.json in '${publish_dir}' — create '${config_dest}' manually." >&2
|
|
fi
|
|
|
|
# ── 7. systemd unit ──────────────────────────────────────────────────────────
|
|
echo "Installing systemd unit to '${UNIT_DEST}'..."
|
|
install -m 0644 "$unit_src" "$UNIT_DEST"
|
|
systemctl daemon-reload
|
|
systemctl enable "$SERVICE_NAME" >/dev/null
|
|
|
|
# ── 8. Start ─────────────────────────────────────────────────────────────────
|
|
if [[ "$start_service" -eq 1 ]]; then
|
|
echo "Starting service '${SERVICE_NAME}'..."
|
|
systemctl start "$SERVICE_NAME"
|
|
sleep 1
|
|
if systemctl is-active --quiet "$SERVICE_NAME"; then
|
|
echo "Service '${SERVICE_NAME}' is running."
|
|
else
|
|
echo "WARNING: service '${SERVICE_NAME}' did not reach active state." >&2
|
|
echo "Check: journalctl -u ${SERVICE_NAME} -e" >&2
|
|
fi
|
|
fi
|
|
|
|
echo ""
|
|
echo "Install complete."
|
|
echo " Config : ${config_dest}"
|
|
echo " Logs : ${LOG_DIR}"
|
|
echo " Binary : ${INSTALL_DIR}/Mbproxy"
|
|
echo ""
|
|
echo "Next steps:"
|
|
echo " 1. Edit '${config_dest}' to configure your PLC list and BCD tags."
|
|
echo " 2. Restart: sudo systemctl restart ${SERVICE_NAME}"
|
|
echo " 3. Logs: journalctl -u ${SERVICE_NAME} -f"
|
|
echo " 4. Status: http://localhost:8080/"
|