Función directa y variables en sudo su - <usuario> << EOF

9

He declarado funciones y variables en bash / ksh y necesito reenviarlas a 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
fuente

Respuestas:

4

sudo su -, que es una forma complicada de escribir sudo -i, construye un ambiente prístino. Ese es el punto de un shell de inicio de sesión. Incluso un plano sudoelimina la mayoría de las variables del entorno. Además sudoes un comando externo; no hay forma de elevar los privilegios en el script de shell en sí, solo para ejecutar un programa externo ( sudo) con privilegios adicionales, y eso significa que las variables de shell (es decir, las variables no exportadas) y las funciones definidas en el shell principal no estarán disponibles en La cáscara del niño.

Puede pasar las variables de entorno no invocando un shell de inicio de sesión (en sudo bashlugar de sudo su -o sudo -i) y configurando sudo para dejar pasar estas variables (con Defaults !env_reseto Defaults env_keep=…en el sudoersarchivo). Esto no lo ayudará con las funciones (aunque bash tiene una función de exportación de funciones, sudo lo bloquea).

La forma normal de obtener sus funciones en el shell hijo sería definirlas allí. Tenga cuidado de citar: si utiliza <<EOFpara el documento here, el contenido del documento here se expande primero por el shell principal, y el resultado de esa expansión se convierte en el script que ve el shell secundario. Es decir, si escribes

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

Esto muestra el nombre del usuario original, no el usuario objetivo. Para evitar esta primera fase de expansión, cite el marcador del documento aquí después del <<operador:

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

Entonces, si no necesita pasar datos del shell principal al shell secundario, puede usar un documento citado aquí:

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

Si bien puede hacer uso de un marcador de documento aquí sin comillas para pasar datos desde el shell principal al shell secundario, esto solo funciona si los datos no contienen ningún carácter especial. Eso es porque en un guión como

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

la salida de se whoamiconvierte en un código de shell, no en una cadena. Por ejemplo, si el whoamicomando regresó "; rm -rf /; "true, el shell hijo ejecutaría el comando echo ""; rm -rf /; "true".

Si necesita pasar datos desde el shell principal, una forma simple es pasarlos como argumentos. Invoque el shell hijo explícitamente y pásele parámetros posicionales:

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

Si tiene que pasar varias variables, será más fácil leerlas por nombre. Llame envexplícitamente para establecer variables de entorno para el shell hijo.

#!/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

Tenga en cuenta que si esperaba que /etc/profileel usuario objetivo ~/.profilefuera leído, tendrá que leerlo explícitamente o llamar en bash --loginlugar de hacerlo sh.

Gilles 'SO- deja de ser malvado'
fuente
1

Esto no funciona porque la función log_fno se declara en el sudo su -shell que inicia. En lugar:

extVAR="yourName"

sudo su - <user> << EOF

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

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

Necesita obtener la función definida en el subshell raíz. Eso podría hacerlo, pero ... No sé qué hace la mayoría de esas cosas. Al menos, siempre y cuando sudoni sunecesiten stdin para leer una contraseña, eso debería log_f()declararse.

Por cierto, confío en que quiere decir expandir esos valores en la entrada del shell raíz. Si no tiene la intención de hacerlo, entonces debe citar EOFy los vars mismos.

mikeserv
fuente
1

En mi caso necesario para pasar una matriz y tenía algunos problemas, pero tuvo éxito después de un tiempo haciendo eco de los valores de la matriz a una envtecla y envolviendo el código previsto en bash -c '<intended code>', y, básicamente, tiene que volver a crear la matriz, por ejemplo .: INNER_KEY=($<env_key>).

Por ejemplo:

#!/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

El problema era que no podía hacer directamente algo como lo siguiente (no usar bash -c '...'):

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