¿Cómo puede un script verificar si se está ejecutando como root?

104

Estoy escribiendo un script bash simple, pero lo necesito para verificar si se está ejecutando como root o no. Sé que probablemente haya una forma muy simple de hacerlo, pero no tengo idea de cómo.

Para que quede claro:
¿Cuál es una forma sencilla de escribir un guión foo.sh , para que el comando ./foo.shsalidas 0, y el comando de sudo ./foo.shsalidas 1?

Malabarba
fuente

Respuestas:

148
#!/bin/bash
if [[ $EUID -ne 0 ]]; then
   echo "This script must be run as root" 
   exit 1
fi
aneeshep
fuente
77
Estoy aceptando esta causa (después de algunas pruebas) usando la variable de sistema EUID resultó ser (aproximadamente 100 veces) más rápido que ejecutar un comando (id -u), pero todas las respuestas funcionaron muy bien.
Malabarba
18
Además, $UIDy $EUIDson bashismos. Los shells que simplemente cumplen con POSIX no tienen esas variables y debes usarlos id(1)en su lugar.
David Foerster
3
en un script de bash, podría usar if ((EUID)); then, vea el comentario de @ geirha
jfs
77
@ Andrew: las variables se sustituyen antes de pasar a sudo. Si corres sudo sh -c 'echo $EUID', verás los resultados esperados.
M. Dudley
66
@ Andrew - Sé que llego tarde aquí, pero para la posteridad: $EUIDes un Bashismo (como se mencionó anteriormente por @DavidFoerster), y /bin/shes muy probable que sea un enlace a él /bin/dash, no /bin/bash. sudo bash -c 'echo $EUID'dará el resultado esperado.
Adrian Günter
118

Un usuario root no tiene que llamarse "root". whoamidevuelve el primer nombre de usuario con ID de usuario 0. $USERcontiene el nombre del usuario conectado, que puede tener ID de usuario 0, pero tener un nombre diferente.

El único programa confiable para verificar si la cuenta ha iniciado sesión como root o no:

id -u

Lo uso -upara la identificación de usuario efectiva , no -rpara la identificación de usuario real . Los permisos están determinados por la identificación de usuario efectiva , no por la real .

Pruebas

/etc/passwdcontiene los siguientes nombres de usuario con ID de usuario 0en el orden dado:

rootx
root2

Conectado como root2, da los siguientes resultados:

  • whoami: rootx
  • echo $USER: root2(esto devuelve una cadena vacía si el programa se inició en un entorno vacío, por ejemplo env -i sh -c 'echo $USER')
  • id -u: 0 Como puede ver, los otros programas fallaron en esta verificación, solo id -upasaron.

El script actualizado se vería así:

#!/bin/bash
if ! [ $(id -u) = 0 ]; then
   echo "I am not root!"
   exit 1
fi
Lekensteyn
fuente
55
No necesitas id -uen bash askubuntu.com/questions/30148/…
jfs
55
Siempre trato de cumplir con POSIX lo más posible, usando sh( dash) como intérprete en lugar de bash. Pero buen tiro, salva otro tenedor :)
Lekensteyn
Después de estar fuera de combate por un tiempo, regresé y eché un vistazo. El método de Lekensteyn sí parece ser mejor. Su respuesta es ahora la nueva respuesta aceptada. +1 para ti, Lekensteyn, esp. por sacar esa insignia difícil de sacar de esta pregunta;)
Thomas Ward
Gracias por esperar tanto tiempo por aceptar mi pregunta: DI obtuve una insignia Populista Dorada y una Bonita Respuesta de bronce por esta respuesta :) ¡Me pregunto cómo esta pregunta consiguió esa popular, 345 visitas en un día!
Lekensteyn
3
He visto versiones más cortas, [ -w / ]. La idea sigue siendo la misma. Nota: en ciertos chroots, [ -w /etc/shadow ]fallará porque /etc/shadowno existe, por lo tanto, /se prefiere el enfoque con . Una manera mejor sería verificar la necesidad real de permisos de root. Si el script necesita escribir /etc/someconfig, solo verifique si ese archivo es editable O el archivo no existe y /etces editable.
Lekensteyn
30

Como dijo @Lekensteyn , debes usar una identificación de usuario efectiva. No necesitas llamar id -ua bash:

#!/bin/bash

if [[ $EUID -ne 0 ]]; then
   echo "You must be root to do this." 1>&2
   exit 100
fi

La sugerencia de @ geirha de los comentarios utiliza la evaluación aritmética:

#!/bin/bash

if (( EUID != 0 )); then
   echo "You must be root to do this." 1>&2
   exit 100
fi
jfs
fuente
77
En general, uno debería usar ((..))para probar números y [[..]]para probar cadenas y archivos, así que lo haría en su if (( EUID != 0 )); thenlugar, o simplementeif ((EUID)); then
geirha
@geirha: He añadido tu sugerencia.
jfs
2
EUIDdebería convertirse $EUID. En lugar de usar (( $EUID != 0 )), usa [ $EUID != 0 ]. Funcionará dashtambién con .
Lekensteyn
2
@Lekensteyn: EUIDfunciona bien. La pregunta es etiquetado bashno dash. El comando env -i sh -c '[ $EUID != 0 ]'falla, pero env -i bash -c '(( EUID != 0 ))'funciona. por cierto, dashno funciona para algunos caracteres no ASCII en Ubuntu stackoverflow.com/questions/5160125/... Es 2011 y hay personas que usan otros idiomas.
jfs
Después de mirar hacia atrás mientras me aburro horriblemente y probar, voy a usar este método como se enumera aquí con las $EUIDcosas de aquí en adelante. Como resultado, he cambiado la respuesta aceptada.
Thomas Ward
20

Puede lograr esto utilizando el whoamicomando, que devuelve el usuario actual:

#!/bin/bash

if [ `whoami` != 'root' ]
  then
    echo "You must be root to do this."
    exit
fi

...

La ejecución de lo anterior se imprimirá You must be root to do this.si el usuario actual no lo está root.


Nota: una alternativa en algunos casos es simplemente verificar la $USERvariable:

if [ $USER != 'root' ]
Nathan Osman
fuente
Echaré un vistazo al código, veré si no hace que el script falle o algo así. Si funciona, aceptaré tu respuesta :)
Thomas Ward
44
@ George Edison: Recomiendo no usar $USER, especialmente de esta manera. $USERestá configurado por el shell de inicio de sesión, no necesariamente se propaga al programa ( env -i sh -c 'echo $USER'). De esa manera, $USERestá vacío y se produce un error de sintaxis.
Lekensteyn
1
@Lekensteyn No solo lo $USERestablece el shell, sino que también es algo fácil de burlar. Whoami devolverá el usuario real.
Paul de Vrieze
2
@PauldeVrieze ¿Cuál es el punto de engañar a ese cheque?
htorque
1
@andrewsomething: $USERes interpretado por su shell, su ejemplo debe ser sudo sh -c 'echo $USER'para que tenga sentido. @George: hace una suposición equivocada que whoamisiempre regresará rootpara UID 0.
sam hocevar
11

Teniendo en cuenta la eficiencia, puede probar, primero, la EUIDvariable de entorno y luego, si no existe, llamar al idcomando estándar :

if ((${EUID:-0} || "$(id -u)")); then
  echo You are not root.
else
  echo Hello, root.
fi

De esta manera, debido al acceso directo OR , evita llamar a un comando del sistema, priorizando la consulta de una variable en memoria.

Reutilización de código:

function amIRoot() {
  ! ((${EUID:-0} || "$(id -u)"))
}
Luchostein
fuente
Me temo que no lo ha comparado, bueno, sí, y esto lleva el mismo tiempo que id -u. Vea el script de banco junto con los resultados a continuación aquí: pastebin.com/srC3LWQy
LinuxSecurityFreak
9
#!/bin/bash
[[ $(id -u) != 0 ]] 
echo $?
João Pinto
fuente
2

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
No hagas esto. Intenta iniciar sesión directamente como root, mientras que sudo puede ser necesario en muchos sistemas porque el primero está prohibido. Además, el shebang está destinado a garantizar que su script se ejecute en el que fue diseñado, mientras que su método hará que el script se ejecute en el shell predeterminado de la raíz, lo que no se puede predecir si el script lo ejecuta alguien que no sea el autor. Por lo tanto, usar el shebang para elevar los privilegios de un script romperá severamente su portabilidad y provocará errores en muchos sistemas. (su: Fallo de autenticación)
StarCrashr
1
#!/bin/bash
uid=`id -u`
if [ "$uid" == "0" ]
then
    echo 1
else
    echo 0
fi
Delan Azabani
fuente
1

Este fragmento podría:

  • Consultar diferentes sesiones
  • sugiero usar sudo !!
  • y devuelve un error
if ["$ (whoami & 2> / dev / null)"! = "root"] && ["$ (id -un & 2> / dev / null)"! = "root"]
      entonces
      echo "¡Debes ser root para ejecutar este script!"
      echo "usa 'sudo !!'"
      salida 1
fi
rubo77
fuente
1

Esta respuesta es solo para guardar una idea, puede ser útil para algunos de ustedes. Si necesita un script que se ejecuta desde la GUI del escritorio y requiere privilegios de root, intente de esta manera:

#!/bin/bash
if ! [ $(id -u) = 0 ]; then
   gksudo -w $0 $@
   exit
fi

#here go superuser commands, e.g. (switch intel cpu into powersave mode):
echo 1 > /sys/devices/system/cpu/intel_pstate/no_turbo
cpupower frequency-set -g powersave

De esta manera, obtendrá una buena ventana de diálogo que le pedirá la contraseña de usuario root. Al igual que con la línea de comandos sudo.

Es gksudoposible que no esté disponible en su sistema y luego instálelo con sudo apt-get install gksu.

gertas
fuente
0

Este código funciona tanto en Bash como en Bourne sh (probado en FreeBSD) que no define EUID. Si EUID existe, se devuelve su valor, de lo contrario se ejecuta el comando 'id'. Es un poco más corto que el ejemplo "o" anterior, ya que utiliza un shell incorporado ": -".

Raíz en sh:

# echo $EUID

# euid=${EUID:-`id -u`}
# echo $euid
0

In bash:
[chaapala@tenfwd2 ese]$ euid=${EUID:-`id -u`}
[chaapala@tenfwd2 ese]$ echo $euid
10260
Clayton Haapala
fuente