Comment vérifier si l'exécution en tant que root dans un script bash

275

J'écris un script qui nécessite des autorisations au niveau racine, et je veux faire en sorte que si le script n'est pas exécuté en tant que root, il fait simplement écho «Veuillez exécuter en tant que root». et sort.

Voici un pseudocode pour ce que je recherche:

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

  else (do stuff)
fi

exit

Comment pourrais-je au mieux (proprement et en toute sécurité) accomplir cela? Merci!

Ah, juste pour clarifier: la partie (faire des trucs) impliquerait d'exécuter des commandes qui en elles-mêmes nécessitent root. Donc, l'exécuter en tant qu'utilisateur normal reviendrait simplement à une erreur. Ceci est juste destiné à exécuter proprement un script qui nécessite des commandes root, sans utiliser sudo dans le script, je cherche juste du sucre syntaxique.

Nathan
la source
8
(1) le rendre non exécutable par quoi que ce soit d'autre puis root (2) organiser également d'autres autorisations .. (3) id -uretourne 0pour root.
Wrikken

Réponses:

404

La variable d'environnement $ EUID contient l'UID de l'utilisateur actuel. L'UID de Root est 0. Utilisez quelque chose comme ceci dans votre script:

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

Remarque: Si vous obtenez 2: [: Illegal number:vérifiez si vous avez #!/bin/shen haut et changez-le en #!/bin/bash.

ptierno
la source
Il semble que de bonnes autorisations et l'avoir constituent une double couche de sécurité
Kolob Canyon
25
Je pense qu'il vaut mieux comparer chaîne avec chaîne, nombre avec nombre. en utilisant des crochets doubles, vous pouvez utiliser> directement sans citation [[$ EUID> 0]]
Sergio Abreu
7
J'ai reçu un 2: [: Illegal number:avertissement jusqu'à ce qu'il soit changé pour la version de Sergio.
alexeydemin
1
@ thekiwi5000 Le point-virgule n'est requis que si le thenest sur la même ligne que la condition ...
ptierno
1
@StephenAngelico Sudo devrait fonctionner. Si vous le testez en faisant $ sudo echo $ EUID; c'est un mauvais test et échouera car $ EUID est développé avant que la commande ne soit passée à sudo. Essayez de mettre echo $ EUID dans un script de test et de l'exécuter avec sudo.
user1169420
79

Dans un script bash, vous avez plusieurs façons de vérifier si l'utilisateur en cours d'exécution est root.

À titre d' avertissement , ne vérifiez pas si un utilisateur est root en utilisant le rootnom d'utilisateur. Rien ne garantit que l'utilisateur avec l'ID 0 est appelé root. C'est une convention très forte qui est largement suivie, mais n'importe qui peut renommer le superutilisateur sous un autre nom.

Je pense que la meilleure façon d'utiliser bash est d'utiliser $EUID, à partir de la page de manuel:

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

C'est un meilleur moyen que celui $UIDqui pourrait être modifié et ne reflète pas l'utilisateur réel exécutant le script.

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

Une façon dont j'aborde ce genre de problème consiste à injecter sudodans mes commandes lorsqu'il n'est pas exécuté en tant que root. Voici un exemple:

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

De cette façon, ma commande est exécutée par root lors de l'utilisation du superutilisateur ou par sudolorsqu'elle est exécutée par un utilisateur normal.

Si votre script doit toujours être exécuté par root, définissez simplement les droits en conséquence ( 0500).

sberder
la source
Si la personne qui essaie d'exécuter le script n'a pas les privilèges sudo, cela provoquera l'erreur et la commande ne s'exécutera pas? Je veux juste m'assurer, je comprends bien.
Caperneoignis du
1
Je ne suis pas sûr que cette réponse soit 100% complètement correcte. Sur RHEL7.2 en utilisant Bash 4.2.46 ... si je suis printf $EUIDavec ou sans sudo, je récupère mon propre UID. Si j'utilise, id -uj'obtiens mon UID et lorsque je l'invoque avec sudo, j'obtiens 0 en retour. Est-ce que j'ai fait quelque chose de mal?
0xSheepdog
4
@ 0xSheepdog, il est possible que sur le cli bash, l'expansion de la variable $ EUID soit d'abord résolue, puis sudo change d'utilisateur. Par conséquent, vous obtiendriez ce comportement, mais dans les scripts, tout fonctionnerait toujours bien.
Alexander Bird
@AlexanderBird Bon point, merci! Je n'ai fait aucun vrai test, je viens de rapporter mon expérience.
0xSheepdog
3
Utilisez un "herestring" pour votre test pour empêcher l'expansion locale du shell de la variable. Comparez sudo bash <<<'echo $EUID'avec bash <<<'echo $EUID'. En savoir plus sur l'hérédité hérédoc-like sur tldp.org/LDP/abs/html/x17837.html
Bruno Bronosky
75

Quelques réponses ont été données, mais il semble que la meilleure méthode à utiliser soit:

  • id -u
  • S'il est exécuté en tant que root, retournera un identifiant de 0.

Cela semble être plus fiable que les autres méthodes, et il semble qu'il renvoie un identifiant de 0 même si le script est exécuté sudo.

Nathan
la source
1
C'est la meilleure réponse
Dan Ortega
59
if [[ $(id -u) -ne 0 ]] ; then echo "Please run as root" ; exit 1 ; fi

ou

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

:)

Dale_Reagan
la source
Vous pourriez envisager d'intégrer la réponse de Jeremy J Starcher à cette partie, au final c'est toujours la même chose ...
reallynice
Je sais que depuis le terminal, lorsque j'oublie de préfixer quelque chose avec, sudoje peux simplement taper sudo !!et cela fait le travail pour moi, plutôt que d'appuyer sur la flèche HAUT, d'aller au début de la ligne et d'ajouter sudo à la main. Je ne sais pas si c'est une chose BASH ou une chose SUDO ou autre, mais cela fonctionne la plupart du temps.
0xSheepdog
@ 0xSheepdog: C'est un truc Bash (et une caractéristique de certains autres shells tels que csh, d'où il est issu IIRC).
pause jusqu'à nouvel ordre.
Dans l'ensemble, je supprimerais la partie barrée dans son ensemble et réécrirais la ligne ok if [ "$(id -u)" -ne 0 ]; then echo 'Please run as root.' >&2; exit 1; fi. À votre santé.
LinuxSecurityFreak
29

Comme @wrikken l'a mentionné dans ses commentaires, id -uc'est une bien meilleure vérification de la racine.

De plus, avec une bonne utilisation de sudo, vous pouvez faire vérifier le script et voir s'il fonctionne en tant que root. Sinon, demandez-lui de se rappeler via sudopuis d'exécuter avec les autorisations root.

Selon ce que fait le script, une autre option peut être de configurer une sudoentrée pour les commandes spécialisées dont le script peut avoir besoin.

Jeremy J Starcher
la source
Existe-t-il un moyen gracieux de rappeler un programme lui-même? Peut-être qu'il y a une variable bash avec le chemin absolu vers le programme?
Nathan
1
Je ne suis pas à proximité d'une invite BASH pour tester, mais $0a le nom du script en cours d'exécution. Il y a quelques exemples ici qui pourraient vous aider.
Jeremy J Starcher
25

Il y a une simple vérification pour qu'un utilisateur soit root.

La [[ stuff ]]syntaxe est la manière standard d'exécuter une vérification dans 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

Cela suppose également que vous souhaitez quitter avec un 1 en cas d'échec. La errorfonction est un flair qui définit le texte de sortie en rouge (pas nécessaire, mais assez chic si vous me le demandez).

Slater Victoroff
la source
Quelle est cette errorcommande? Mon système ne semble pas l'avoir. . .
ruakh
Oh, c'est juste une petite histoire. Cela n'a pas beaucoup d'importance, mais je vais le joindre.
Slater Victoroff
4
C'est plutôt cool! Si je peux suggérer quelques améliorations: (1) déplacer la nouvelle ligne à la fin; (2) écrire sur l'erreur standard plutôt que sur la sortie standard; (3) ne définissez la couleur que si l'erreur standard est un terminal (plutôt que de risquer d'écrire des caractères d'échappement dans des fichiers journaux lessou autre); et (4) définir une couleur d'arrière-plan, de sorte que le texte sera lisible quelle que soit la couleur d'arrière-plan du terminal de l'utilisateur. Donc, quelque chose comme function error () { if [[ -t 2 ]] ; then echo $'\033[31;2;47m'"$@"$'\033[0m' ; else echo "$@" ; fi >&2 ; }. (Tweak comme vous le souhaitez.)
ruakh
3
Cela ne devrait-il pas être "-ne" au lieu de "-eq"?
Carlos Rendon
2
Le code de @CarlosRendon Slater est d' empêcher que quelque chose ne soit exécuté en tant que root. (C'est l'opposé de ce que le PO demandait, mais la méthode de vérification serait la même.)
Joshua Taylor
11

Très simple, il suffit de mettre:

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

L'avantage d'utiliser ceci au lieu de idest que vous pouvez également vérifier si un certain utilisateur non root exécute la commande; par exemple.

if [ "$(whoami)" == "john" ] ; then
    # you are john
else
    # you are not john
fi
Matthew Trotter
la source
si vous testez l'utilisateur avec une chaîne "root", ne permettez-vous pas d'exécuter quelqu'un nommé "root"?
pcarvalho
Vous avez oublié le ';' après l'if
Triskeldeian
1
@peteroak qui d'autre serait nommé root autre que root?
ptierno
3
+1 pour avoir répondu à la question sur whoamiplutôt que d'utiliser id; la whoamicommande peut également être utilisée pour rechercher d' autres utilisateurs que root, par leur nom.
Jez
10

0- Lisez la documentation officielle GNU Linux, il y a plusieurs façons de le faire correctement.

1- assurez-vous de mettre la signature shell pour éviter les erreurs d'interprétation:

 #!/bin/bash

2- c'est mon script

#!/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
la source
10

Dans cette réponse, soyons clairs, je suppose que le lecteur est capable de lire bashet de scripts shell POSIX comme dash.

Je pense qu'il n'y a pas grand-chose à expliquer ici, car les réponses très votées expliquent bien la plupart de ces questions.

Pourtant, s'il y a quelque chose à expliquer, n'hésitez pas à commenter, je ferai de mon mieux pour combler les lacunes.


bashSolution complète (et pas seulement ) optimisée pour les performances et la fiabilité; tous les coques compatibles

Nouvelle solution:

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

Benchmark (enregistrer dans un fichier 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

Solution originale:

#!/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

^^^ La solution supprimée s'est avérée ne pas accélérer les choses, mais elle existe depuis longtemps, donc je vais la garder ici aussi longtemps que je le jugerai nécessaire.


Explication

Comme il est plusieurs fois plus rapide de lire la variable $EUIDstandard bash, le numéro d'ID utilisateur effectif, que d'exécuter une id -ucommande pour POSIX- trouver l'ID utilisateur, cette solution combine les deux en une fonction bien emballée. Si, et seulement si, $EUIDpour une raison quelconque n'est pas disponible, la id -ucommande sera exécutée, garantissant que nous obtenons la valeur de retour appropriée quelles que soient les circonstances .


Pourquoi je poste cette solution après tant d'années que le PO a demandé

Eh bien, si je vois bien, il semble y avoir un morceau de code manquant ci-dessus.

Vous voyez, il existe de nombreuses variables qui doivent être prises en compte, et l'une d'entre elles combine performances et fiabilité .


Solution POSIX portable + Exemple d'utilisation de la fonction ci-dessus

#!/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

Conclusion

Autant que vous ne l'aimez peut-être pas, l'environnement Unix / Linux s'est beaucoup diversifié. Cela signifie qu'il y a des gens qui aiment bashtant, ils ne pensent même pas à la portabilité ( coquilles POSIX ). D'autres comme moi préfèrent les coques POSIX . C'est aujourd'hui une question de choix et de besoins personnels.

LinuxSecurityFreak
la source
6

Si le script nécessite vraiment un accès root, ses autorisations sur les fichiers doivent refléter cela. Avoir un script racine exécutable par des utilisateurs non root serait un drapeau rouge. Je vous encourage à ne pas contrôler l'accès avec un ifchèque.

chown root:root script.sh
chmod u=rwx,go=r script.sh
John Kugelman
la source
4
Si quelqu'un a ses autorisations pour que cela fonctionne très bien, mais j'ai l'impression que la surutilisation de la 777bombe rend cette vérification un peu défectueuse pour le type d'utilisateurs qui commettraient l'erreur en premier lieu.
Slater Victoroff
7
Cela suppose que l'utilisateur exécute un script exécutable. Si l'utilisateur appelle juste, bash /path/to/scriptil peut toujours être exécuté mêmeo=r
ptierno
5

Une façon simple de rendre le script exécutable uniquement par root est de démarrer le script avec la ligne:

#!/bin/su root

alexandre1985
la source
1
Je suis curieux de savoir pourquoi cette réponse n'est pas votée plus haut? Cela semble être le plus simple et le plus propre. Y a-t-il des inconvénients ici?
Bassinator
@Bassinator Je crois que certaines personnes disent qu'il ne fonctionnera pas sur certains nix mais il a fonctionné parfaitement sur mon Linux jusqu'à présent. Essayez! Peut-être que cette réponse est arrivée tard dans la course, mais j'essaie d'ajouter des connaissances simples à la communauté (au lieu de donner des réponses similaires, comme la plupart sur ce fil: /) Votez cela si vous avez la chance de lire ceci et cela fonctionne sur votre machine
alexandre1985
@TamusJRoyce Si l'objectif est de vérifier si vous exécutez en tant que root et de ne pas forcer le script à s'exécuter uniquement en tant que root, pourquoi est-ce que dans chaque réponse, après la vérification si s'exécute en tant que root, ils font le script exit? Et ces réponses sont toujours en hausse? Je suppose que les gens ne veulent pas implicitement que le script soit exécuté en tant que root. Je suis donc suivre cette façon de penser, avec une réponse plus simple. Mais oui, vous pouvez également apprendre des réponses plus verbeuses ci
alexandre1985
@ alexandre1985 Exactement. Scénario: Si vous exécutez en tant que root, vous souhaitez peut-être qu'un script par défaut installe le programme globalement lorsqu'il vous demande comment vous souhaitez qu'il soit installé. Sinon, la valeur par défaut est définie pour l'installer localement. Au lieu d'appuyer sur Entrée, l'utilisateur peut choisir de l'installer global ou local. Mais s'ils aiment la valeur par défaut, ils peuvent appuyer sur Entrée. Et ils ne seront pas invités avec un mot de passe. Votre shebang ne "vérifiera" jamais si vous êtes root (par titre). Mais je pense toujours que cette réponse est utile.
TamusJRoyce
@TamusJRoyce donne tout son sens à votre commentaire. En effet est une préoccupation et cette solution n'est pas pour ce cas d'utilisation. Vous avez ouvert mes perspectives. Vous avez raison. Merci
alexandre1985
4

essayez le code suivant:

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

OU

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

Pour autant que je sache, la manière correcte de le vérifier est:

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

Voir la section "Test de la racine" ici:

http://linuxcommand.org/lc3_wss0080.php

WebBrother
la source
1
remplacer = "0"par-eq 0
LinuxSecurityFreak
1
@LinuxSecurityFreak, je le remplacerai si vous expliquez pourquoi je dois le faire.
WebBrother
2

id -uest bien meilleur que whoami, car certains systèmes comme android peuvent ne pas fournir la racine du mot.

Exemple:

# whoami
whoami
whoami: unknown uid 0
Smeterlink
la source
1

Vérifiez si vous êtes root et quittez si vous ne l'êtes pas:

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

Ou dans cet exemple, essayez de créer un répertoire à l'emplacement racine, puis essayez une fois les droits élevés.

Vérifiez si vous êtes root et si ce n'est pas élevé si possible:

# 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
la source
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

Note de l'éditeur: si vous n'avez pas besoin de crochets doubles, utilisez des crochets simples pour la portabilité du code.

Pramod Kharade
la source
3
Vous n'avez pas expliqué pourquoi vous avez fourni une réponse alternative à une question de 5 ans qui a déjà plusieurs réponses.
Styphon
-1

Vérifiez la racine:

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

Testé et exécuté en root.

fvillalba89
la source