¿Pasar una función a otro usuario en Bash?

11

¿Hay alguna manera de que pueda pasar una función de un usuario a otro?

Por ejemplo, tengo un pequeño script Bash que ejecuto como Root:

#!/bin/bash
user_func(){
  whoami
  exit
}
su vagrant -c 'user_func'

Sin embargo, la función user_func no está definida para el usuario Vagrant, solo para Root, y no se puede ejecutar.

Mi otra opción sería tener múltiples líneas de

su vagrant -c 'cmd1' 
su vagrant -c 'cmd2'
, etc 

O bien, ejecute varios comandos, por ejemplo: su vagrant -c 'cmd1; cmd2; cmd3;'pero preferiría no tener el exceso, especialmente cuando intente ejecutar más de 5 comandos como usuario de Vagrant.

¿Es posible pasar una Función a otro usuario desde el mismo script (por ejemplo, no crear un script en el disco como un usuario diferente y luego ejecutar ese script generado)? ¿O hay otra opción que estoy pasando por alto?

gdieckmann
fuente

Respuestas:

10

Suena como si necesitaras exportesa definición de función primero:

#!/bin/bash
user_func (){
  whoami
  exit
}
export -f user_func
su vagrant -c 'user_func'

debería hacer el truco.

El -findica exportque este es un nombre de función en lugar de un nombre de variable. Citando de help export:

Marca cada NOMBRE para la exportación automática al entorno de comandos ejecutados posteriormente. ....

Opciones:

 -f   refer to shell functions

Como señalaron Peter y Stephane en los comentarios, esto supone dos cosas:

  1. Que su sucomando no sobrescribirá el entorno del usuario
  2. Ese vagrantes el shell de inicio de sesión bash. Si no, puede usar la sulínea de comando alternativa provista por Stephane:

    su vagrant -c 'bash -c user_func'
Joseph R.
fuente
Esto es en realidad exactamente lo que esperaba. No me di cuenta de que podrías exportar la función. Esto funcionó tal como esperaba después de editar el script de muestra. ¡Gracias!
gdieckmann
1
Agradable, pero no funcionará en casos donde suanula el medio ambiente.
Peter
1
Tenga en cuenta que solo funciona si el shell de inicio de sesión de vagrantes bash. Si no,su vagrant -c 'bash -c user_func'
Stéphane Chazelas
6

Es un poco difícil, pero puede imprimir la definición de la función dentro del sommand pasado suy, por supuesto, puede usarla.

$ function foo { do_some_stuff_here; }
$ su test -c "$(typeset -f foo); foo"

Esto funcionará incluso si por alguna razón suse sobrescribe el entorno del shell generado , ya que coloca la definición después de la inicialización del shell. Si escribe la función de manera suficientemente compatible, incluso funcionará cuando los dos usuarios en cuestión estén usando shells diferentes.

Peterph
fuente
+1 ¡Truco realmente genial! Sin embargo, solo una pregunta: ¿se supuede sobrescribir el entorno del shell por factores externos? Quiero decir, en este caso tienes control total sobre la sulínea de comando ya que está en un script. ¿Cómo se puede sobrescribir el entorno de su nuevo shell?
Joseph R.
Por ejemplo, el shell generado supodría hacer una inicialización del entorno. También supodría eliminar parte del entorno de la persona que llama para reforzar un poco la seguridad (aunque esto generalmente se hace con alternativas más potentes como sudo).
Peter
0

Ese no es un script que tienes, es una función. Sin embargo, parece que quieres un guión. Cree un guión adecuado y póngalo, según lo requieran sus necesidades, ya sea en /usr/local/bino dentro /home/vagrant/bin, y de lo que debería poder, p.su vagrant -c '/home/vagrant/bin/myscript.sh'

DopeGhoti
fuente
Es una función dentro de un script de muestra. Mi esperanza era incluir todo lo que quiero hacer dentro de este script único (los comandos se ejecutan como Root y como usuario Vagrant), y no tener que tener un script separado para el usuario Root y un script separado para el usuario Vagrant.
gdieckmann
0

Otra forma algo más portátil de hacer esto (sin dependencia de bash) es hacer que su script se llame a sí mismo y que su comportamiento cambie según el contexto (uid) o los parámetros. Se dan ejemplos de esto en la documentación superdonde muestran un script que necesita permisos de root, llamándose a sí mismo a través de super cuando no es root.

hildred
fuente