diff --git a/install.sh b/install.sh index 529caf3..b6443ec 100755 --- a/install.sh +++ b/install.sh @@ -64,6 +64,14 @@ detect_platform() { fi } +validate_service_manager() { + [[ "$PLATFORM" != "linux" || "$NO_SERVICE" == "1" ]] && return 0 + command -v systemctl >/dev/null 2>&1 \ + || fail 'systemd is required for a production Linux install; use --no-service only for development' + [[ -d /run/systemd/system ]] \ + || fail 'systemd is not running on this Linux host; use --no-service only for development' +} + java_major() { local java_bin="${1:-java}" "$java_bin" -version 2>&1 | awk -F'[".]' '/version/ {print $2; exit}' @@ -294,10 +302,11 @@ shell_setting() { prepare_layout() { if [[ "$PLATFORM" == "linux" ]]; then ERP_USER="${ERP_SERVICE_USER:-kaidi-erp}" - ERP_GROUP="$ERP_USER" [[ "$ERP_USER" =~ ^[a-z_][a-z0-9_-]*[$]?$ ]] || fail 'invalid Linux service user name' id "$ERP_USER" >/dev/null 2>&1 \ || useradd --system --home-dir "$INSTALL_ROOT" --shell /usr/sbin/nologin "$ERP_USER" + ERP_GROUP="$(id -gn "$ERP_USER" 2>/dev/null)" \ + || fail "unable to resolve the primary group for Linux service user: $ERP_USER" CONFIG_ROOT="${ERP_CONFIG_ROOT:-/etc/kaidi-erp}" STATE_ROOT="${ERP_STATE_ROOT:-/var/lib/kaidi-erp}" LOG_ROOT="${ERP_LOG_ROOT:-/var/log/kaidi-erp}" @@ -506,6 +515,7 @@ detect_lan_address() { main() { detect_platform + validate_service_manager if [[ -z "$INSTALL_ROOT" ]]; then if [[ "$PLATFORM" == "linux" ]]; then INSTALL_ROOT=/opt/kaidi-erp diff --git a/tests/release-scripts.test.sh b/tests/release-scripts.test.sh index 616d5f9..161aac9 100755 --- a/tests/release-scripts.test.sh +++ b/tests/release-scripts.test.sh @@ -456,6 +456,19 @@ test_installer_requires_explicit_gitea_url() ( [[ "$status" -ne 0 && "$output" == *'Gitea URL is required'* ]] ) +test_linux_service_preflight_requires_systemd() ( + local tmp output status=0 + tmp="$(mktemp -d "${TMPDIR:-/tmp}/erp-systemd-test.XXXXXX")" || return 1 + trap 'rm -rf "$tmp"' EXIT + mkdir -p "$tmp/bin" + source "$PROJECT_ROOT/install.sh" + PLATFORM=linux + NO_SERVICE=0 + output="$(PATH="$tmp/bin" validate_service_manager 2>&1)" || status=$? + [[ "$status" -ne 0 && "$output" == *'systemd'* ]] || return 1 + NO_SERVICE=1 PATH="$tmp/bin" validate_service_manager +) + test_no_service_install_disables_online_update() ( local tmp tmp="$(mktemp -d "${TMPDIR:-/tmp}/erp-no-service-test.XXXXXX")" || return 1 @@ -506,6 +519,7 @@ run_test 'update helper rolls back an unhealthy release end to end' test_update_ run_test 'update helper rejects a concurrent process' test_update_lock_rejects_concurrent_process run_test 'installer moves database setup to the web wizard' test_installer_moves_database_setup_to_web_wizard run_test 'installer requires an explicit Gitea URL' test_installer_requires_explicit_gitea_url +run_test 'Linux production install requires systemd' test_linux_service_preflight_requires_systemd run_test 'no-service install disables online update' test_no_service_install_disables_online_update run_test 'release workflow uses the scoped Gitea job token' test_release_workflow_uses_scoped_job_token run_test 'installer starts correctly when piped to bash' test_installer_runs_when_piped_to_bash