Tengo un script que hace varias cosas diferentes, la mayoría de las cuales no requieren privilegios especiales. Sin embargo, una sección específica, que he contenido dentro de una función, necesita privilegios de root.
No deseo requerir que todo el script se ejecute como root, y quiero poder llamar a esta función, con privilegios de root, desde el script. Solicitar una contraseña si es necesario no es un problema, ya que de todos modos es principalmente interactivo. Sin embargo, cuando trato de usar sudo functionx, obtengo:
sudo: functionx: command not found
Como esperaba, exportno hizo la diferencia. Me gustaría poder ejecutar la función directamente en el script en lugar de dividirla y ejecutarla como un script separado por varias razones.
¿Hay alguna forma de hacer que mi función sea "visible" para sudo sin extraerla, encontrar el directorio apropiado y luego ejecutarlo como un script independiente?
La función se trata de una página en sí misma y contiene múltiples cadenas, algunas con comillas dobles y otras con comillas simples. También depende de una función de menú definida en otra parte del script principal.
Solo esperaría que alguien con sudo CUALQUIERA pueda ejecutar la función, ya que una de las cosas que hace es cambiar las contraseñas.

declaretambién a ellas.Respuestas:
Admito que no hay una forma simple e intuitiva de hacer esto, y esto es un poco hackey. Pero, puedes hacerlo así:
O más simplemente:
Esto funciona para mi:
Básicamente,
declare -fdevolverá el contenido de la función, que luego pasará a enbash -clínea.Si desea exportar todas las funciones desde la instancia externa de bash, cambie
FUNC=$(declare -f hello)aFUNC=$(declare -f).Editar
Para abordar los comentarios sobre las citas, vea este ejemplo:
fuente
echo "Hello!"es efectivamente el mismo queecho Hello!(es decir, las comillas dobles no hacen ninguna diferencia para este comando de eco en particular). En muchas otras circunstancias, las comillas dobles en la función pueden romper elbash -ccomando.bash -xcen lugar de sólobash -c) y parece quebashes lo suficientemente inteligente como para las cosas volver a citar en esta situación, incluso hasta el punto de sustituir las comillas dobles con comillas simples y cambiando'a'\''si es necesario. Estoy seguro de que habrá algunos casos que no puede manejar, pero definitivamente funciona para casos al menos simples y moderadamente complejos, por ejemplo, intentefunction hello() { filename="this is a 'filename' with single quotes and spaces" ; echo "$filename" ; } ; FUNC=$(declare -f hello) ; bash -xc "$FUNC ; hello"declare -fimprime la definición de la función de manera que bash pueda volver a analizarla, por lobash -c "$(declare -f)"que funciona correctamente (suponiendo que la capa externa también sea bash). El ejemplo que publicó muestra que funciona correctamente: el lugar donde se cambiaron las comillas está en la traza , porque bash imprime trazas en la sintaxis de shell, por ejemplo, intentebash -xc 'echo "hello world"'sudo yourFunctionse encuentra (de lo contrario, obtiene un error de segmentación de la recursión)El "problema" es que
sudoborra el entorno (a excepción de un puñado de variables permitidas) y establece algunas variables en valores seguros predefinidos para proteger contra riesgos de seguridad. en otras palabras, esto no es realmente un problema. Es una característicaPor ejemplo, si configuró
PATH="/path/to/myevildirectory:$PATH"ysudono configuró PATH en un valor predefinido, cualquier script que no especifique el nombre de ruta completo para TODOS los comandos que ejecuta (es decir, la mayoría de los scripts) se vería/path/to/myevildirectoryantes que cualquier otro directorio. Ponga comandos comolsugrepotras herramientas comunes allí y podrá hacer fácilmente lo que quiera en el sistema.La forma más fácil / mejor es volver a escribir la función como un script y guardarla en algún lugar de la ruta (o especificar la ruta completa al script en la
sudolínea de comandos, lo que deberá hacer de todos modos a menos quesudoesté configurado para permitirle ejecutar CUALQUIER comando como root) y hacerlo ejecutable conchmod +x /path/to/scriptname.shLa reescritura de una función de shell como un guión es tan simple como el ahorro de los comandos dentro de la definición de función en un archivo (sin el
function ...,{y}líneas).fuente
sudo -Eevita limpiar el medio ambiente.He escrito mi propia
Sudofunción bash para hacer eso, funciona para llamar a funciones y alias:fuente
Puedes combinar funciones y alias
Ejemplo:
entonces
sudo hellofuncionafuente
Aquí hay una variación en la respuesta de Will . Implica un
catproceso adicional , pero ofrece la comodidad de heredoc. En pocas palabras, es así:Si quieres más comida para pensar, prueba esto:
El resultado es:
Aquí tenemos la
menufunción correspondiente con la de la pregunta, que está "definida en otra parte del script principal". Si "en otro lugar" significa que su definición ya se ha leído en esta etapa cuandosudose ejecuta la función exigente , entonces la situación es análoga. Pero puede que aún no se haya leído. Puede haber otra función que aún activará su definición. En este casodeclare -f menutiene que ser reemplazado por algo más sofisticado, o todo el script corregido de una manera que lamenufunción ya esté declarada.fuente
menufunción se habría declarado antes de este punto, comofse invoca desde un menú.Suponiendo que su script sea (a) autocontenido o (b) pueda obtener sus componentes en función de su ubicación (en lugar de recordar dónde está su directorio de inicio), puede hacer algo como esto:
$0nombre de ruta para el script, use eso en elsudocomando, y pase una opción que el script verificará, para llamar a la actualización de contraseña. Siempre y cuando confíes en encontrar el script en la ruta (en lugar de solo ejecutarlo./myscript), deberías obtener un nombre de ruta absoluto$0.sudoejecuta el script, tiene acceso a las funciones que necesita en el script.uidy se dará cuenta de que se ejecutó como usuario raíz , y al ver que tiene la opción establecida para indicarle que actualice la contraseña, vaya y haga ese.Los scripts pueden repetirse en sí mismos por varias razones: el cambio de privilegios es uno de esos.
fuente