¿Cómo detener un script se ejecute si no es la raíz (y echo “No está en ejecución como root! Saliendo ...”)

17

Aquí está mi fuente:

#!/bin/bash

echo "Running script to free general cached memory!"
echo "";
echo "Script must be run as root!";
echo "";
echo "Clearing swap!";
swapoff -a && swapon -a;
echo "";
echo "Clear inodes and page file!";
echo 1 > /proc/sys/vm/drop_caches;
echo "";

Despeja cachés y esas cosas, y se hace eco de que necesita ser ejecutado como root en el terminal. Básicamente, solo quiero que el script deje de ejecutarse si detecta que no se está ejecutando como root.

Ejemplo:

"Running script to free general cached memory!"
"Warning: script must be run as root or with elevated privileges!"
"Error: script not running as root or with sudo! Exiting..."

Si se ejecuta con privilegios elevados, simplemente se ejecuta normalmente. ¿Algunas ideas? ¡Gracias!

M. Knepper
fuente
2
@muru, excepto que otra pregunta es para lo contrario: falla el script si se ejecuta como root.
Stéphane Chazelas
3
@ StéphaneChazelas ah, mi mal. Retraído
muru
Una alternativa es limitar la cantidad de trabajo realizado como rootanteponiendo el prefijo todos los comandos que se deben ejecutar como rootcon sudo.
reinierpost

Respuestas:

46
#!/bin/sh

if [ "$(id -u)" -ne 0 ]; then
        echo 'This script must be run by root' >&2
        exit 1
fi

cat <<HEADER
Host:          $(hostname)
Time at start: $(date)

Running cache maintenance...
HEADER

swapoff -a && swapon -a
echo 1 >/proc/sys/vm/drop_caches

cat <<FOOTER
Cache maintenance done.
Time at end:   $(date)
FOOTER

El usuario raíz tiene UID 0 (independientemente del nombre de la cuenta "raíz"). Si el UID efectivo devuelto por id -uno es cero, el usuario no ejecuta la secuencia de comandos con privilegios de root. Utilícelo id -rupara probar el ID real (el UID del usuario que invoca el script).

No utilice $EUIDen el guión, ya que puede ser modificado por un usuario sin privilegios:

$ bash -c 'echo $EUID'
1000

$ EUID=0 bash -c 'echo $EUID'
0

Si un usuario hiciera esto, obviamente no conduciría a una escalada de privilegios, pero podría llevar a que los comandos en el script no puedan hacer lo que se supone que deben hacer y que los archivos se creen con el propietario incorrecto, etc.

Kusalananda
fuente
1
Nota: en Solaris 5.10, /bin/id -uda/bin/id: illegal option -- u Usage: id [-ap] [user]
soportes jrw32982 Mónica
1
@ jrw32982 Usted debe tener /usr/xpg4/binal principio de su $PATHconseguir el acceso a los servicios públicos POSIX en Solaris.
Kusalananda
1
El punto es que la -uopción de idno es universal y, por tanto, esta solución es universal sólo con la advertencia de que una versión de POSIX iddebe ocurrir por primera vez en su PATH.
jrw32982 es compatible con Monica el
1
@ jrw32982 Para la secuencia de comandos para recoger las utilidades POSIX correctas en Solaris, modificar $PATHen la parte superior de la secuencia de comandos de manera que /usr/xpg4/bines antes /bin. Si usted insiste en el uso no POSIX id, entonces, evidentemente, tendrá que llegar a una solución más portátil.
Kusalananda
1
@Harry Sí, por lo que el guión podría utilizar PATH=$( getconf PATH )o establecer alguna otra ruta predeterminada explícita, o utilizar una ruta explícita para llamar id.
Kusalananda
19

Creo que lo que quiere es más bien para comprobar que dispone de privilegios de superusuario, es decir, que su identificador de usuario efectivo es 0.

zshy bashhaga que esté disponible en la $EUIDvariable, para que pueda hacer:

if ((EUID != 0)); then
  echo >&2 "Error: script not running as root or with sudo! Exiting..."
  exit 1
fi

Con cualquier POSIX como conchas, se puede utilizar el idcomando estándar:

if [ "$(id -u)" -ne 0 ]; then
  echo >&2 "Error: script not running as root or with sudo! Exiting..."
  exit 1
fi

Tenga en cuenta que todos id -uno whoamio la $USERNAMEvariable en zshle dará el primer nombre de usuario para el fluido. En sistemas que tienen otros usuarios con el ID 0, que no puede haber rootincluso si el proceso es un descendiente de uno que ha sido autenticado como root.

$USERque por lo general le dará al usuario que autentica, pero confiando en que es bastante frágil. No se establece por la cáscara, pero por lo general se establece mediante el comando de autenticación (como login, su(en sistemas GNU / Linux, no necesariamente otros), sudo, sshd(el de OpenSSH al menos) ...). No siempre, aunque (cambiar el UID no establecer automagicamente esa variable, que tiene que ser hecho de manera explícita por la aplicación cambiar el UID) y también podría haber sido modificado por algún otro proceso en la ascendencia de la cáscara. $LOGNAME, con la misma advertencia es más confiable como lo especifica POSIX (originalmente de FIPS 151-2)

Stéphane Chazelas
fuente
12

Puede usar $USERo whoamipara verificar el usuario actual.

if [[ "$USER" != "root" ]]; then
    echo "Error: script not running as root or with sudo! Exiting..."
    exit 1
fi

if [[ $(whoami) != "root" ]]; then
    echo "Warning: script must be run as root or with elevated privileges!"
    exit 1
fi

if [[ $(id -u) != "0" ]]; then
    echo "Error: script not running as root or with sudo! Exiting..."
    exit 1
fi
Jesse_b
fuente
1
NOTARIO PÚBLICO. Sugiero leer literalmente sólo directamente a través del manual de bash [ gnu.org/software/bash/manual/bashref.html] . En realidad es un sorprendentemente fácil listo. Para esta respuesta en particular, le sugiero referencias: 3.2.4.2 Conditional Constructs 3.5.4 Command Substitution
Jesse_b
9
El comando id -ucon o sin -nopción es una alternativa al uso de whoami. Sin -n y comparando a cero es una mejor adaptación a la prueba el núcleo está haciendo realidad. Todos los cuidados del núcleo de que es el ID, no el nombre del archivo de contraseñas.
Icarus
66
Creo que usar $(id -u)es mejor. En algunos casos (maliciosos), $USERpodría estar equivocado.
Basile Starynkevitch
1
Para aquellos que estén interesados ​​en el enlace proporcionado por @Jesse_b: hay un error tipográfico. Debe ser gnu.org/software/bash/manual/bashref.html
Kryten
1
Algunos sistemas no usan "root" como el nombre de la cuenta privilegiada que tiene uid 0. QNAP viene a la mente como uno. Por lo que sólo debe comprobar UID 0, y no el nombre de la cuenta raíz.
roaima
10

Lo que realmente quiere es determinar es si usted tiene acceso a hacer estas operaciones. Se considera una mala práctica para comprobar si está o no está arraigado en lugar de eso.

Si el sistema se ha configurado para permitir que un usuario no root para modificar la página de intercambio y caída de caché, ¿por qué no llegar a ese usuario ejecutar la secuencia de comandos?

En su lugar, sólo tiene que probar la operación y salir con un mensaje de ayuda si se produce un error:

if ! ( swapoff -a && swapon -a )
then
  echo "Failed to clear swap (rerun as root?)" >&2
  exit 1
fi

if ! echo 1 > /proc/sys/vm/drop_caches
then 
  echo "Failed to free page cache (rerun as root?)" >&2
  exit 1
fi
ese otro chico
fuente
¿Un usuario no root desactivando el intercambio?
Kusalananda
2
Si. Puede configurar esto con SELinux. Del mismo modo, se puede desactivar un proceso de raíz de hacerlo.
ese otro tipo
1
Es posible que no desee exitdespués de que algo falle, en caso de que el usuario quiera hacer todo lo que pueda con sus privilegios actuales. (Pero para un sistema típico donde todo esto requiere root, salir sería más útil / menos ruidoso.)
Peter Cordes
2
Yo no iría tan lejos como para decir que es "mala práctica" para comprobar si está o no está raíz. En particular, si eso es exactamente lo que quiere saber. Considero que es mejor verificar si tiene permisos suficientes para hacer lo que quiere.
Erik Bennett