diff --git a/README.md b/README.md index 9f35c5a..1884482 100644 --- a/README.md +++ b/README.md @@ -2569,6 +2569,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 | +| `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 Cronjobs), `-v/--verbose`. @@ -2664,13 +2665,40 @@ Erkannt wird das nicht geraten, sondern an dem, was `curl -v` selbst sagt (`Uses proxy env variable http_proxy == …`) – dafür muss auf der Zieladresse nichts laufen. -Dauerhaft eintragen: +**In der laufenden Sitzung** – ein Programm kann die Umgebung seiner Elternshell +nicht ändern, deshalb der Umweg über `eval`: ```bash -sudo ./scripts/cmk-manage.sh noproxy --fix # /etc/profile.d/cmk-noproxy.sh -./scripts/cmk-manage.sh noproxy --fix --user # ~/.bashrc +eval "$(./scripts/cmk-manage.sh noproxy --export)" ``` +**Dauerhaft** – die Ziele schließen einander nicht aus, je nach Rechner braucht +es mehrere: + +| Befehl | wirkt für | +|---|---| +| `sudo … noproxy --fix` | Anmeldeshells (`/etc/profile.d/cmk-noproxy.sh`) | +| `… noproxy --fix --user` | nur diesen Benutzer (`~/.bashrc`) | +| `sudo … noproxy --fix --environment` | Anmeldungen ohne Shell (`/etc/environment`) | +| `sudo … noproxy --fix --service` | **Systemdienste** – Ergänzung der systemd-Unit | + +Der letzte Punkt ist der, den man leicht übersieht: **Systemdienste lesen weder +`profile.d` noch `.bashrc` noch `/etc/environment`.** Läuft der Stack über +systemd, schreibt `--service` eine Ergänzung nach +`/etc/systemd/system/checkmk-stack.service.d/cmk-noproxy.conf`: + +```ini +[Service] +Environment=no_proxy=localhost,127.0.0.1,::1,checkmk-host,172.0.250.82 +Environment=NO_PROXY=localhost,127.0.0.1,::1,checkmk-host,172.0.250.82 +Environment=http_proxy=http://proxy.kunde.local:3128 +Environment=https_proxy=http://proxy.kunde.local:3128 +``` + +Der Proxy selbst kommt dabei mit hinein – ohne ihn käme der Dienst beim Holen +von Images nicht ins Internet. Gibt es keine passende Unit, zeigt der Befehl +den Abschnitt zum Einfügen von Hand. + **Was schon dasteht, bleibt – und zwar vorn.** Der Eintrag sammelt beide Schreibweisen ein (`no_proxy` *und* `NO_PROXY`; manche Systeme setzen nur die große), hängt die lokalen Adressen hinten an und wirft Doppelte heraus: @@ -2698,9 +2726,9 @@ Ein zweiter Aufruf schreibt nichts doppelt. In der Oberfläche liegt das unter > CGI-Umgebungen eine eingehende Kopfzeile `Proxy:` sie setzen könnte. Der > Bericht weist darauf hin, wenn nur diese gesetzt ist. -> **Dienste lesen keine Profildateien.** Läuft der Stack über systemd und steht -> dort ein Proxy, gehört die Ausnahme zusätzlich nach `/etc/environment` oder -> in die Unit: `Environment=no_proxy=localhost,127.0.0.1,…` +> **Reihenfolge:** Erst `noproxy` zum Nachsehen, dann eintragen, dann mit +> `eval "$(… noproxy --export)"` in der laufenden Sitzung wirksam machen – +> sonst wundert man sich, warum sich nichts ändert. --- diff --git a/README_en.md b/README_en.md index 51adb53..a88b33a 100644 --- a/README_en.md +++ b/README_en.md @@ -2551,6 +2551,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 | +| `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), `-v/--verbose`. @@ -2648,13 +2649,40 @@ This is not guessed but read from what `curl -v` reports itself (`Uses proxy env variable http_proxy == …`) – nothing needs to be listening on the target address for that. -To make it permanent: +**In the running session** – a program cannot change its parent shell's +environment, hence the detour via `eval`: ```bash -sudo ./scripts/cmk-manage.sh noproxy --fix # /etc/profile.d/cmk-noproxy.sh -./scripts/cmk-manage.sh noproxy --fix --user # ~/.bashrc +eval "$(./scripts/cmk-manage.sh noproxy --export)" ``` +**Permanently** – the targets are not mutually exclusive; depending on the +machine you need several: + +| Command | takes effect for | +|---|---| +| `sudo … noproxy --fix` | login shells (`/etc/profile.d/cmk-noproxy.sh`) | +| `… noproxy --fix --user` | this user only (`~/.bashrc`) | +| `sudo … noproxy --fix --environment` | logins without a shell (`/etc/environment`) | +| `sudo … noproxy --fix --service` | **system services** – systemd unit drop-in | + +The last one is easily overlooked: **system services read neither `profile.d` +nor `.bashrc` nor `/etc/environment`.** If the stack runs under systemd, +`--service` writes a drop-in to +`/etc/systemd/system/checkmk-stack.service.d/cmk-noproxy.conf`: + +```ini +[Service] +Environment=no_proxy=localhost,127.0.0.1,::1,checkmk-host,172.0.250.82 +Environment=NO_PROXY=localhost,127.0.0.1,::1,checkmk-host,172.0.250.82 +Environment=http_proxy=http://proxy.customer.local:3128 +Environment=https_proxy=http://proxy.customer.local:3128 +``` + +The proxy itself is carried over – without it the service could not reach the +internet to pull images. If no matching unit exists, the command prints the +section to paste by hand. + **Whatever is already there stays – and stays first.** The entry collects both spellings (`no_proxy` *and* `NO_PROXY`; some systems only set the uppercase one), appends the local addresses and drops duplicates: @@ -2680,9 +2708,9 @@ Runtime und Zeitzone → Lokale Verbindungen prüfen**. > it deliberately, because in CGI environments an incoming `Proxy:` header > could set it. The report points this out when only that one is set. -> **Services do not read profile files.** If the stack runs under systemd and a -> proxy is configured there, the exception also belongs in `/etc/environment` -> or in the unit: `Environment=no_proxy=localhost,127.0.0.1,…` +> **Order of operations:** first `noproxy` to look, then write it, then apply it +> to the running session with `eval "$(… noproxy --export)"` – otherwise you +> will wonder why nothing changed. --- diff --git a/scripts/cmk-manage.sh b/scripts/cmk-manage.sh index 58628fc..8d0da58 100755 --- a/scripts/cmk-manage.sh +++ b/scripts/cmk-manage.sh @@ -7191,17 +7191,39 @@ Die Ausnahme jetzt dauerhaft eintragen?" || return 0 local sel sel="$(ui_menu "Wohin eintragen?" \ -"Fuer alle Benutzer braucht es root-Rechte. Dienste (systemd, cron) -lesen weder das eine noch das andere - dort gehoert die Ausnahme in -die Unit bzw. nach /etc/environment." \ - system "Fuer alle: /etc/profile.d/cmk-noproxy.sh" \ - user "Nur fuer mich: ~/.bashrc" \ - back "zurueck")" || return 0 - case "$sel" in back) return 0 ;; esac +"Die Ziele schliessen einander nicht aus - je nachdem, was auf diesem +Rechner laeuft, braucht es mehrere. + +Anmeldeshells lesen profile.d und .bashrc, Anmeldungen ohne Shell die +Datei /etc/environment, und Systemdienste lesen NICHTS davon - fuer die +gibt es die Ergaenzung der Unit." \ + system "Anmeldeshells: /etc/profile.d/cmk-noproxy.sh (root)" \ + user "Nur fuer mich: ~/.bashrc" \ + environment "Anmeldungen ohne Shell: /etc/environment (root)" \ + service "Systemdienste: Ergaenzung der Unit (root)" \ + jetzt "Nur in dieser Sitzung - Befehl zum Kopieren zeigen" \ + back "zurueck")" || return 0 + case "$sel" in + back) return 0 ;; + jetzt) local ex; ex="$( ( NO_COLOR=1 cmd_noproxy --export ) 2>/dev/null )" + ui_msg "Sofort setzen" "Ein Programm kann die Umgebung seiner Elternshell nicht +aendern. In der laufenden Shell hilft deshalb: + + eval \"\$($SELF noproxy --export)\" + +Das setzt: + +$ex" + return 0 ;; + esac local -a a=(noproxy --fix) + case "$sel" in + user) a+=(--user) ;; + environment) a+=(--environment) ;; + service) a+=(--service) ;; + esac if [ "$sel" = user ]; then - a+=(--user) local f2; f2="$(mktemp)" ( NO_COLOR=1 cmd_noproxy --fix --user ) >"$f2" 2>&1 || true ui_text "Eingetragen" "$f2"; rm -f "$f2" @@ -8116,7 +8138,11 @@ cmd_firewall() { # stimmen. Genau das prueft und richtet dieser Befehl ein. # ===================================================================== -NOPROXY_FILE="/etc/profile.d/cmk-noproxy.sh" +NOPROXY_FILE="${NOPROXY_FILE:-/etc/profile.d/cmk-noproxy.sh}" +# Ueberschreibbar, damit sich die Schreibwege pruefen lassen, ohne /etc +# dieses Rechners anzufassen. +NOPROXY_ENV_FILE="${NOPROXY_ENV_FILE:-/etc/environment}" +NOPROXY_UNIT_DIR="${NOPROXY_UNIT_DIR:-/etc/systemd/system}" # Welche Adressen gehoeren in no_proxy? noproxy_list() { @@ -8129,6 +8155,21 @@ noproxy_list() { printf '%s' "$l" } +# Vorhandenes zuerst, dann unsere Adressen, ohne Doppelte +noproxy_merge() { # alt-klein alt-gross + local all e out="" + all="$1" + if [ -n "${2:-}" ]; then all="${all:+${all},}$2"; fi + all="${all:+${all},}$(noproxy_list)" + for e in $(printf '%s' "$all" | tr ',' ' '); do + case ",$out," in + *",$e,"*) ;; + *) out="${out:+${out},}$e" ;; + esac + done + printf '%s' "$out" +} + # Wuerde curl fuer diese Adresse den Proxy benutzen? noproxy_would_use_proxy() { # url local out @@ -8140,20 +8181,34 @@ noproxy_would_use_proxy() { # url } cmd_noproxy() { - local fix="" scope=system + local fix="" scope=system export_only="" while [ $# -gt 0 ]; do case "$1" in - --fix) fix=1; shift ;; - --user) scope=user; shift ;; + --fix) fix=1; shift ;; + --export) export_only=1; shift ;; + --user) scope=user; shift ;; --system) scope=system; shift ;; + --environment) scope=environment; shift ;; + --service) scope=service; shift ;; --help|-h) cat </dev/null | tail -1 | tr -d '"')" + alt_g="$(sed -n 's/^NO_PROXY=//p' "$ef" 2>/dev/null | tail -1 | tr -d '"')" + merged="$(noproxy_merge "${alt_k:-${no_proxy:-}}" "${alt_g:-${NO_PROXY:-}}")" + local t2; t2="$(mktemp)" + { grep -vE '^(no_proxy|NO_PROXY)=' "$ef" 2>/dev/null || true + printf 'no_proxy="%s"\n' "$merged" + printf 'NO_PROXY="%s"\n' "$merged" + } >"$t2" + install -m 0644 "$t2" "$ef"; rm -f "$t2" + ok "Eingetragen in $ef" + log "Gilt fuer neue Anmeldungen. Systemdienste lesen diese Datei NICHT - + dafuer: $SELF noproxy --fix --service" + return 0 + fi + + # --- systemd-Unit des Stacks -------------------------------------- + if [ "$scope" = service ]; then + [ "$(id -u)" -eq 0 ] || die "Zum Schreiben einer Unit-Ergaenzung werden root-Rechte benoetigt." + command -v systemctl >/dev/null 2>&1 || die "systemd ist hier nicht im Einsatz." + local merged; merged="$(noproxy_merge "${no_proxy:-}" "${NO_PROXY:-}")" + local -a units=() u + local lst + lst="$(systemctl list-unit-files --no-legend 2>/dev/null || true)" + for u in checkmk-stack.service checkmk.service nginx-proxy-manager.service; do + case "$lst" in + "$u"*|*" +$u"*) units+=("$u") ;; + esac + done + if [ "${#units[@]}" -eq 0 ]; then + err "Keine Unit des Stacks gefunden." + printf ' Angelegt werden sie von: ./install.sh --with-systemd bzw. --quadlet + Von Hand waere es eine Ergaenzung mit diesem Inhalt: + + [Service] + Environment=no_proxy=%s + Environment=NO_PROXY=%s +\n' "$merged" "$merged" >&2 + return 1 + fi + for u in "${units[@]}"; do + local d="$NOPROXY_UNIT_DIR/$u.d" + mkdir -p "$d" + { + printf '# Lokale Adressen nicht ueber den HTTP-Proxy leiten.\n' + printf '# Erzeugt von cmk-manage.sh noproxy --fix --service\n' + printf '[Service]\n' + printf 'Environment=no_proxy=%s\n' "$merged" + printf 'Environment=NO_PROXY=%s\n' "$merged" + # Der Proxy selbst gehoert mit hinein: ohne ihn kommt der + # Dienst beim Holen von Images nicht ins Internet. + if [ -n "${http_proxy:-}" ]; then printf 'Environment=http_proxy=%s\n' "$http_proxy"; fi + if [ -n "${https_proxy:-}" ]; then printf 'Environment=https_proxy=%s\n' "$https_proxy"; fi + if [ -n "${https_proxy:-}" ]; then printf 'Environment=HTTPS_PROXY=%s\n' "$https_proxy"; fi + } > "$d/cmk-noproxy.conf" + ok "Ergaenzung geschrieben: $d/cmk-noproxy.conf" + done + if [ "$NOPROXY_UNIT_DIR" = /etc/systemd/system ]; then + systemctl daemon-reload && ok "systemd hat die Units neu eingelesen." + fi + log "Wirksam beim naechsten Start der Unit: systemctl restart ${units[0]}" + return 0 + fi + local target if [ "$scope" = user ]; then target="$HOME/.bashrc" @@ -8280,15 +8413,17 @@ EOF ok "Eingetragen in $target" log "Vorhandene Eintraege bleiben erhalten und stehen vorn - ergaenzt wird nur, was fehlt (beide Schreibweisen, no_proxy und NO_PROXY)." - log "Wirksam in neuen Sitzungen. Sofort: + log "Wirksam in neuen Sitzungen. In DIESER Sitzung sofort: + eval \"\$($SELF noproxy --export)\" + (ein Programm kann die Umgebung seiner Elternshell nicht aendern)" + log "Alter Weg, gleichwertig: export no_proxy='$liste' NO_PROXY='$liste'" cat <