Skip to content

Add repair/cleanup script for half-installed RMM and Zabbix hosts - #2

Merged
MarkLFT merged 1 commit into
trmm-linux-no-meshfrom
rmm-zabbix-repair-script
Aug 2, 2026
Merged

Add repair/cleanup script for half-installed RMM and Zabbix hosts#2
MarkLFT merged 1 commit into
trmm-linux-no-meshfrom
rmm-zabbix-repair-script

Conversation

@MarkLFT

Copy link
Copy Markdown
Owner

Stacked on #1 (base is trmm-linux-no-mesh, so this shows only its own commit). GitHub will retarget it to main automatically once #1 merges.

What this is

repair-rmm-zabbix-linux.sh — diagnoses and repairs a client server left half-installed by an interrupted or failed TacticalRMM agent or Zabbix Agent 2 install, and can strip either stack back to nothing so a clean install can follow.

It never installs either agent. That stays with install-tacticalrmm-agent-linux.sh and install-zabbix-agent-linux-tactical-rmm.sh; this script's job is to get a messy host back to a known state so those can run cleanly.

Actions

ActionWhat it does
reportRead-only diagnosis (default). Exit 0 = healthy/absent, 1 = problems found — so it doubles as a TacticalRMM check
repairFixes what can be fixed safely, then re-reports
clean-trmm / clean-zabbix / clean-allRemoves the named stack(s)

What it detects

RMM agent: binary present but never registered · config present with the binary missing · missing or orphaned systemd unit · failed service · an empty /opt/tacticalmesh left by a failed mesh install (exactly the wreckage the bug in #1 produced) · stale build leftovers in /tmp.

Zabbix: half-installed package · broken dpkg state · legacy v1 zabbix-agent alongside Agent 2, which conflicts on port 10050 · config missing Server=/ServerActive=/Hostname= · missing plugins.d Include · CHANGE_ME placeholder credentials · apt repo added without the agent · and the classic crash loop, a plugin config referencing a loadable plugin whose package is not installed.

repair reconciles a broken dpkg state, recreates the tacticalagent unit, starts services that should be running, renames orphaned plugin configs to .disabled so the agent stops crash-looping, adds the missing Include, and clears build leftovers. Anything it cannot fix safely is reported with a next step rather than guessed at.

Safety

This script deletes things, so the defaults are deliberately conservative:

  • report is the default and is read-only — nothing is removed by accident.
  • Every destructive action writes a timestamped config backup to /var/backupsfirst, and aborts if the backup fails.
  • A clean-* action refuses to touch a stack that looks healthy unless force is passed. A scheduled run that drifts onto a healthy host must not wipe a working agent.
  • Non-interactive runs are refused outright without an explicit yes. Interactive runs require typing REMOVE.
  • clean-zabbix leaves the apt repo in place (a reinstall needs it); clean-trmm leaves /usr/local/go.

Uses set -uo pipefail with explicit || die / || warn rather than -e, matching the TRMM installer and updater in this repo — on a deliberately broken host, a probe returning non-zero is normal input, not a failure.

Test results

Debian 12 containers — 9 scenarios, 29 assertions, all passing:

ScenarioVerified
Clean hostboth stacks reported absent, exit 0
Binary present, never registereddetected, state partial, exit 1
Binary + config, no unitdetected as auto-repairable; repair writes the unit with the correct ExecStart
Config present, binary missingdetected as broken
Stale build leftoversdetected and cleared by repair
Empty /opt/tacticalmeshdetected and removed
Zabbix partial configmissing Server=, ServerActive=, CHANGE_ME placeholder and missing Include all detected; repair adds the Include and backs the config up first
Destructive safetyrefuses without confirmation and leaves the agent untouched; with yes takes a backup then removes
Unknown actionrejected, non-zero exit

The healthy-stack guard was verified separately (5/5): yes will not remove a healthy stack — only force will, and neither empty nor yes gets through.

The container has systemd installed but not booted, which also confirmed the script degrades sanely when systemctl cannot work at all.

Not yet exercised on a real host: anything needing a live systemd — the service-restart paths and the healthy state itself. Progress.md records that.

bash -n and shellcheck 0.10.0 clean. README and CLAUDE.md updated.

Diagnoses and repairs a client server left in a partial state by an interrupted
or failed TacticalRMM agent or Zabbix Agent 2 install, and can strip either
stack back to nothing so a clean install can follow. It never installs an agent
— the existing installers do that.
Detects, for the RMM agent: binary present but never registered, config present
with the binary missing, a missing or orphaned systemd unit, a failed service,
an empty /opt/tacticalmesh left by a failed mesh install, and stale build
leftovers in /tmp. For Zabbix: a half-installed package, a broken dpkg state,
the legacy v1 agent alongside Agent 2 (they conflict on port 10050), a config
missing Server/ServerActive/Hostname, a missing plugins.d Include, CHANGE_ME
placeholder credentials, the apt repo added without the agent, and the classic
crash loop — a plugin config referencing a loadable plugin whose package is not
installed.
repair reconciles a broken dpkg state, recreates the tacticalagent unit, starts
services that should be running, disables orphaned plugin configs, adds the
missing Include, and clears build leftovers. Anything it cannot fix safely is
reported with a next step.
Safety: report is the default and is read-only, exiting 0 when healthy/absent
and 1 when problems are found so it doubles as a TacticalRMM check. Destructive
actions back up all configuration to /var/backups first, refuse to touch a stack
that looks healthy unless "force" is given, and refuse to run non-interactively
without an explicit "yes" — a stray scheduled run must not wipe a working agent.
Interactive runs require typing REMOVE.
Uses set -uo pipefail with explicit || die / || warn rather than -e, matching the
TRMM installer and updater: on a broken host a probe returning non-zero is normal
input, not a failure.
Tested in Debian 12 containers — 9 scenarios, 29 assertions, all passing, plus
5/5 on the healthy-stack guard. Service-restart paths and the healthy state
itself still need a host with a live systemd.
@MarkLFT
MarkLFT merged commit 9ec0c6d into trmm-linux-no-meshAug 2, 2026
1 check passed
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@MarkLFT