Come verificare se eseguito come root in uno script bash


275

Sto scrivendo uno script che richiede autorizzazioni a livello di root e voglio farlo in modo tale che se lo script non viene eseguito come root, fa semplicemente eco "Esegui come root". ed esce.

Ecco alcuni pseudocodici per quello che sto cercando:

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

  else (do stuff)
fi

exit

Come potrei farlo meglio (in modo pulito e sicuro)? Grazie!

Ah, solo per chiarire: la parte (fare cose) implicherebbe l'esecuzione di comandi che di per sé richiedono il root. Quindi eseguirlo come un normale utente provocherebbe solo un errore. Questo ha lo scopo di eseguire in modo pulito uno script che richiede comandi di root, senza usare sudo all'interno dello script, sto solo cercando un po 'di zucchero sintattico.


8
(1) renderlo non eseguibile da nient'altro che root (2) disponga anche ulteriori permessi. (3) id -urestituisce 0per root.
Wrikken,

Risposte:


404

La variabile di ambiente $ EUID contiene l'UID dell'utente corrente. L'UID di Root è 0. Usa qualcosa di simile nel tuo script:

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

Nota: se si ottiene 2: [: Illegal number:verificare se si dispone #!/bin/shnella parte superiore e cambiarlo in #!/bin/bash.


Sembra che avere buoni permessi e avere questo sia un doppio livello di sicurezza
Kolob Canyon,

25
Penso che sia meglio confrontare la stringa con la stringa, il numero con il numero. utilizzando le parentesi doppie, è possibile utilizzare> direttamente senza virgolette [[$ EUID> 0]]
Sergio Abreu,

7
Ho ricevuto un 2: [: Illegal number:avviso fino a quando non ho cambiato la versione di Sergio.
alexeydemin,

1
@ thekiwi5000 Il punto e virgola è richiesto solo se si thentrova sulla stessa riga della condizione ...
ptierno

1
@StephenAngelico Sudo dovrebbe funzionare. Se lo stai testando facendo $ sudo echo $ EUID; è un test negativo e fallirà perché $ EUID viene espanso prima che il comando venga passato a sudo. Prova a inserire echo $ EUID in uno script di test ed eseguilo con sudo.
user1169420

79

In uno script bash, hai diversi modi per verificare se l'utente in esecuzione è root.

Come avvertimento , non verificare se un utente è root utilizzando il rootnome utente. Nulla garantisce che venga chiamato l'utente con ID 0 root. È una convenzione molto forte che viene ampiamente seguita ma chiunque potrebbe rinominare il superutente con un altro nome.

Penso che il modo migliore quando si usa bash sia usare $EUID, dalla pagina man:

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

Questo è un modo migliore rispetto al $UIDquale potrebbe essere modificato e non riflettere l'utente reale che esegue lo script.

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

Un modo per affrontare questo tipo di problema è iniettando i sudomiei comandi quando non eseguito come root. Ecco un esempio:

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

In questo modo il mio comando viene eseguito da root quando si utilizza il superutente o sudoquando viene eseguito da un utente normale.

Se il tuo script deve essere sempre eseguito da root, imposta semplicemente i diritti di conseguenza ( 0500).


Se la persona che sta tentando di eseguire lo script non dispone dei privilegi di sudo, ciò causerà la generazione dell'errore e il comando non verrà eseguito? Voglio solo essere sicuro, ho capito bene.
Caperneoignis,

1
Non sono sicuro che questa risposta sia completamente corretta al 100%. Su RHEL7.2 usando Bash 4.2.46 ... se printf $EUIDcon o senza sudo, ottengo il mio UID indietro. Se uso id -uottengo il mio UID e quando lo invoco con sudo ottengo 0 indietro. Ho fatto qualcosa di male?
0xSheepdog,

4
@ 0xSheepdog, è possibile che sul bash cli, l'espansione della variabile $ EUID venga risolta per prima, quindi sudo cambia l'utente. Pertanto otterresti quel comportamento, ma negli script tutto funzionerebbe comunque bene.
Alexander Bird,

@AlexanderBird Ottimo punto, grazie! Non ho fatto alcun test reale, ho solo riportato la mia esperienza.
0xSheepdog

3
Utilizzare un "herestring" per il test per impedire l'espansione della shell locale della variabile. Confronta sudo bash <<<'echo $EUID'con bash <<<'echo $EUID'. Maggiori informazioni sull'erede simile a una eredità su tldp.org/LDP/abs/html/x17837.html
Bruno Bronosky,

75

Sono state fornite alcune risposte, ma sembra che il metodo migliore da usare sia:

  • id -u
  • Se eseguito come root, restituirà un ID di 0.

Questo sembra essere più affidabile rispetto agli altri metodi e sembra che restituisca un ID pari a 0 anche se lo script viene eseguito sudo.


1
Grande questa è la risposta migliore
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

:)


Potresti considerare di integrare la risposta di Jeremy J Starcher con questa parte, alla fine è sempre la stessa roba ...
davvero,

So che dal terminale, quando dimentico di aggiungere un prefisso, sudoposso semplicemente digitare sudo !!e fa il lavoro per me, piuttosto che premere la freccia SU, andare all'inizio della riga e aggiungere sudo manualmente. Non sono sicuro che sia una cosa BASH o una cosa SUDO o altro, ma funziona quasi sempre.
0xSheepdog,

@ 0xSheepdog: è una cosa Bash (e una caratteristica di alcune altre shell come csh, da dove ha avuto origine IIRC).
In pausa fino a nuovo avviso.

Tutto sommato, rimuoverei la parte reticolata nel suo insieme e riscriverei la riga ok in if [ "$(id -u)" -ne 0 ]; then echo 'Please run as root.' >&2; exit 1; fi. Saluti.
LinuxSecurityFreak

29

Come @wrikken ha menzionato nei suoi commenti, id -uè un controllo molto migliore per root.

Inoltre, con un uso corretto di sudo, potresti avere lo script check e vedere se è in esecuzione come root. In caso contrario, richiamalo tramite sudoe quindi esegui con i permessi di root.

A seconda di ciò che fa lo script, un'altra opzione potrebbe essere quella di impostare una sudovoce per qualsiasi comando specializzato di cui lo script potrebbe aver bisogno.


Esiste un modo grazioso per richiamare un programma da solo? Forse c'è qualche variabile bash con il percorso assoluto per il programma?
Nathan,

1
Non sono vicino a un prompt BASH in questo momento per testare, ma $0ha il nome dello script in esecuzione. Ci sono alcuni esempi qui che potrebbero aiutarvi.
Jeremy J Starcher,

25

C'è un semplice controllo per un utente che è root.

La [[ stuff ]]sintassi è il modo standard di eseguire 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

Ciò presuppone anche che si desidera uscire con un 1 se si fallisce. La errorfunzione è un po 'di stile che imposta il testo in uscita su rosso (non necessario, ma piuttosto elegante se me lo chiedi).


Cos'è quel errorcomando? Il mio sistema non sembra averlo. . .
Ruakh,

Oh, è solo una piccola cosa di talento. Non importa molto, ma lo allego.
Slater Victoroff

4
È abbastanza bello! Se posso suggerire alcuni miglioramenti: (1) spostare la nuova riga alla fine; (2) scrivere sull'errore standard anziché sull'output standard; (3) impostare il colore solo se l'errore standard è un terminale (piuttosto che rischiare di scrivere caratteri di escape in file di registro lesso quant'altro); e (4) impostare un colore di sfondo, quindi il testo sarà leggibile indipendentemente dal colore di sfondo del terminale dell'utente. Quindi qualcosa del genere function error () { if [[ -t 2 ]] ; then echo $'\033[31;2;47m'"$@"$'\033[0m' ; else echo "$@" ; fi >&2 ; }. (Modifica a piacimento.)
Ruakh

3
Non dovrebbe essere "-ne" anziché "-eq"?
Carlos Rendon,

2
Il codice di @CarlosRendon Slater è impedire che qualcosa venga eseguito come root. (Questo è opposto a quello che l'OP stava chiedendo, ma il metodo di controllo sarebbe lo stesso.)
Joshua Taylor,

11

Modo molto semplice in poche parole:

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

Il vantaggio di usare questo invece di idè che puoi controllare se anche un certo utente non root sta eseguendo il comando; per esempio.

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

se testerai l'utente con una stringa "root", non ti permetti di eseguire qualcuno che si chiama "root"?
pcarvalho,

Hai dimenticato il ';' dopo l'if
Triskeldeian il

1
@peteroak chi altro sarebbe chiamato root diverso da root?
ptierno,

3
+1 per aver effettivamente risposto alla domanda whoamipiuttosto che usare id; il whoamicomando può anche essere usato per controllare altri utenti oltre a root, per nome.
Jez,

10

0- Leggi la documentazione ufficiale di GNU Linux, ci sono molti modi per farlo correttamente.

1- assicurati di mettere la firma della shell per evitare errori di interpretazione:

 #!/bin/bash

2- questa è la mia sceneggiatura

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

10

In questa risposta, sia chiaro, presumo che il lettore sia in grado di leggere bashe scrivere script shell POSIX come dash.

Credo che non ci sia molto da spiegare qui, dato che le risposte molto votate fanno un buon lavoro nel spiegarne gran parte.

Tuttavia, se c'è qualcosa da spiegare ulteriormente, non esitate a commentare, farò del mio meglio per colmare le lacune.


bashSoluzione a tutto tondo ottimizzata (non solo ) per prestazioni e affidabilità; compatibile con tutte le shell

Nuova soluzione:

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

Benchmark (salva su file 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: info@vlastimilburian.cz                      ##
##                             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

Soluzione 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

^^^ È stato dimostrato che la soluzione eliminata non accelera le cose, ma esiste da molto tempo, quindi la terrò qui per tutto il tempo che riterrò necessario.


Spiegazione

Poiché è molto più veloce leggere la variabile $EUIDstandard bash, il numero ID utente effettivo, rispetto all'esecuzione del id -ucomando POSIX per trovare facilmente l'ID utente, questa soluzione combina entrambe in una funzione ben confezionata. Se, e solo se, $EUIDnon è disponibile per qualsiasi motivo, il id -ucomando verrà eseguito, assicurandoci di ottenere il valore di ritorno corretto, indipendentemente dalle circostanze .


Perché inserisco questa soluzione dopo così tanti anni che l'OP ha chiesto

Bene, se vedo correttamente, sembra che ci sia un pezzo di codice mancante sopra.

Vedete, ci sono molte variabili che devono essere prese in considerazione e una di queste sta combinando prestazioni e affidabilità .


Soluzione POSIX portatile + Esempio di utilizzo della funzione sopra

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

Conclusione

Per quanto possibilmente non ti piaccia, l'ambiente Unix / Linux si è diversificato molto. Significa che ci sono persone a cui piace bashcosì tanto che non pensano nemmeno alla portabilità ( shell POSIX ). Altri come me preferiscono le shell POSIX . Oggi è una questione di scelta e necessità personali.


6

Se lo script richiede davvero l'accesso come root, le sue autorizzazioni per i file dovrebbero rispecchiarlo. Avere uno script root eseguibile da utenti non root sarebbe una bandiera rossa. Ti incoraggio a non controllare l'accesso con un ifassegno.

chown root:root script.sh
chmod u=rwx,go=r script.sh

4
Se qualcuno ha i suoi permessi per 777farlo funzionare alla grande, ma mi sento come se l'abuso della bomba rendesse questo controllo un po 'difettoso per il tipo di utenti che avrebbero commesso l'errore in primo luogo.
Slater Victoroff

7
Ciò presuppone che l'utente stia eseguendo uno script eseguibile. Se l'utente chiama bash /path/to/script, può comunque essere eseguito anche seo=r
ptierno

5

Un modo semplice per rendere lo script eseguibile solo da root è quello di avviare lo script con la riga:

#!/bin/su root


1
Sono curioso di sapere perché questa risposta non è stata votata più in alto? Sembra il più semplice e pulito. Ci sono degli svantaggi qui?
Bassista il

@Bassinator Credo che alcune persone affermino che non funzionerà su alcuni nix ma finora ha funzionato perfettamente sul mio Linux. Provalo! Forse questa risposta è arrivata in ritardo alla gara, ma sto cercando di aggiungere una conoscenza che è semplice per la comunità (invece di dare risposte simili, come la maggior parte su questa discussione: /) Vota questo se sei fortunato a leggere questo e funziona sulla tua macchina
alexandre1985,

@TamusJRoyce Se l'obiettivo è verificare se si sta eseguendo come root e non forzare l'esecuzione dello script solo come root, perché in ogni risposta, dopo il controllo se è in esecuzione come root, creano lo script exit? E ancora quelle risposte sono state votate? Immagino che le persone implicitamente non vogliano eseguire lo script come root. Quindi sto seguendo quel modo di pensare, con una risposta più semplice. Ma sì, puoi anche imparare dalle risposte più dettagliate sopra
alexandre1985,

@ alexandre1985 Esatto. Scenario: se eseguito come root, forse si desidera che uno script esegua per impostazione predefinita l'installazione globale del programma quando viene richiesto come si desidera installarlo. Altrimenti, il valore predefinito è impostato per installarlo localmente. Invece di premere invio, l'utente può scegliere di installarlo a livello globale o locale. Ma se a loro piace il default, possono premere invio. E non verrà richiesta una password. Il tuo shebang non "controllerà" mai se sei root (per titolo). Ma penso ancora che questa risposta sia utile.
TamusJRoyce,

@TamusJRoyce ha perfettamente senso il tuo commento. In effetti è una preoccupazione e questa soluzione non è per quel caso d'uso. Hai aperto le mie prospettive. Hai ragione. Grazie
alexandre1985,

4

prova il seguente codice:

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


2

id -uè molto meglio di whoami, poiché alcuni sistemi come Android potrebbero non fornire la parola root.

Esempio:

# whoami
whoami
whoami: unknown uid 0

1

Controlla se sei root e esci se non lo sei:

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

O in questo esempio, prova a creare una directory nella posizione principale, quindi prova dopo che i diritti sono stati elevati.

Controlla se sei root e se non elevato se possibile:

# 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)

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 redattore: se non hai bisogno di doppie parentesi, usa quelle singole per la portabilità del codice.


3
Non hai spiegato perché hai fornito una risposta alternativa a una domanda di 5 anni che ha già diverse risposte.
Styphon,

-1

Controlla la radice:

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

Testato e funzionante in root.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.