diff --git a/README.md b/README.md index 9448af7..9f35c5a 100644 --- a/README.md +++ b/README.md @@ -2630,6 +2630,78 @@ automatisch mit (siehe [Kapitel 12](#12-adminoberfläche-auf-einen-anderen-port- Bei Werten, die erst nach dem Neuerstellen der Container greifen, weist das Menü ausdrücklich darauf hin. +### 14.6 Netze mit Zwangsproxy: `API-Fehler`, der keiner ist + +In Kundennetzen steht oft ein HTTP-Proxy in der Umgebung (`http_proxy`, +`https_proxy`). Nimmt `no_proxy` die lokalen Adressen **nicht** aus, schickt +`curl` selbst eine Anfrage an `127.0.0.1` dorthin. Der Proxy kennt die Adresse +nicht – und die Fehlermeldung landet an einer Stelle, die nichts dafür kann: + +``` +[FEHLER] Anmeldung am Proxy Manager fehlgeschlagen. +``` + +Das sieht nach falschen Zugangsdaten oder einer kaputten API aus. Ist es aber +nicht. Nachsehen: + +```bash +./scripts/cmk-manage.sh noproxy +``` + +``` +HTTP-Proxy in der Umgebung + http_proxy http://proxy.kunde.local:3128 + no_proxy + +Geht http://127.0.0.1:81/ daran vorbei? + [FEHLER] Nein - curl schickt auch diese Anfrage an den Proxy. + +Einzutragen + no_proxy=localhost,127.0.0.1,::1,checkmk-host,172.0.250.82 +``` + +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: + +```bash +sudo ./scripts/cmk-manage.sh noproxy --fix # /etc/profile.d/cmk-noproxy.sh +./scripts/cmk-manage.sh noproxy --fix --user # ~/.bashrc +``` + +**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: + +| vorher | nachher | +|---|---| +| *(leer)* | `localhost,127.0.0.1,::1,host,172.0.250.82` | +| `no_proxy=firma.intern,10.0.0.0/8` | `firma.intern,10.0.0.0/8,localhost,127.0.0.1,…` | +| nur `NO_PROXY=firma.intern` | `firma.intern,localhost,127.0.0.1,…` | +| beide gesetzt, verschieden | beide bleiben, dann unsere | +| `127.0.0.1` steht schon drin | bleibt stehen, nur Fehlendes kommt dazu | + +Ein zweiter Aufruf schreibt nichts doppelt. In der Oberfläche liegt das unter +**Einstellungen → Runtime und Zeitzone → Lokale Verbindungen prüfen**. + +> **Die eigenen Aufrufe dieses Werkzeugs sind davon unabhängig.** Anfragen an +> lokale Adressen laufen grundsätzlich mit `curl --noproxy`, Anfragen ins +> Internet (Registry, Downloadportal) weiterhin über den Proxy. Der Befehl ist +> für alles andere da: eigene `curl`-Tests, der Terminal-Browser, andere +> Skripte. + +> **Kleine Eigenheit von curl:** `no_proxy`/`NO_PROXY` und +> `https_proxy`/`HTTPS_PROXY` gelten in beiden Schreibweisen, `HTTP_PROXY` in +> Großschreibung dagegen **nicht** – das ignoriert curl absichtlich, weil in +> 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,…` + --- ## 15. Backup @@ -3167,6 +3239,7 @@ Checkmk-Werksnotizen (Werks/Release Notes) lesen. | `ERR_SSL_UNRECOGNIZED_NAME_ALERT` beim Aufruf über `https:///` | Der Browser sendet bei einer IP kein SNI, nginx fällt auf seinen Standard-Server zurück und lehnt ab. `cmk-manage.sh proxy default --domain ` – siehe [Kapitel 10.8](#108-https-über-die-blanke-ip) | | `omd restore`: *apache user www-data must be member of group ``* | Der Container wurde neu erstellt, die Site liegt im Bind-Mount. `cmk-manage.sh` zieht das beim Restore und beim `up` selbst nach – siehe [Kapitel 16.1](#161-warum-ein-restore-nach-dem-neuerstellen-des-containers-scheiterte) | | `omd restore`: *fstab entry for /omd/sites/…/tmp does not exist* | gleiche Ursache, gleiche Behebung | +| `Anmeldung am Proxy Manager fehlgeschlagen` trotz richtiger Zugangsdaten | Zwangsproxy im Netz: `no_proxy` nimmt `127.0.0.1` nicht aus. `cmk-manage.sh noproxy` – siehe [Kapitel 14.6](#146-netze-mit-zwangsproxy-api-fehler-der-keiner-ist) | | `Port 80/443 already in use` | Auf dem Host läuft bereits ein Webserver: `ss -tlnp \| grep ':80'` → `systemctl disable --now apache2 nginx httpd` | | Nach Reboot laufen die Container nicht (Podman) | systemd-Unit fehlt: `./install.sh --with-systemd` bzw. `--quadlet`, danach `systemctl is-enabled checkmk-stack` | | `omd restore`: *version is not installed* | passendes Image holen: `cmk-manage.sh image pull --edition --version `, dann `up` | diff --git a/README_en.md b/README_en.md index 32834a6..51adb53 100644 --- a/README_en.md +++ b/README_en.md @@ -2615,6 +2615,75 @@ readable by compose, systemd **and** the shell. When you change values that only take effect once the containers are recreated, the menu says so explicitly. +### 14.6 Networks with a mandatory proxy: an `API error` that is none + +In customer networks an HTTP proxy is often present in the environment +(`http_proxy`, `https_proxy`). If `no_proxy` does **not** exclude local +addresses, `curl` sends even a request to `127.0.0.1` there. The proxy does not +know that address – and the error surfaces somewhere entirely innocent: + +``` +[FEHLER] Anmeldung am Proxy Manager fehlgeschlagen. +``` + +That looks like wrong credentials or a broken API. It is neither. To check: + +```bash +./scripts/cmk-manage.sh noproxy +``` + +``` +HTTP-Proxy in der Umgebung + http_proxy http://proxy.customer.local:3128 + no_proxy + +Geht http://127.0.0.1:81/ daran vorbei? + [FEHLER] Nein - curl schickt auch diese Anfrage an den Proxy. + +Einzutragen + no_proxy=localhost,127.0.0.1,::1,checkmk-host,172.0.250.82 +``` + +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: + +```bash +sudo ./scripts/cmk-manage.sh noproxy --fix # /etc/profile.d/cmk-noproxy.sh +./scripts/cmk-manage.sh noproxy --fix --user # ~/.bashrc +``` + +**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: + +| before | after | +|---|---| +| *(empty)* | `localhost,127.0.0.1,::1,host,172.0.250.82` | +| `no_proxy=company.internal,10.0.0.0/8` | `company.internal,10.0.0.0/8,localhost,127.0.0.1,…` | +| only `NO_PROXY=company.internal` | `company.internal,localhost,127.0.0.1,…` | +| both set, different | both kept, then ours | +| `127.0.0.1` already present | kept, only what is missing is added | + +A second call writes nothing twice. The GUI has it under **Einstellungen → +Runtime und Zeitzone → Lokale Verbindungen prüfen**. + +> **This tool's own calls are unaffected.** Requests to local addresses always +> use `curl --noproxy`, requests to the internet (registry, download portal) +> keep using the proxy. The command exists for everything else: your own `curl` +> tests, the terminal browser, other scripts. + +> **A curl quirk:** `no_proxy`/`NO_PROXY` and `https_proxy`/`HTTPS_PROXY` are +> honoured in both spellings, uppercase `HTTP_PROXY` is **not** – curl ignores +> 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,…` + --- ## 15. Backup @@ -3151,6 +3220,7 @@ release notes beforehand. | `ERR_SSL_UNRECOGNIZED_NAME_ALERT` when opening `https:///` | browsers send no SNI for an IP, nginx falls back to its default server and rejects. `cmk-manage.sh proxy default --domain ` – see [chapter 10.8](#108-https-on-the-bare-ip) | | `omd restore`: *apache user www-data must be member of group ``* | the container was recreated while the site lives in the bind mount. `cmk-manage.sh` repairs this on restore and on `up` – see [chapter 16.1](#161-why-a-restore-failed-after-recreating-the-container) | | `omd restore`: *fstab entry for /omd/sites/…/tmp does not exist* | same cause, same fix | +| `Anmeldung am Proxy Manager fehlgeschlagen` despite correct credentials | mandatory proxy in the network: `no_proxy` does not exclude `127.0.0.1`. `cmk-manage.sh noproxy` – see [chapter 14.6](#146-networks-with-a-mandatory-proxy-an-api-error-that-is-none) | | `Port 80/443 already in use` | a web server is already running on the host: `ss -tlnp \| grep ':80'` → `systemctl disable --now apache2 nginx httpd` | | Containers do not run after a reboot (Podman) | systemd unit missing: `./install.sh --with-systemd` or `--quadlet`, then `systemctl is-enabled checkmk-stack` | | `omd restore`: *version is not installed* | fetch the matching image: `cmk-manage.sh image pull --edition --version `, then `up` | diff --git a/scripts/cmk-manage.sh b/scripts/cmk-manage.sh index 273a1e7..58628fc 100755 --- a/scripts/cmk-manage.sh +++ b/scripts/cmk-manage.sh @@ -64,6 +64,9 @@ KOMMANDOS - Stack - SSH niemals, fremde Freigaben bleiben unberuehrt. Der Adminport des Proxy Managers wird mit angeboten; --keep-admin laesst ihn offen + 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") selftest Skripte auf bekannte Fallstricke pruefen tui-check Testzeilen fuer die Rahmendarstellung ausgeben (hilft bei q/x/l/m statt Linien, etwa in PuTTY) @@ -978,6 +981,35 @@ _curl_cfg() { # user pass -> Konfigurationszeile auf stdout printf 'user = "%s:%s"\n' "$u" "$p" } +# --------------------------------------------------------------------- +# Lokale Anfragen am HTTP-Proxy vorbei +# +# In Umgebungen mit Zwangsproxy stehen http_proxy/https_proxy in der +# Umgebung, und wenn no_proxy die lokalen Adressen nicht ausnimmt, +# schickt curl selbst eine Anfrage an 127.0.0.1 an den Proxy. Der kennt +# die Adresse nicht und antwortet mit einem Fehler - hier sichtbar als +# "API-Fehler" beim Anmelden am Proxy Manager. +# +# Fuer Ziele auf diesem Rechner wird der Proxy deshalb ausdruecklich +# abgeschaltet. Anfragen ins Internet (Registry, Downloadportal) bleiben +# unberuehrt - die brauchen ihn ja. +# --------------------------------------------------------------------- +url_is_local() { # url + local h="${1#*://}"; h="${h%%/*}"; h="${h%%\?*}" + h="${h##*@}"; h="${h%%:*}" + case "$h" in + localhost|127.0.0.1|::1|\[::1\]|0.0.0.0) return 0 ;; + 127.*) return 0 ;; + esac + [ -n "$h" ] && [ "$h" = "$(primary_ip 2>/dev/null)" ] && return 0 + return 1 +} + +# Argumente fuer curl, damit eine lokale Anfrage nicht ueber den Proxy geht +curl_local_args() { # url + if url_is_local "$1"; then printf -- '--noproxy\n*\n'; fi +} + curl_auth() { # user pass curl-argumente... local u="$1" p="$2"; shift 2 if [ -n "$u" ]; then @@ -992,6 +1024,7 @@ http_code() { # url [user] [pass] [extra-header] local url="$1" u="${2:-}" p="${3:-}" hdr="${4:-}" local -a a=(-sS -o /dev/null -w '%{http_code}' --max-time 30) if [ -n "$hdr" ]; then a+=(-H "$hdr"); fi + local np; while IFS= read -r np; do [ -n "$np" ] && a+=("$np"); done < <(curl_local_args "$url") local code code="$(curl_auth "$u" "$p" "${a[@]}" "$url" 2>/dev/null)" || code=000 printf '%s\n' "${code:-000}" @@ -3728,15 +3761,25 @@ EOF return 1 fi local body - body="$(curl -sS --max-time 20 -X POST "$base/api/tokens" \ + body="$(curl -sS --max-time 20 --noproxy '*' -X POST "$base/api/tokens" \ -H 'Content-Type: application/json' \ -d "{\"identity\":\"$NPM_ADMIN_EMAIL\",\"secret\":\"$NPM_ADMIN_PASSWORD\"}" 2>/dev/null)" || true local tok; tok="$(json_str "$body" token)" if [ -z "$tok" ]; then err "Anmeldung am Proxy Manager fehlgeschlagen." local m; m="$(json_str "$body" message)" - [ -n "$m" ] && printf ' Antwort: %s\n' "$m" >&2 + if [ -n "$m" ]; then printf ' Antwort: %s\n' "$m" >&2; fi printf ' Geprueft wurde: %s\n' "$base/api/tokens" >&2 + # In Kundennetzen mit Zwangsproxy ist das die haeufigste Ursache + # fuer eine Fehlermeldung, die nach einem API-Problem aussieht. + if [ -n "${http_proxy:-}${HTTP_PROXY:-}${https_proxy:-}${HTTPS_PROXY:-}" ]; then + printf ' + In dieser Umgebung steht ein HTTP-Proxy. Nimmt no_proxy die lokalen + Adressen nicht aus, geht selbst diese Anfrage an ihn - dann meldet + er den Fehler, nicht der Proxy Manager. Nachsehen mit: + %s noproxy +' "$SELF" >&2 + fi return 1 fi printf '%s' "$tok" @@ -3750,7 +3793,7 @@ npm_api() { local method="$1" path="$2" data="${3:-}" local base; base="$(npm_api_base)" local -a a=(-sS --max-time 60 -X "$method" -H "Authorization: Bearer $NPM_TOKEN" - -w '\n%{http_code}') + --noproxy '*' -w '\n%{http_code}') [ -n "$data" ] && a+=(-H 'Content-Type: application/json' -d "$data") local out; out="$(curl "${a[@]}" "$base$path" 2>/dev/null)" || out=$'\n000' NPM_CODE="${out##*$'\n'}" @@ -3807,7 +3850,7 @@ npm_cert_selfsigned() { # domain fi log "Lade Schluessel und Zertifikat hoch (ID $id) ..." >&2 local up - up="$(curl -sS --max-time 60 -X POST "$(npm_api_base)/api/nginx/certificates/$id/upload" \ + up="$(curl -sS --max-time 60 --noproxy '*' -X POST "$(npm_api_base)/api/nginx/certificates/$id/upload" \ -H "Authorization: Bearer $NPM_TOKEN" \ -F "certificate=@$dir/fullchain.pem" \ -F "certificate_key=@$dir/privkey.pem" 2>/dev/null)" || true @@ -6366,6 +6409,7 @@ gui_settings_category() { done < <(settings_defs) # Zusatzaktionen, die inhaltlich zur Kategorie gehoeren case "$cat" in + runtime) items+=("__net__" ">> Lokale Verbindungen pruefen (Zwangsproxy)") ;; image) items+=("__get__" ">> Image jetzt holen (Registry oder Downloadportal)") items+=("__wizard__" ">> Assistent: Edition, Version, Bezugsweg") items+=("__test__" ">> Zugangsdaten jetzt pruefen (Registry + Downloadportal)") ;; @@ -6391,6 +6435,7 @@ gui_settings_category() { __fwcheck__) gui_firewall || true; continue ;; __fwapply__) gui_firewall_apply || true; continue ;; __fwclose__) gui_firewall_close || true; continue ;; + __net__) gui_noproxy || true; continue ;; __npm__) local f; f="$(mktemp)" ( NO_COLOR=1 cmd_npm_enable; NO_COLOR=1 cmd_npm_port ) >"$f" 2>&1 || true ui_text "NGINX Proxy Manager" "$f"; rm -f "$f"; continue ;; @@ -7131,6 +7176,45 @@ Bitte als root erneut aufrufen." } # Nicht mehr benoetigte Ports wieder schliessen +# Zwangsproxy: geht 127.0.0.1 daran vorbei? +gui_noproxy() { + local f rc=0 + f="$(mktemp)" + ( NO_COLOR=1 cmd_noproxy ) >"$f" 2>&1 || rc=$? + ui_text "Lokale Verbindungen und HTTP-Proxy" "$f" + rm -f "$f" + [ "$rc" -eq 0 ] && return 0 + + ui_yesno "HTTP-Proxy" "Lokale Adressen laufen ueber den HTTP-Proxy. + +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 + + local -a a=(noproxy --fix) + 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" + elif [ "$(id -u)" -eq 0 ]; then + ui_run "Eintragen" "$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." + fi + return 0 +} + gui_firewall_close() { local tmp rc=0 hat="" adminfall="" tmp="$(mktemp)" @@ -8017,6 +8101,199 @@ cmd_firewall() { return 1 } +# ===================================================================== +# Zwangsproxy: lokale Adressen ausnehmen +# +# In Kundennetzen steht oft ein HTTP-Proxy in der Umgebung. Nimmt +# no_proxy die lokalen Adressen nicht aus, schickt curl selbst eine +# Anfrage an 127.0.0.1 dorthin. Der Proxy kennt die Adresse nicht, und +# am Ende steht ein "API-Fehler" beim Anmelden am Proxy Manager - eine +# Meldung, die in die voellig falsche Richtung zeigt. +# +# Dieses Werkzeug umgeht das fuer seine eigenen Aufrufe bereits +# (curl --noproxy). Fuer alles andere auf dem Rechner - eigene +# curl-Tests, der Terminal-Browser, andere Skripte - muss no_proxy +# stimmen. Genau das prueft und richtet dieser Befehl ein. +# ===================================================================== + +NOPROXY_FILE="/etc/profile.d/cmk-noproxy.sh" + +# Welche Adressen gehoeren in no_proxy? +noproxy_list() { + local ip host + ip="$(primary_ip 2>/dev/null)" + host="$(hostname 2>/dev/null)" + local l="localhost,127.0.0.1,::1" + if [ -n "$host" ]; then l="$l,$host"; fi + if [ -n "$ip" ]; then l="$l,$ip"; fi + printf '%s' "$l" +} + +# Wuerde curl fuer diese Adresse den Proxy benutzen? +noproxy_would_use_proxy() { # url + local out + out="$(curl -sS -o /dev/null -v --max-time 3 "$1" 2>&1 || true)" + case "$out" in + *"Uses proxy env variable http_proxy"*|*"Uses proxy env variable https_proxy"*) return 0 ;; + esac + return 1 +} + +cmd_noproxy() { + local fix="" scope=system + while [ $# -gt 0 ]; do + case "$1" in + --fix) fix=1; shift ;; + --user) scope=user; shift ;; + --system) scope=system; shift ;; + --help|-h) +cat <}" + done + + if [ -z "$any" ]; then + echo + ok "Es ist kein HTTP-Proxy gesetzt - lokale Anfragen gehen direkt." + printf ' Auf Rechnern mit Zwangsproxy sieht das anders aus; dort hilft: + %s noproxy --fix\n\n' "$SELF" + return 0 + fi + + printf '\n%sGeht %s daran vorbei?%s\n' "$C_BLD" "$url" "$C_RST" + if noproxy_would_use_proxy "$url"; then + test_result fail "Nein - curl schickt auch diese Anfrage an den Proxy." + printf ' Daher kommen Meldungen wie "API-Fehler" beim Anmelden am + Proxy Manager: nicht der Proxy Manager antwortet nicht, sondern + der HTTP-Proxy weiss mit 127.0.0.1 nichts anzufangen.\n' + else + test_result ok "Ja - lokale Anfragen gehen direkt." + if [ -z "$fix" ]; then + printf '\n Die eigenen Aufrufe dieses Werkzeugs gehen ohnehin daran vorbei + (curl --noproxy). Fuer eigene Tests und andere Programme ist es + damit ebenfalls in Ordnung.\n\n' + return 0 + fi + fi + + local liste; liste="$(noproxy_list)" + printf '\n%sEinzutragen%s\n' "$C_BLD" "$C_RST" + printf ' no_proxy=%s\n' "$liste" + + if [ -z "$fix" ]; then + printf '\n Dauerhaft setzen: + sudo %s noproxy --fix fuer alle (%s) + %s noproxy --fix --user nur fuer diesen Benutzer (~/.bashrc)\n\n' \ + "$SELF" "$NOPROXY_FILE" "$SELF" + return 1 + fi + + local target + if [ "$scope" = user ]; then + target="$HOME/.bashrc" + else + target="$NOPROXY_FILE" + if [ "$(id -u)" -ne 0 ]; then + die "Zum Schreiben von $target werden root-Rechte benoetigt. + Entweder mit sudo, oder nur fuer diesen Benutzer: + $SELF noproxy --fix --user" + fi + fi + + if ( set +o pipefail; grep -q 'cmk-manage.sh noproxy' "$target" 2>/dev/null ); then + ok "In $target steht der Eintrag bereits." + log "Wirksam wird er in neuen Sitzungen - oder sofort mit: + export no_proxy='$liste' NO_PROXY='$liste'" + return 0 + fi + + # Wichtig: was schon dasteht, bleibt - und zwar VORNE. Beide + # Schreibweisen werden eingesammelt, denn manche Systeme setzen nur + # NO_PROXY; wer nur no_proxy liest, wirft das Grosse weg. Doppelte + # Eintraege fallen dabei heraus. + local tmp; tmp="$(mktemp)" + { + printf '\n# Lokale Adressen nicht ueber den HTTP-Proxy leiten.\n' + printf '# Erzeugt von cmk-manage.sh noproxy --fix\n' + printf '# Vorhandene Eintraege bleiben erhalten und stehen vorn.\n' + printf '_cmk_local="%s"\n' "$liste" + printf '_cmk_all="${no_proxy:-}"\n' + printf 'if [ -n "${NO_PROXY:-}" ]; then _cmk_all="${_cmk_all:+${_cmk_all},}${NO_PROXY}"; fi\n' + printf '_cmk_all="${_cmk_all:+${_cmk_all},}${_cmk_local}"\n' + printf '_cmk_out=""\n' + printf 'for _cmk_e in $(printf "%%s" "$_cmk_all" | tr "," " "); do\n' + printf ' case ",${_cmk_out}," in\n' + printf ' *",${_cmk_e},"*) ;;\n' + printf ' *) _cmk_out="${_cmk_out:+${_cmk_out},}${_cmk_e}" ;;\n' + printf ' esac\n' + printf 'done\n' + printf 'no_proxy="$_cmk_out"\n' + printf 'NO_PROXY="$_cmk_out"\n' + printf 'export no_proxy NO_PROXY\n' + printf 'unset _cmk_local _cmk_all _cmk_out _cmk_e\n' + } >"$tmp" + + if [ "$scope" = user ]; then + cat "$tmp" >> "$target" + else + { [ -f "$target" ] && cat "$target"; printf '#!/bin/sh\n'; } >/dev/null 2>&1 + { printf '#!/bin/sh\n'; cat "$tmp"; } > "$tmp.f" + install -m 0644 "$tmp.f" "$target" + rm -f "$tmp.f" + fi + rm -f "$tmp" + 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: + export no_proxy='$liste' NO_PROXY='$liste'" + cat <