Cómo verificar si se ejecuta como root en un script bash

275

Estoy escribiendo un script que requiere permisos de nivel raíz, y quiero hacerlo de modo que si el script no se ejecuta como root, simplemente haga eco de "Ejecútelo como root". y salidas

Aquí hay un pseudocódigo para lo que estoy buscando:

if (whoami != root)
  then echo "Please run as root"

  else (do stuff)
fi

exit

¿Cómo podría lograr esto (de forma limpia y segura)? ¡Gracias!

Ah, solo para aclarar: la parte (hacer cosas) implicaría ejecutar comandos que en sí mismos requieren root. Por lo tanto, ejecutarlo como un usuario normal solo generaría un error. Esto solo está destinado a ejecutar de manera limpia un script que requiere comandos raíz, sin usar sudo dentro del script, solo estoy buscando algo de azúcar sintáctico.

Nathan
fuente
8
(1) hacer que no sea ejecutable por otra cosa que no sea root (2) organizar más permisos también .. (3) id -udevuelve 0para root.
Escrito el

Respuestas:

404

La variable de entorno $ EUID contiene el UID del usuario actual. El UID de Root es 0. Use algo como esto en su script:

if [ "$EUID" -ne 0 ]
  then echo "Please run as root"
  exit
fi

Nota: Si obtiene, 2: [: Illegal number:verifique si tiene #!/bin/shen la parte superior y cámbielo a #!/bin/bash.

ptierno
fuente
Parece que buenos permisos y tener esto es una doble capa de seguridad
Kolob Canyon
25
Creo que es mejor comparar cadena con cadena, número con número. usando corchetes dobles, puede usar> directamente sin presupuesto [[$ EUID> 0]]
Sergio Abreu
77
Recibí 2: [: Illegal number:advertencia hasta que lo cambié a la versión de Sergio.
alexeydemin
1
@ thekiwi5000 El punto y coma solo se requiere si thenestá en la misma línea que la condición ...
ptierno
1
@StephenAngelico Sudo debería funcionar. Si lo está probando haciendo $ sudo echo $ EUID; esa es una mala prueba y fallará porque $ EUID se expande antes de que el comando se pase a sudo. Intente poner echo $ EUID en un script de prueba y ejecutarlo con sudo.
user1169420
79

En un script bash, tiene varias formas de verificar si el usuario en ejecución es root.

Como advertencia , no verifique si un usuario es root utilizando el rootnombre de usuario. Nada garantiza que se llame al usuario con ID 0 root. Es una convención muy fuerte que se sigue ampliamente, pero cualquiera podría cambiar el nombre del superusuario por otro nombre.

Creo que la mejor manera cuando se usa bash es usar $EUID, desde la página de manual:

EUID   Expands to the effective user ID of the current  user,  initialized
       at shell startup.  This variable is readonly.

Esta es una mejor manera de lo $UIDque podría cambiarse y no reflejar el usuario real que ejecuta el script.

if (( $EUID != 0 )); then
    echo "Please run as root"
    exit
fi

Una forma de abordar ese tipo de problema es inyectando sudomis comandos cuando no se ejecuta como root. Aquí hay un ejemplo:

SUDO=''
if (( $EUID != 0 )); then
    SUDO='sudo'
fi
$SUDO a_command

De esta manera, mi comando es ejecutado por root cuando uso el superusuario o sudocuando lo ejecuta un usuario normal.

Si su script siempre debe ser ejecutado por root, simplemente configure los derechos en consecuencia ( 0500).

sberder
fuente
Si la persona que está tratando de ejecutar el script no tiene privilegios de sudo, ¿esto provocará el error y el comando no se ejecutará? Solo quiero asegurarme, lo entiendo correctamente.
Caperneoignis
1
No estoy seguro de que esta respuesta sea 100% completamente correcta. En RHEL7.2 usando Bash 4.2.46 ... si printf $EUIDcon o sin sudo, recupero mi propio UID. Si uso id -uobtengo mi UID y cuando lo invoco con sudo obtengo 0 de regreso. ¿Hice algo mal?
0xSheepdog
44
@ 0xSheepdog, es posible que en bash cli, la expansión de la variable $ EUID se resuelva primero y luego sudo cambie de usuario. Por lo tanto, obtendría ese comportamiento, pero en los scripts, todo funcionaría bien.
Alexander Bird
@AlexanderBird Buen punto, gracias! No hice ninguna prueba real, solo reporté mi experiencia.
0xSheepdog
3
Use una "herejía" para su prueba para evitar la expansión local de la variable. Comparar sudo bash <<<'echo $EUID'a bash <<<'echo $EUID'. Más información sobre la herejía al estilo
Bruno Bronosky
75

Se han dado algunas respuestas, pero parece que el mejor método es usar:

  • id -u
  • Si se ejecuta como root, devolverá un id de 0.

Esto parece ser más confiable que los otros métodos, y parece que devuelve una identificación de 0 incluso si se ejecuta el script sudo.

Nathan
fuente
1
Genial, esta es la mejor respuesta
Dan Ortega
59
if [[ $(id -u) -ne 0 ]] ; then echo "Please run as root" ; exit 1 ; fi

o

if [[ `id -u` -ne 0 ]] ; then echo "Please run as root" ; exit 1 ; fi

:)

Dale_Reagan
fuente
Podría considerar integrar la respuesta de Jeremy J Starcher con esta parte, al final siempre es lo mismo ...
realmente agradable
Sé que desde la terminal, cuando me olvido de prefijar algo sudo, simplemente puedo escribir sudo !!y hace el trabajo por mí, en lugar de presionar la flecha ARRIBA, ir al comienzo de la línea y agregar sudo a mano. No estoy seguro si eso es una cosa BASH o una cosa SUDO u otra, pero funciona la mayor parte del tiempo.
0xSheepdog
@ 0xSheepdog: es una cosa Bash (y una característica de algunos otros shells como csh, donde se originó el IIRC).
Pausado hasta nuevo aviso.
Con todo, eliminaría la parte marcada en su conjunto y volvería a escribir la línea ok en if [ "$(id -u)" -ne 0 ]; then echo 'Please run as root.' >&2; exit 1; fi. Salud.
LinuxSecurityFreak
29

Como @wrikken mencionó en sus comentarios, id -ues mucho mejor verificar la raíz.

Además, con el uso adecuado de sudo, podría hacer que el script verifique y vea si se está ejecutando como root. Si no, sudohaga que se recupere a través de y luego se ejecute con permisos de root.

Dependiendo de lo que haga el script, otra opción puede ser configurar una sudoentrada para cualquier comando especializado que el script pueda necesitar.

Jeremy J Starcher
fuente
¿Hay alguna manera elegante de hacer que un programa se recupere? ¿Quizás hay alguna variable bash con la ruta absoluta al programa?
Nathan
1
No estoy cerca de un indicador de BASH en este momento para probar, pero $0tiene el nombre del script en ejecución. Hay algunos ejemplos aquí que podrían ayudarle.
Jeremy J Starcher
25

Hay una verificación simple para que un usuario sea root.

La [[ stuff ]]sintaxis es la forma estándar de ejecutar un check in bash.

error() {
  printf '\E[31m'; echo "$@"; printf '\E[0m'
}

if [[ $EUID -eq 0 ]]; then
    error "Do not run this as the root user"
    exit 1
fi

Esto también supone que desea salir con un 1 si falla. loserror función es un toque que establece el texto de salida en rojo (no es necesario, pero es bastante elegante si me preguntas).

Slater Victoroff
fuente
¿Cuál es ese errorcomando? Mi sistema no parece tenerlo. . .
ruakh
Oh, eso es solo una pequeña cosa de estilo. No importa tanto, pero lo adjuntaré.
Slater Victoroff
44
¡Eso es muy bonito! Si puedo sugerir algunas mejoras: (1) mueva la nueva línea hasta el final; (2) escribir en error estándar en lugar de salida estándar; (3) solo configure el color si el error estándar es un terminal (en lugar de arriesgarse a escribir caracteres de escape en archivos de registro lesso lo que sea); y (4) establecer un color de fondo, de modo que el texto sea legible independientemente del color de fondo del terminal del usuario. Entonces, algo así function error () { if [[ -t 2 ]] ; then echo $'\033[31;2;47m'"$@"$'\033[0m' ; else echo "$@" ; fi >&2 ; }. (Ajustar como se desee)
ruakh
3
¿No debería ser "-ne" en lugar de "-eq"?
Carlos Rendon
2
El código de @CarlosRendon Slater es para evitar que algo se ejecute como root. (Esto es lo opuesto a lo que pedía el OP, pero el método de verificación sería el mismo.)
Joshua Taylor
11

De manera muy simple, solo pon:

if [ "$(whoami)" == "root" ] ; then
    # you are root
else
    # you are not root
fi

El beneficio de usar esto en lugar de ides que puede verificar si cierto usuario no root también está ejecutando el comando; p.ej.

if [ "$(whoami)" == "john" ] ; then
    # you are john
else
    # you are not john
fi
Matthew Trotter
fuente
si prueba al usuario con una cadena "root", ¿no está permitiendo ejecutar a nadie que se llame "root"?
pcarvalho
Olvidaste el ';' después del if
Triskeldeian
1
@peteroak, ¿a quién más se llamaría root además de root?
ptierno
3
+1 por responder realmente la pregunta sobre en whoamilugar de usar id; el whoamicomando también se puede usar para buscar otros usuarios que no sean root, por nombre.
Jez
10

0- Lea la documentación oficial de GNU Linux, hay muchas maneras de hacerlo correctamente.

1- asegúrese de poner la firma del shell para evitar errores de interpretación:

 #!/bin/bash

2- este es mi guión

#!/bin/bash 

if [[ $EUID > 0 ]]; then # we can compare directly with this syntax.
  echo "Please run as root/sudo"
  exit 1
else
  #do your stuff
fi
Sergio Abreu
fuente
10

En esta respuesta, que quede claro, supongo que el lector puede leer bashy ejecutar scripts de shell POSIX comodash .

Creo que no hay mucho que explicar aquí ya que las respuestas altamente votadas hacen un buen trabajo al explicar gran parte de ello.

Sin embargo, si hay algo más que explicar, no dude en comentar, haré todo lo posible para llenar los vacíos.


bashSolución integral optimizada (no solo ) para rendimiento y confiabilidad; todos los depósitos compatibles

Nueva solución:

# bool function to test if the user is root or not
is_user_root () { [ ${EUID:-$(id -u)} -eq 0 ]; }

Benchmark (guardar en archivo is_user_root__benchmark)

###############################################################################
##                          is_user_root() benchmark                         ##
##                  Bash is fast while Dash is slow in this                  ##
##          Tested with Dash version 0.5.8 and Bash version 4.4.18           ##
##                     Copyright: 2020 Vlastimil Burian                      ##
##                      E-mail: [email protected]                      ##
##                             License: GPL-3.0                              ##
##                               Revision: 1.0                               ##
###############################################################################

# intentionally, the file does not have executable bit, nor it has no shebang
# to use it, please call the file directly with your shell interpreter like:

# bash is_user_root__benchmark
# dash is_user_root__benchmark

# bool function to test if the user is root or not
is_user_root () { [ ${EUID:-$(id -u)} -eq 0 ]; }

# helper functions
print_time   () { date +"%T.%2N"; }
print_start  () { printf '%s' 'Start  : '; print_time; }
print_finish () { printf '%s' 'Finish : '; print_time; }

readonly iterations=10000

printf '%s\n' '______BENCHMARK_____'
print_start

i=1; while [ $i -lt $iterations ]; do
    is_user_root
    i=$((i + 1))
done

print_finish

Solución original:

#!/bin/bash

is_user_root()
# function verified to work on Bash version 4.4.18
# both as root and with sudo; and as a normal user
{
    ! (( ${EUID:-0} || $(id -u) ))
}

if is_user_root; then
    echo 'You are the almighty root!'
else
    echo 'You are just an ordinary user.'
fi

^^^ Se demostró que la solución eliminada no acelera las cosas, pero ha existido durante mucho tiempo, así que la mantendré aquí todo el tiempo que considere necesario.


Explicación

Dado que es muchísimo más rápido leer la variable $EUIDestándar bash, el número de identificación de usuario efectivo, que ejecutar el id -ucomando para encontrar la ID de usuario POSIX , esta solución combina ambos en una función muy bien empaquetada. Si, y solo si, $EUIDpor alguna razón no está disponible, el id -ucomando se ejecutará, asegurando que obtengamos el valor de retorno adecuado sin importar las circunstancias .


¿Por qué publico esta solución después de tantos años?

Bueno, si veo correctamente, parece que falta un fragmento de código arriba.

Verá, hay muchas variables que deben tenerse en cuenta, y una de ellas es combinar rendimiento y confiabilidad .


Solución POSIX portátil + Ejemplo de uso de la función anterior

#!/bin/sh

# bool function to test if the user is root or not (POSIX only)
is_user_root() { [ "$(id -u)" -eq 0 ]; }

if is_user_root; then
    echo 'You are the almighty root!'
    exit 0 # unnecessary, but here it serves the purpose to be explicit for the readers
else
    echo 'You are just an ordinary user.' >&2
    exit 1
fi

Conclusión

Por mucho que posiblemente no te guste, el entorno Unix / Linux se ha diversificado mucho. Lo que significa que hay personas a las que les gusta bashtanto, que ni siquiera piensan en la portabilidad ( shells POSIX ). Otros como yo prefieren los proyectiles POSIX . Hoy en día es una cuestión de elección personal y necesidades.

LinuxSecurityFreak
fuente
6

Si el script realmente requiere acceso de root, entonces sus permisos de archivo deberían reflejar eso. Tener una secuencia de comandos raíz ejecutable por usuarios no root sería una señal de alerta. Le animo a que no controle el acceso con un ifcheque.

chown root:root script.sh
chmod u=rwx,go=r script.sh
John Kugelman
fuente
44
Si alguien tiene sus permisos para que esto funcione muy bien, pero siento que el uso excesivo de la 777bomba hace que esta verificación sea un poco defectuosa para el tipo de usuarios que cometerían el error en primer lugar.
Slater Victoroff
77
Esto supone que el usuario está ejecutando un script ejecutable. Si el usuario simplemente llama bash /path/to/script, aún puede ejecutarse aunqueo=r
ptierno
5

Una manera simple de hacer que el script solo sea ejecutable por root es comenzar el script con la línea:

#!/bin/su root

alexandre1985
fuente
1
Tengo curiosidad por qué esta respuesta no se vota más alto. Parece el más simple y limpio. ¿Hay desventajas aquí?
Bassinator
@Bassinator Creo que algunas personas dicen que no se ejecutará en ciertos nix, pero hasta ahora ha funcionado perfectamente en mi Linux. ¡Intentalo! Tal vez esta respuesta haya llegado tarde a la carrera, pero estoy tratando de agregar conocimiento que sea simple para la comunidad (en lugar de dar respuestas similares, como la mayoría en este hilo: /) Vote esto si tiene la suerte de leer esto y funciona en su máquina
alexandre1985
@TamusJRoyce Si el objetivo es verificar si se está ejecutando como root y no forzar que el script se ejecute solo como root, ¿por qué entonces en cada respuesta, después de la verificación si se está ejecutando como root, hacen el script exit? ¿Y todavía se están votando esas respuestas? Supongo que la gente implícitamente no quiere que el script se ejecute como root. Así que sigo esa forma de pensar, con una respuesta más simple. Pero sí, también puedes aprender de las respuestas más detalladas anteriores
alexandre1985
@ alexandre1985 Exactamente. Escenario: si se ejecuta como root, tal vez desee que un script establezca de forma predeterminada la instalación global del programa cuando le pregunte cómo desea instalarlo. De lo contrario, el valor predeterminado está configurado para instalarlo localmente. En lugar de presionar enter, el usuario podría optar por instalarlo global o local. Pero si les gusta el valor predeterminado, pueden presionar enter. Y no se les solicitará una contraseña. Su shebang nunca "comprobará" si es root (por título). Pero sigo pensando que esta respuesta es útil.
TamusJRoyce
@TamusJRoyce tiene mucho sentido para tu comentario. De hecho es una preocupación y esta solución no es para ese caso de uso. Abriste mis perspectivas. Tienes razón. Gracias
alexandre1985
4

prueba el siguiente código:

if [ "$(id -u)" != "0" ]; then
    echo "Sorry, you are not root."
    exit 1
fi

O

if [ `id -u` != "0" ]; then
    echo "Sorry, you are not root."
    exit 1
fi
MLSC
fuente
3

Hasta donde sé, la forma correcta de verificarlo es:

if [ $(id -u) = "0" ]; then
    echo "You are root"
else
    echo "You are NOT root"
fi

Consulte la sección "Prueba de raíz" aquí:

http://linuxcommand.org/lc3_wss0080.php

WebBrother
fuente
1
reemplazar = "0"con-eq 0
LinuxSecurityFreak
1
@LinuxSecurityFreak, lo reemplazaré si explica por qué debería hacerlo.
WebBrother
2

id -u es mucho mejor que whoami , ya que algunos sistemas como Android pueden no proporcionar la raíz de la palabra.

Ejemplo:

# whoami
whoami
whoami: unknown uid 0
Smeterlink
fuente
1

Compruebe si es root y salga si no lo es:

if ((EUID != 0)); then
    echo "Root or Sudo  Required for script ( $(basename $0) )"
    exit
fi

O en este ejemplo, intente crear un directorio en la ubicación raíz e intente después de que se hayan elevado los derechos.

Compruebe si es root y, si no es así, eleve si es posible:

# Fails to create these dirs (needs sudo)
mkdir /test-dir-$(basename $0)
rmdir /test-dir-$(basename $0)

if ((EUID != 0)); then
    echo "Granting root privileges for script ( $(basename $0) )"
    if [[ -t 1 ]]; then
        sudo "$0" "$@"
    else
        exec 1> output_file
        gksu "$0" "$@"
    fi
    exit
fi
echo "Root privileges granted..."
# Creates Dirs as it now has rights
mkdir /test-dir-$(basename $0)
rmdir /test-dir-$(basename $0)
Mike Q
fuente
0
#!/bin/bash

# GNU bash, version 4.3.46
# Determine if the user executing this script is the root user or not

# Display the UID
echo "Your UID is ${UID}"

if [ "${UID}" -eq 0 ]
then
    echo "You are root"
else
    echo "You are not root user"
fi

Nota del editor: si no necesita corchetes dobles, use uno solo para la portabilidad del código.

Pramod Kharade
fuente
3
No ha explicado por qué ha proporcionado una respuesta alternativa a una pregunta de 5 años que ya tiene varias respuestas.
Styphon
-1

Verifique la raíz:

ROOT_UID=0   # Root has $UID 0.

if [ "$UID" -eq "$ROOT_UID" ]
then
  echo "You are root."
else
  echo "You are just an ordinary user."
fi

exit 0

Probado y ejecutándose en root.

fvillalba89
fuente