¿Por qué "sudo su" en un script de shell no ejecuta el resto del script como root?

36

Un script de muestra puede ser el siguiente:

#!/bin/bash
sudo su
ls /root

Cuando se utiliza ./test.shcomo usuario normal, en lugar de ejecutar lscomo superusuario y salir, cambia a root; y cuando me desconecto, se ejecuta ls /rootcomo el usuario normal.

¿Alguien puede decirme sobre el mecanismo al respecto?

Hongxu Chen
fuente
13
sudo sume duelen los ojos
gelraen
Se usa porque las personas no conocen sudo lo suficientemente bien, por lo que necesitan una forma de ejecutar su en sistemas donde la raíz está protegida por una contraseña deliberadamente corrupta. Pero sí, sudo "redundifica" el uso de su.
Johan
1
Sin sudo -sembargo, ¿no puedes usar ?
Joe Z.
@Johan, a menudo lo uso sudo suporque estoy más acostumbrado a las opciones suque a las de sudo. Conozco bastante bien las opciones de sudo, pero puedo escribir las su más rápido. Pero sí, supongo que eso significa que no sé sudo lo suficientemente bien.
user606723
1
Acabo de revisar la página de manual de sudo. Parece que sudo -ies similar a su -mientras sudo -sfunciona como su(sin el tablero)
Johan

Respuestas:

49

Los comandos en un script se ejecutan uno por uno, independientemente. El Script en sí mismo como el padre de todos los comandos en el script, es otro proceso independiente y el comando su no lo cambia y no puede cambiarlo a root: el comando su crea un nuevo proceso con privilegios de root.

Una vez que se completa el comando su, el proceso padre, que todavía se ejecuta como el mismo usuario, ejecutará el resto del script.

Lo que quieres hacer es escribir un script de envoltura. Los comandos privilegiados van al script principal, por ejemplo~/main.sh

#!/bin/sh
ls /root

El script de envoltorio llama al script principal con permisos de root, como este

#!/bin/sh
su -c ~/main.sh root

Para iniciar este proceso, ejecuta el reiniciador, que a su vez inicia el script principal después de cambiar de usuario al usuario raíz.

Esta técnica de envoltura se puede usar para convertir el script en una envoltura a su alrededor. Básicamente, verifique si se está ejecutando como root, de lo contrario, use "su" para reiniciarse.

$ 0 es una forma práctica de hacer que un script se refiera a sí mismo, y el comando whoami puede decirnos quiénes somos (¿somos root?)

Entonces, el script principal con el contenedor incorporado se convierte en

#!/bin/sh
[ `whoami` = root ] || exec su -c $0 root
ls /root

Tenga en cuenta el uso de exec. Significa "reemplazar este programa por", que efectivamente finaliza su ejecución e inicia el nuevo programa, lanzado por su, con root, para ejecutarse desde la parte superior. La instancia de reemplazo es "root", por lo que no ejecuta el lado derecho de ||

Johan
fuente
1
fwiw, una adición a este punto. Si estuviera escribiendo un script como este, solo haría una declaración if al principio que verifique $ EUID y, si no es cero, sudo y salga, de lo contrario, continúe con la ejecución del script.
Bratchley
De acuerdo, y actualizaré la respuesta para explicar esto.
Johan
2
Quizás es un poco arcaico, pero me encantan los caminos absolutos a cada ejecutable, por lo que alguien no puede cambiar el script ~ / main.sh en algo nefasto. Atacando a la parte USUARIO del guión
artifex
2
También es posible que desee captar los argumentos que se le pasaron al incluir una referencia a $ *
Bratchley
@JoelDavis Siempre me encuentro con el muro de "¿y si hay caracteres de espacios en los argumentos". Nunca he encontrado una solución satisfactoria. Una vez que escribí un guión que incluía sus argumentos en un archivo temporal, un argumento por línea, y luego llamé lo que necesitaba y pasé a ese guión final el argumento de qué archivo leer para encontrar los argumentos originales.
Johan
20

Use lo siguiente en el script.

sudo su <<HERE
ls /root
HERE

El código entre el bloque AQUÍ se ejecutará como root.

Ankit
fuente
66
sudo suestá llamando a dos programas. Use sudo -s <<HEREDOCo su user <<HEREDOC... Estúpido límite de 5 minutos.
Johan
6

Sin más argumentos suse ejecutará el shell de inicio de sesión para root. Eso es lo que realmente hace la primera línea de tu script. Cuando salga, se cierra el shell de inicio de sesión, declaraciones de su y la escritura continúa la ejecución, que es con la segunda línea: ls /root. Creo que simplemente puedes sudo ls /roothacer lo que quieras.

Bananguin
fuente
Sí, sé que puedo hacer esto ls, pero esto es solo una muestra. De hecho, necesito hacer muchas más cosas con privilegios de root :-) Así que prefiero la respuesta de @ Ankit.
Hongxu Chen
1

Una vez que inicie sudo suun nuevo proceso con la eficacia userid (euid=EUID)de super usuario bifurcado, por lo tanto, tenemos un nuevo bash ejecutándose en diferentes ID de proceso (pid=PID)asociados con el mismo terminal (tname=TTY).

Explicación

Supongamos que después de disparar ps -A | grep bashtiene 21460 pts/2 00:00:00 bashcomo salida. Ahora, cuando ejecutas ./test.shambos comandos sudo suy ls /rootte ponen en cola PID 21460. Después de la ejecución cuando vuelva a rootpresionar como usuario activo ps -A | grep bash, notará que se ejecuta un nuevo bash PID say, 21570. Salir de root bashmatará a bash recién bifurcado user's bashy, por lo tanto, ejecutará el comando en spool ls /rootantes de liberar el mensaje.

sol profundo
fuente
Si usar su o sudo fuera "persistente" en bash (o en cualquier otro lugar) crearía muchos más problemas de los que resolvió. Debe hacer lo mínimo posible como root para la seguridad y la protección. El punto principal de tener su y sudo (¡aparte de la seguridad!) Es hacerte pensar cuidadosamente sobre lo que necesita privilegios de root.
Joe