Funktion und Variablen in sudo su - <user> << EOF weiterleiten

9

Ich habe Funktionen und Variablen in bash / ksh deklariert und muss sie weiterleiten an sudo su - {user} << EOF:

#!/bin/bash

log_f() {
echo "LOG line: $@"
}

extVAR="yourName"

sudo su - <user> << EOF
  intVAR=$(date)
  log_f ${intVAR} ${extVAR}
EOF
waldauf
quelle

Antworten:

4

sudo su -, eine komplizierte Schreibweise sudo -i, schafft eine makellose Umgebung. Das ist der Punkt einer Login-Shell. Sogar eine Ebene sudoentfernt die meisten Variablen aus der Umgebung. Weiterhin sudoist ein externer Befehl; Es gibt keine Möglichkeit, Berechtigungen im Shell-Skript selbst zu erhöhen, sondern nur ein externes Programm ( sudo) mit zusätzlichen Berechtigungen auszuführen. Dies bedeutet, dass in der übergeordneten Shell definierte Shell-Variablen (dh nicht exportierte Variablen) und Funktionen nicht verfügbar sind die Kinderhülle.

Sie können Umgebungsvariablen weitergeben, indem Sie keine Anmeldeshell ( sudo bashanstelle von sudo su -oder sudo -i) aufrufen und sudo so konfigurieren, dass diese Variablen (mit Defaults !env_resetoder Defaults env_keep=…in der sudoersDatei) durchgelassen werden. Dies hilft Ihnen bei Funktionen nicht weiter (obwohl bash über eine Funktion zum Exportieren von Funktionen verfügt, blockiert sudo diese).

Der normale Weg, um Ihre Funktionen in die untergeordnete Shell zu bekommen, besteht darin, sie dort zu definieren. Achten Sie <<EOFauf das Zitieren: Wenn Sie für das Here-Dokument verwenden, wird der Inhalt des Here-Dokuments zuerst von der übergeordneten Shell erweitert, und das Ergebnis dieser Erweiterung wird zum Skript, das die untergeordnete Shell sieht. Das heißt, wenn Sie schreiben

sudo -u "$target_user" -i <<EOF
echo "$(whoami)"
EOF

Dies zeigt den Namen des ursprünglichen Benutzers an, nicht des Zielbenutzers. Um diese erste Phase der Erweiterung zu vermeiden, zitieren Sie die hier angegebene Dokumentmarkierung nach dem <<Operator:

sudo -u "$target_user" -i <<'EOF'
echo "$(whoami)"
EOF

Wenn Sie also keine Daten von der übergeordneten Shell an die untergeordnete Shell übergeben müssen, können Sie ein hier zitiertes Dokument verwenden:

#!/bin/bash
sudo -u "$target_user" -i  <<'EOF'
log_f() {
echo "LOG line: $@"
}
intVAR=$(date)
log_f "${intVAR}"
EOF

Während Sie eine hier nicht zitierte Dokumentmarkierung verwenden können, um Daten von der übergeordneten Shell an die untergeordnete Shell zu übergeben, funktioniert dies nur, wenn die Daten kein Sonderzeichen enthalten. Das liegt daran, dass in einem Skript wie

sudo -u "$target_user" -i <<EOF
echo "$(whoami)"
EOF

Die Ausgabe von whoamiwird zu einem Bit Shell-Code, nicht zu einer Zeichenfolge. Wenn der whoamiBefehl beispielsweise zurückgegeben "; rm -rf /; "truewird, führt die untergeordnete Shell den Befehl aus echo ""; rm -rf /; "true".

Wenn Sie Daten von der übergeordneten Shell übergeben müssen, können Sie sie auf einfache Weise als Argumente übergeben. Rufen Sie die untergeordnete Shell explizit auf und übergeben Sie die Positionsparameter:

#!/bin/bash
extVAR="yourName"
sudo -u "$target_user" -i sh  _ "$extVAR" <<'EOF'
  log_f() {
  echo "LOG line: $@"
  }
  intVAR=$(date)
  log_f "${intVAR}" "${1}"
EOF

Wenn Sie mehrere Variablen übergeben müssen, ist es besser, sie nach Namen zu übergeben. Rufen Sie envexplizit auf, um Umgebungsvariablen für die untergeordnete Shell festzulegen.

#!/bin/bash
extVAR="yourName"
sudo -u "$target_user" -i env extVAR="$extVAR" sh <<'EOF'
  log_f() {
  echo "LOG line: $@"
  }
  intVAR=$(date)
  log_f "${intVAR}" "${1}"
EOF

Beachten Sie, dass Sie, wenn Sie erwartet haben /etc/profileund der Zielbenutzer ~/.profilegelesen werden soll, diese explizit lesen oder bash --loginstattdessen aufrufen müssen sh.

Gilles 'SO - hör auf böse zu sein'
quelle
1

Dies funktioniert nicht, da die Funktion log_fin der von sudo su -Ihnen gestarteten Shell nicht deklariert ist . Stattdessen:

extVAR="yourName"

sudo su - <user> << EOF

log_f() {
echo "LOG line: $@"
}

  intVAR=$(date)
  log_f ${intVAR} ${extVAR}
EOF

Sie müssen die in der Root-Subshell definierte Funktion erhalten. Das könnte es tun, aber ... ich weiß nicht, was das meiste davon macht. Zumindest - solange weder stdin sudonoch sustdin zum Lesen eines Passworts benötigt wird - sollte dies log_f()deklariert werden.

Ich vertraue darauf, dass Sie diese Werte übrigens in die Eingabe der Root-Shell erweitern wollen. Wenn Sie dies nicht beabsichtigen, sollten Sie EOFund die Vars selbst zitieren .

mikeserv
quelle
1

In meinem Fall musste ich ein Array übergeben und hatte einige Probleme, hatte aber nach einer Weile Erfolg, indem envich die Werte des Arrays auf einen -key wiederholte und den beabsichtigten Code einwickelte bash -c '<intended code>'und es im Grunde das Array neu erstellen ließ , z INNER_KEY=($<env_key>).

Zum Beispiel:

#!/usr/bin/env bash
PLUGINS=(foo bar baz)
sudo -u <some-user> -i env PLUGINS="`echo ${PLUGINS[@]}`" sh <<'EOF'
  bash -c '
    FOO=($PLUGINS);
    echo values: \[${FOO[@]}\];

    for pl in ${FOO[@]};
      do echo value: $pl;
    done;
  '
EOF

Das Problem war, dass ich so etwas nicht direkt tun konnte (nicht verwenden bash -c '...'):

FOO=($PLUGINS);
for pl in ${FOO[@]};
...
johanmynhardt
quelle