diff --git a/README.md b/README.md index 0bffda9..e8ff8a4 100644 --- a/README.md +++ b/README.md @@ -2684,6 +2684,7 @@ Eine Dateiauswahl mit Verzeichnisnavigation ist eingebaut. | `firewall [check\|open\|close]` | prüfen, öffnen und nicht mehr Benötigtes wieder schließen (firewalld, ufw, nftables, iptables); `close --keep-admin` lässt den Adminport offen | | `shell` | Root-Shell im Checkmk-Container | | `omd …` | beliebiges `omd`-Kommando im Container | +| `ports [--free]` | wer belegt 80/443/5000/8000 – und lokales Checkmk stilllegen, ohne Daten zu löschen | | `noproxy [--export\|--fix]` | prüfen, ob lokale Adressen am HTTP-Proxy vorbeigehen; eintragen in profile.d, `.bashrc`, `/etc/environment` oder die systemd-Unit | Globale Optionen: `--env-file DATEI`, `-y/--yes` (keine Rückfragen, z. B. für @@ -3459,6 +3460,68 @@ Nützliche Kommandos: docker exec -it checkmk omd su cmk # bzw. podman exec … ``` +### 20.1 Port 5000 (oder 80/443) ist belegt – aber von wem? + +Auf einem Rechner, auf dem Checkmk vorher **direkt installiert** war, hält die +alte Instanz Port 5000 weiter besetzt; ein Apache aus der Grundinstallation +belegt gern 80 und 443. Der Container startet dann nicht, und die Suche ist +mühsam – `ss` zeigt den Prozessnamen nur mit root-Rechten. + +```bash +./scripts/cmk-manage.sh ports +``` + +``` +Belegte Ports + PORT ZWECK PROGRAMM UNIT/SCOPE + 80 HTTP und Lets-Encrypt-Pruefung httpd httpd.service + 443 HTTPS (Checkmk, Zentrale, weitere httpd httpd.service + 81 Adminoberflaeche des Proxy Manage frei + 5000 Checkmk direkt - gehoert hinter d apache2 omd.service + +Direkt installiertes Checkmk + Version : OMD - Open Monitoring Distribution Version 2.3.0p23.cre + alt laeuft Autostart: on + zweitalt gestoppt Autostart: on +``` + +Die **Unit** kommt dabei aus `/proc//cgroup` – die Datei ist lesbar, ohne +root zu sein. Damit steht auch ohne `sudo` da, welcher Dienst es ist. + +### 20.2 Die lokale Instanz stilllegen – ohne die Daten anzufassen + +```bash +sudo ./scripts/cmk-manage.sh ports --free # nur den Vorschlag zeigen +sudo ./scripts/cmk-manage.sh ports --free --apply +``` + +``` +Vorschlag + omd stop alt + omd config alt set AUTOSTART off + omd config zweitalt set AUTOSTART off + systemctl disable --now httpd.service +``` + +**Gelöscht wird nichts.** `omd stop` hält die Site nur an, `AUTOSTART=off` +verhindert den Start nach einem Neustart. `/omd/sites/…` bleibt unangetastet, +die Daten lassen sich also weiterhin in den Container holen – entweder direkt +oder über ein Bundle vom `migrate_creator.sh` +([Kapitel 17](#17-migration-einer-direktinstallation-migrate_creatorsh)): + +```bash +./scripts/cmk-manage.sh import --file +``` + +Zwei Sicherungen sind eingebaut: Gestoppt wird nur, was auch läuft, und ein +`.scope` (etwa eine Login-Sitzung) wird nie angeboten – abschalten lässt sich +nur, was eine echte Unit ist. Container-Dienste (`docker.service`, +`podman.socket` …) bleiben ebenfalls außen vor, sonst legte man sich den +eigenen Stack still. + +In der Oberfläche liegt das im Hauptmenü unter **Belegte Ports – lokales +Checkmk/Apache stilllegen**. + --- ## 21. Sicherheitshinweise diff --git a/README_en.md b/README_en.md index a74e98f..00a438a 100644 --- a/README_en.md +++ b/README_en.md @@ -2664,6 +2664,7 @@ A file chooser with directory navigation is built in. | `firewall [check\|open\|close]` | check, open, and close again what is no longer needed (firewalld, ufw, nftables, iptables); `close --keep-admin` keeps the admin port open | | `shell` | root shell in the Checkmk container | | `omd …` | any `omd` command inside the container | +| `ports [--free]` | what occupies 80/443/5000/8000 – and shut down a local Checkmk without deleting data | | `noproxy [--export\|--fix]` | check whether local addresses bypass the HTTP proxy; write it to profile.d, `.bashrc`, `/etc/environment` or the systemd unit | Global options: `--env-file FILE`, `-y/--yes` (no prompts, e.g. for cron jobs), @@ -3437,6 +3438,67 @@ Useful commands: docker exec -it checkmk omd su cmk # or podman exec … ``` +### 20.1 Port 5000 (or 80/443) is taken – but by what? + +On a machine where Checkmk was previously installed **directly**, the old +instance keeps holding port 5000; an Apache from the base installation likes to +occupy 80 and 443. The container then fails to start, and finding the culprit +is tedious – `ss` only shows the process name with root privileges. + +```bash +./scripts/cmk-manage.sh ports +``` + +``` +Belegte Ports + PORT ZWECK PROGRAMM UNIT/SCOPE + 80 HTTP und Lets-Encrypt-Pruefung httpd httpd.service + 443 HTTPS (Checkmk, Zentrale, weitere httpd httpd.service + 81 Adminoberflaeche des Proxy Manage frei + 5000 Checkmk direkt - gehoert hinter d apache2 omd.service + +Direkt installiertes Checkmk + Version : OMD - Open Monitoring Distribution Version 2.3.0p23.cre + alt laeuft Autostart: on + zweitalt gestoppt Autostart: on +``` + +The **unit** comes from `/proc//cgroup` – that file is readable without +being root. So even without `sudo` you get to see which service it is. + +### 20.2 Shutting the local instance down – without touching the data + +```bash +sudo ./scripts/cmk-manage.sh ports --free # only show the proposal +sudo ./scripts/cmk-manage.sh ports --free --apply +``` + +``` +Vorschlag + omd stop alt + omd config alt set AUTOSTART off + omd config zweitalt set AUTOSTART off + systemctl disable --now httpd.service +``` + +**Nothing is deleted.** `omd stop` merely halts the site, `AUTOSTART=off` +prevents it from starting after a reboot. `/omd/sites/…` stays untouched, so +the data can still be brought into the container – either directly or via a +bundle from `migrate_creator.sh` +([chapter 17](#17-migrating-a-bare-metal-installation-migrate_creatorsh)): + +```bash +./scripts/cmk-manage.sh import --file +``` + +Two safeguards are built in: only what is actually running gets stopped, and a +`.scope` (a login session, say) is never offered – only a real unit can be +disabled. Container services (`docker.service`, `podman.socket` …) are excluded +as well, or you would shut down your own stack. + +The GUI has this in the main menu under **Belegte Ports – lokales +Checkmk/Apache stilllegen**. + --- ## 21. Security notes diff --git a/scripts/cmk-manage.sh b/scripts/cmk-manage.sh index a87f616..317dcaf 100755 --- a/scripts/cmk-manage.sh +++ b/scripts/cmk-manage.sh @@ -64,6 +64,8 @@ KOMMANDOS - Stack - SSH niemals, fremde Freigaben bleiben unberuehrt. Der Adminport des Proxy Managers wird mit angeboten; --keep-admin laesst ihn offen + ports [--free] wer belegt 80/443/5000/8000? Direkt installiertes + Checkmk stilllegen, ohne Daten zu loeschen noproxy [--fix] pruefen, ob lokale Adressen am HTTP-Proxy vorbeigehen (Zwangsproxy: sonst laufen selbst Anfragen an 127.0.0.1 dorthin - sichtbar als "API-Fehler") @@ -7327,6 +7329,43 @@ gui_cert_self() { } # Bericht anzeigen; fehlt etwas, das Uebernehmen anbieten +# Wer belegt die Ports - und Angebot, es stillzulegen +gui_ports() { + local f rc=0 + f="$(mktemp)" + ( NO_COLOR=1 cmd_ports ) >"$f" 2>&1 || rc=$? + ui_text "Belegte Ports" "$f"; rm -f "$f" + + local vorschlag rc2=0 + vorschlag="$(mktemp)" + ( NO_COLOR=1 cmd_ports --free ) >"$vorschlag" 2>&1 || rc2=$? + if ! ( set +o pipefail; grep -q '^ omd \|^ systemctl ' "$vorschlag" ); then + rm -f "$vorschlag"; return 0 + fi + ui_text "Was stillgelegt werden koennte" "$vorschlag"; rm -f "$vorschlag" + + ui_yesno "Stilllegen" "Die gezeigten Dienste jetzt stilllegen? + +Es wird NICHTS geloescht. Eine direkt installierte Site wird nur +gestoppt und vom automatischen Start genommen - ihre Daten bleiben +und lassen sich weiterhin importieren." || return 0 + + local -a a=(ports --free --apply --yes) + if [ "$(id -u)" -eq 0 ]; then + ui_run "Stilllegen" "$SELF" ${SELF_ENV_ARR[@]+"${SELF_ENV_ARR[@]}"} "${a[@]}" || true + elif command -v sudo >/dev/null 2>&1; then + gui_run_interactive sudo -- "$SELF" ${SELF_ENV_ARR[@]+"${SELF_ENV_ARR[@]}"} "${a[@]}" + else + ui_msg "Rechte" "Dafuer werden root-Rechte benoetigt." + return 0 + fi + + f="$(mktemp)" + ( NO_COLOR=1 cmd_ports ) >"$f" 2>&1 || true + ui_text "Belegte Ports - Stand danach" "$f"; rm -f "$f" + return 0 +} + gui_firewall() { local tmp rc=0 tmp="$(mktemp)" @@ -7518,6 +7557,7 @@ Backups : $BACKUP_DIR" \ browser "Terminal-Browser (Proxy Manager lokal bedienen)" \ cert "Selbstsigniertes Zertifikat erzeugen" \ firewall "Firewall pruefen (welche Ports muessen offen sein)" \ + ports "Belegte Ports - lokales Checkmk/Apache stilllegen" \ config "Einstellungen (.env) - menuegefuehrt" \ shell "Root-Shell im Checkmk-Container" \ quit "Beenden")" || break @@ -7534,6 +7574,7 @@ Backups : $BACKUP_DIR" \ browser) gui_browser_menu || true ;; cert) gui_cert || true ;; firewall) gui_firewall || true ;; + ports) gui_ports || true ;; config) gui_settings_menu || true ;; shell) gui_need_container || continue gui_run_interactive cmd_shell ;; @@ -7614,6 +7655,192 @@ ${C_BLD}Auswertung${C_RST} EOF } +# ===================================================================== +# Wer belegt die Ports, und wie legt man ihn stumm? +# +# Auf einem Rechner, auf dem Checkmk vorher direkt installiert war, +# haelt die alte Instanz Port 5000 weiter besetzt - und ein Apache aus +# der Grundinstallation gern 80 und 443. Der Container startet dann +# nicht, und die Suche nach dem Schuldigen ist muehsam, weil "ss" den +# Prozessnamen nur mit root-Rechten zeigt. +# +# Geloescht wird hier NICHTS. Eine direkt installierte Site enthaelt +# Daten, die man spaeter importieren will - sie wird nur gestoppt und +# vom automatischen Start genommen. +# ===================================================================== + +# Wer lauscht auf diesem Port? -> "pid|programm|unit" +port_owner() { # port + local port="$1" line pid prog unit="" + line="" + if command -v ss >/dev/null 2>&1; then + line="$(ss -ltnpH "sport = :$port" 2>/dev/null | head -1)" + fi + if [ -z "$line" ] && command -v netstat >/dev/null 2>&1; then + line="$(netstat -ltnp 2>/dev/null | awk -v p=":$port\$" '$4 ~ p {print; exit}')" + fi + [ -n "$line" ] || return 1 + + pid="$(printf '%s' "$line" | sed -n 's/.*pid=\([0-9]*\).*/\1/p')" + if [ -z "$pid" ]; then + pid="$(printf '%s' "$line" | sed -n 's|.*[[:space:]]\([0-9]\{1,\}\)/.*|\1|p')" + fi + if [ -z "$pid" ] && command -v lsof >/dev/null 2>&1; then + pid="$(lsof -tiTCP:"$port" -sTCP:LISTEN 2>/dev/null | head -1)" + fi + + if [ -n "$pid" ] && [ -r "/proc/$pid/comm" ]; then + prog="$(cat "/proc/$pid/comm" 2>/dev/null)" + else + prog="$(printf '%s' "$line" | sed -n 's/.*users:((\"\([^\"]*\)\".*/\1/p')" + fi + + # Die systemd-Unit steht in der cgroup-Zeile - dafuer braucht es + # keine root-Rechte, anders als fuer den Prozessnamen aus ss. + if [ -n "$pid" ] && [ -r "/proc/$pid/cgroup" ]; then + unit="$(sed -n 's|.*/\([^/]*\.service\)$|\1|p' "/proc/$pid/cgroup" 2>/dev/null | head -1)" + if [ -z "$unit" ]; then + unit="$(sed -n 's|.*/\([^/]*\.scope\)$|\1|p' "/proc/$pid/cgroup" 2>/dev/null | head -1)" + fi + fi + printf '%s|%s|%s\n' "${pid:-?}" "${prog:-unbekannt}" "$unit" +} + +# Sites einer direkt installierten Checkmk-Instanz +local_omd_sites() { + command -v omd >/dev/null 2>&1 || return 0 + omd sites 2>/dev/null | awk 'NR>1 && $1 != "" {print $1}' +} + +local_omd_running() { # site + ( set +o pipefail; omd status "$1" 2>/dev/null | grep -qE '^Overall state:[[:space:]]*running' ) +} + +cmd_ports() { + local free="" apply="" + while [ $# -gt 0 ]; do + case "$1" in + --free) free=1; shift ;; + --apply) apply=1; free=1; shift ;; + --yes|-y) ASSUME_YES=1; shift ;; + --help|-h) +cat </dev/null | sed 's/.*: *//' || true)" + local st auto + for st in "${sites[@]}"; do + # Fehlt die Datei, liefert sed 2 - unter "set -e" waere hier + # sonst Schluss, mitten in der Ausgabe. + auto="$(sed -n "s/^CONFIG_AUTOSTART='\(.*\)'$/\1/p" \ + "/omd/sites/$st/etc/omd/site.conf" 2>/dev/null || true)" + printf ' %-16s %-12s Autostart: %s\n' "$st" \ + "$(local_omd_running "$st" && echo laeuft || echo 'gestoppt')" "${auto:-?}" + done + fi + + if [ "$belegt" -eq 0 ] && [ "${#sites[@]}" -eq 0 ]; then + echo; ok "Kein Port belegt, keine direkt installierte Instanz."; echo + return 0 + fi + + if [ -z "$free" ]; then + printf '\n Aufloesen: sudo %s ports --free\n\n' "$SELF" + return 0 + fi + + # --- Vorschlaege -------------------------------------------------- + printf '\n%sVorschlag%s\n' "$C_BLD" "$C_RST" + local -a cmds=() + for st in ${sites[@]+"${sites[@]}"}; do + if local_omd_running "$st"; then cmds+=("omd stop $st"); fi + cmds+=("omd config $st set AUTOSTART off") + done + local u + for u in ${units[@]+"${units[@]}"}; do + case "$u" in + *.scope) continue ;; # kein Dienst, nichts abzuschalten + docker.service|containerd.service|podman.service|podman.socket) continue ;; + esac + cmds+=("systemctl disable --now $u") + done + if [ "${#cmds[@]}" -eq 0 ]; then + warn "Nichts gefunden, das sich gefahrlos stilllegen liesse." + printf ' Die Belegung kommt vermutlich von den eigenen Containern.\n\n' + return 0 + fi + local c + for c in "${cmds[@]}"; do printf ' %s\n' "$c"; done + printf ' + %sDie Daten bleiben.%s "omd stop" haelt die Site nur an, AUTOSTART=off + verhindert den Start nach einem Neustart. Nichts wird geloescht - ein + Import ist weiterhin moeglich: + %s import --file \n' "$C_BLD" "$C_RST" "$SELF" + + if [ -z "$apply" ]; then + printf '\n Ausfuehren mit: sudo %s ports --free --apply\n\n' "$SELF" + return 1 + fi + + echo + [ "$(id -u)" -eq 0 ] || die "Dafuer werden root-Rechte benoetigt." + confirm "Diese Befehle jetzt ausfuehren?" || die "Abgebrochen." + for c in "${cmds[@]}"; do + log "$c" + eval "$c" >/dev/null 2>&1 || warn "Fehlgeschlagen: $c" + done + ok "Erledigt. Danach pruefen: $SELF ports" + echo + return 0 +} + # ===================================================================== # Firewall # @@ -8876,6 +9103,7 @@ main() { selftest) cmd_selftest ;; tui-check) cmd_tui_check ;; firewall) cmd_firewall "$@" ;; + ports) cmd_ports "$@" ;; noproxy) cmd_noproxy "$@" ;; help|-h|--help) usage ;; *) err "Unbekanntes Kommando: $cmd"; echo; usage; exit 1 ;;