From 20eceda18312d1e0afc878a14a20ff60ad26d5d0 Mon Sep 17 00:00:00 2001 From: duffyduck Date: Sun, 20 Sep 2026 23:20:56 +0200 Subject: [PATCH] noproxy: sofort wirksam machen, und Ziele fuer Dienste Zwei Luecken im vorherigen Stand. Erstens war der Eintrag erst in einer neuen Sitzung wirksam. Ein Programm kann die Umgebung seiner Elternshell nicht aendern - dafuer gibt es jetzt "noproxy --export", das nur die beiden Zeilen ausgibt: eval "$(cmk-manage.sh noproxy --export)" Danach gilt es sofort; nachgemessen mit curl -v (vorher "Uses proxy env variable http_proxy", danach "Trying 127.0.0.1"). Der Wert wird dabei aus denselben Regeln gebildet wie beim Schreiben in eine Datei - Vorhandenes zuerst, unsere Adressen dahinter, ohne Doppelte. Zweitens lesen Systemdienste weder profile.d noch .bashrc noch /etc/environment. Dafuer gibt es zwei weitere Ziele: noproxy --fix --environment ergaenzt /etc/environment, ohne die uebrigen Zeilen anzuruehren noproxy --fix --service schreibt eine Ergaenzung der systemd-Unit des Stacks; der Proxy selbst kommt mit hinein, sonst kaeme der Dienst beim Holen von Images nicht mehr ins Internet Findet sich keine passende Unit, zeigt der Befehl den Abschnitt zum Einfuegen von Hand. Die Schreibpfade sind ueber NOPROXY_ENV_FILE und NOPROXY_UNIT_DIR ueberschreibbar - damit liessen sie sich pruefen, ohne /etc dieses Rechners anzufassen. In der Oberflaeche stehen alle vier Ziele zur Auswahl, dazu der Menuepunkt fuer die laufende Sitzung, der den eval-Befehl zum Kopieren zeigt. Co-Authored-By: Claude Opus 5 (1M context) --- README.md | 40 ++++++++-- README_en.md | 40 ++++++++-- scripts/cmk-manage.sh | 175 +++++++++++++++++++++++++++++++++++++----- 3 files changed, 223 insertions(+), 32 deletions(-) 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 <