fix(installer): Selbstschutz gegen stdin-Frass bei curl|sh (VERSION 1.4.0)

x14 brach mitten in der Installation ab: der Installer gab seinen eigenen
Quelltext aus ("; then", Kommentarzeilen) und blieb stehen.

Ursache: Bei `curl ... | sh` liest die Shell das Skript aus STDIN. apt startet
auf Ubuntu `needrestart` (Meldung "Scanning processes... / Scanning linux
images..."), und das liest stdin — damit war der Rest des Skripts weg. Die
Shell setzte mitten im Quelltext fort. Bei x22 trat es nicht auf, weil Telegraf
dort schon installiert war (kein apt-Lauf).

Fix, drei Schutzschichten:
1. Re-Exec: laeuft das Skript ueber eine Pipe, laedt es sich frisch von der
   Quelle und startet sich neu — mit stdin auf /dev/null. NICHT per cat von
   stdin kopieren: die Shell puffert bereits, die Kopie waere unvollstaendig.
2. NEEDRESTART_MODE=a + DEBIAN_FRONTEND=noninteractive fuer alle apt-Aufrufe.
3. </dev/null an jedem Paketmanager (apt, dnf, yum, apk).
This commit is contained in:
mm committed 2026-09-14 10:14:10 +02:00
1 parent 0e94bf4d91
commit 1eb7976ec8
2 files changed
+65 -10

No files matched your search

+1 -1
View File
@@ -1 +1 @@
1.3.0 1.4.0
+64 -9
View File
@@ -1,5 +1,43 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# ============================================================================ # ============================================================================
# SELBSTSCHUTZ BEI "curl | sh"
#
# Problem (real passiert, x14): Bei `curl … | sh` liest die Shell das Skript aus
# STDIN. Jeder Unterbefehl, der stdin genauso liest, frisst den Rest des
# Skripts — die Shell setzt dann mitten im Quelltext fort und bricht ab.
# Ausloeser ist apt/dpkg: auf Ubuntu laeuft dabei `needrestart`, und das
# meldet sich mit "Scanning processes... / Scanning linux images...".
# Symptom in der Praxis: Der Installer gibt seinen EIGENEN Quelltext aus
# ("; then", "fi", Kommentarzeilen) und bleibt mitten in der Installation stehen.
# Auf Nodes mit bereits installiertem Telegraf tritt das NICHT auf (kein apt).
#
# Loesung: Laeuft das Skript ueber eine Pipe, kopiert es sich EINMAL auf die
# Platte und startet sich von dort neu. Ab da ist stdin frei und apt kann
# nichts mehr verschlucken. Idempotent: der Neustart setzt die Marker-Variable.
# ============================================================================
if [ -z "${NETBIRD_TG_REEXEC:-}" ] && [ ! -t 0 ]; then
# Das Skript wird NICHT per `cat` von stdin kopiert: die Shell liest stdin
# blockweise und hat den Anfang bereits gepuffert — `cat` bekaeme nur den
# Rest und die Kopie waere unvollstaendig. Stattdessen frisch von der Quelle
# laden (dieselbe URL, die der Aufrufer benutzt hat).
_src="${REPO_RAW:-https://gitea.m-m.bio/mm/netbird-telegraf-installer/raw/branch/main}"
_self="$(mktemp /tmp/netbird-telegraf-install.XXXXXX)"
if command -v curl >/dev/null 2>&1 && \
curl -fsSL "$_src/install.sh" -o "$_self" 2>/dev/null && [ -s "$_self" ]; then
chmod 0700 "$_self"
# stdin ausdruecklich auf /dev/null: der Prozess erbt sonst die Pipe, und
# apt/needrestart koennte weiter daraus lesen.
NETBIRD_TG_REEXEC=1 REPO_RAW="$_src" sh "$_self" "$@" < /dev/null
_rc=$?
rm -f "$_self"
exit "$_rc"
fi
# Kein curl oder Download fehlgeschlagen: weiter wie bisher. Dann bleibt das
# Risiko, aber der Installer laeuft wenigstens (z. B. in einer Umgebung ohne
# Netz beim zweiten Aufruf).
rm -f "$_self"
fi
# ============================================================================
# NetBird Observability — Telegraf Node Installer (Linux) # NetBird Observability — Telegraf Node Installer (Linux)
# #
# Installiert Telegraf als systemd-Dienst und verbindet die Node fest mit dem # Installiert Telegraf als systemd-Dienst und verbindet die Node fest mit dem
@@ -425,13 +463,22 @@ fi
# Installation # Installation
# -------------------------------------------------------------------------- # --------------------------------------------------------------------------
install_apt() { install_apt() {
command -v gpg >/dev/null || { apt-get update -qq; apt-get install -y -qq gnupg >/dev/null; } # ZWEITE SCHUTZSCHICHT gegen den stdin-Fraß:
command -v curl >/dev/null || apt-get install -y -qq curl >/dev/null # `needrestart` (Ubuntu-Standard) liest stdin und meldet
# "Scanning processes... / Scanning linux images...". Mit NEEDRESTART_MODE=a
# laeuft es nicht-interaktiv, und die apt-Optionen halten dpkg davon ab,
# Prompts zu stellen. Der Re-Exec oben schuetzt die Shell — diese Zeile
# schuetzt zusaetzlich den Installer-Ablauf selbst.
export NEEDRESTART_MODE=a
export DEBIAN_FRONTEND=noninteractive
APT_OPTS="-y -qq -o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--force-confold"
command -v gpg >/dev/null || { apt-get update -qq; apt-get install $APT_OPTS gnupg >/dev/null; }
command -v curl >/dev/null || apt-get install $APT_OPTS curl >/dev/null
mkdir -p /etc/apt/keyrings mkdir -p /etc/apt/keyrings
curl -fsSL https://repos.influxdata.com/influxdata-archive.key | gpg --dearmor --yes -o /etc/apt/keyrings/influxdata-archive.gpg curl -fsSL https://repos.influxdata.com/influxdata-archive.key | gpg --dearmor --yes -o /etc/apt/keyrings/influxdata-archive.gpg
echo "deb [signed-by=/etc/apt/keyrings/influxdata-archive.gpg] https://repos.influxdata.com/debian stable main" > /etc/apt/sources.list.d/influxdata.list echo "deb [signed-by=/etc/apt/keyrings/influxdata-archive.gpg] https://repos.influxdata.com/debian stable main" > /etc/apt/sources.list.d/influxdata.list
apt-get update -qq apt-get update -qq
DEBIAN_FRONTEND=noninteractive apt-get install -y -qq telegraf >/dev/null apt-get install $APT_OPTS telegraf >/dev/null
} }
install_rpm() { install_rpm() {
cat > /etc/yum.repos.d/influxdata.repo <<'EOF' cat > /etc/yum.repos.d/influxdata.repo <<'EOF'
@@ -442,7 +489,13 @@ enabled = 1
gpgcheck = 1 gpgcheck = 1
gpgkey = https://repos.influxdata.com/influxdata-archive.key gpgkey = https://repos.influxdata.com/influxdata-archive.key
EOF EOF
if command -v dnf >/dev/null; then dnf install -y -q telegraf; else yum install -y -q telegraf; fi # dnf/yum lesen ebenfalls stdin (Prompts, Plugin-Rueckfragen) -> hier mit
# -y und ohne Assumeyes-Rueckfrage, damit nichts aus der Pipe greift.
if command -v dnf >/dev/null; then
dnf install -y -q telegraf < /dev/null
else
yum install -y -q telegraf < /dev/null
fi
} }
install_static() { install_static() {
command -v curl >/dev/null || die "curl fehlt." command -v curl >/dev/null || die "curl fehlt."
@@ -499,7 +552,7 @@ else
case "$OS_ID" in case "$OS_ID" in
debian|ubuntu|raspbian|linuxmint|pop) install_apt ;; debian|ubuntu|raspbian|linuxmint|pop) install_apt ;;
rhel|centos|rocky|almalinux|fedora|ol) install_rpm ;; rhel|centos|rocky|almalinux|fedora|ol) install_rpm ;;
alpine) apk add --no-cache -q curl ca-certificates; install_static ;; alpine) apk add --no-cache -q curl ca-certificates < /dev/null; install_static ;;
*) if command -v apt-get >/dev/null; then install_apt *) if command -v apt-get >/dev/null; then install_apt
elif command -v dnf >/dev/null || command -v yum >/dev/null; then install_rpm elif command -v dnf >/dev/null || command -v yum >/dev/null; then install_rpm
else install_static; fi ;; else install_static; fi ;;
@@ -524,11 +577,13 @@ grant_apache_log_access() {
id "$_u" >/dev/null 2>&1 || return 0 id "$_u" >/dev/null 2>&1 || return 0
if ! command -v setfacl >/dev/null 2>&1; then if ! command -v setfacl >/dev/null 2>&1; then
# acl-Paket nachziehen, sonst ist die Rechtevergabe nicht moeglich. # acl-Paket nachziehen, sonst ist die Rechtevergabe nicht moeglich.
# Alle Paketmanager mit </dev/null: sie duerfen nichts aus stdin lesen.
if command -v apt-get >/dev/null; then if command -v apt-get >/dev/null; then
DEBIAN_FRONTEND=noninteractive apt-get install -y -qq acl >/dev/null 2>&1 || true NEEDRESTART_MODE=a DEBIAN_FRONTEND=noninteractive \
elif command -v dnf >/dev/null; then dnf install -y -q acl >/dev/null 2>&1 || true apt-get install -y -qq acl </dev/null >/dev/null 2>&1 || true
elif command -v yum >/dev/null; then yum install -y -q acl >/dev/null 2>&1 || true elif command -v dnf >/dev/null; then dnf install -y -q acl </dev/null >/dev/null 2>&1 || true
elif command -v apk >/dev/null; then apk add --no-cache -q acl >/dev/null 2>&1 || true elif command -v yum >/dev/null; then yum install -y -q acl </dev/null >/dev/null 2>&1 || true
elif command -v apk >/dev/null; then apk add --no-cache -q acl </dev/null >/dev/null 2>&1 || true
fi fi
fi fi
if ! command -v setfacl >/dev/null 2>&1; then if ! command -v setfacl >/dev/null 2>&1; then