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
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 sudo
elimina la mayoría de las variables del entorno. Además sudo
es 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 bash
lugar de sudo su -
o sudo -i
) y configurando sudo para dejar pasar estas variables (con Defaults !env_reset
o Defaults env_keep=…
en el sudoers
archivo). 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 <<EOF
para 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 whoami
convierte en un código de shell, no en una cadena. Por ejemplo, si el whoami
comando 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 env
explí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/profile
el usuario objetivo ~/.profile
fuera leído, tendrá que leerlo explícitamente o llamar en bash --login
lugar de hacerlo sh
.
Esto no funciona porque la función log_f
no 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 sudo
ni su
necesiten 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 EOF
y los vars mismos.
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 env
tecla 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[@]};
...