Jak sprawdzić, czy działa jako root w skrypcie bash

Piszę skrypt, który wymaga uprawnień na poziomie roota i chcę, aby był tak, że jeśli skrypt nie jest uruchamiany jako root, po prostu wyświetla Echo " proszę Uruchom jako root."i wyjścia.

Oto jakiś pseudokod do tego czego szukam:

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

  else (do stuff)
fi

exit

Jak mógłbym najlepiej (czysto i bezpiecznie) to osiągnąć? Dzięki!

Tak dla jasności: część (do stuff) wymagałaby uruchamiania poleceń, które same w sobie wymagają roota. Więc uruchamianie go jako normalnego użytkownika po prostu wyskoczyłby błąd. Jest to po prostu przeznaczone do czystego uruchomienia skryptu, który wymaga poleceń roota, bez używania sudo wewnątrz skryptu, Szukam tylko trochę cukru składniowego.
Author: LinuxSecurityFreak, 2013-08-13

18 answers

Zmienna środowiskowa $EUID przechowuje UID bieżącego użytkownika. UID roota wynosi 0. Użyj czegoś takiego w swoim skrypcie:

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

Uwaga: Jeśli otrzymasz 2: [: Illegal number: Sprawdź, czy masz #!/bin/sh na górze i zmień ją na #!/bin/bash.

 460
Author: ptierno,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-19 16:29:38

Udzielono kilku odpowiedzi, ale wydaje się, że najlepszą metodą jest użycie:

  • id -u
  • jeśli zostanie uruchomiony jako root, zwróci id równe 0.

Ta metoda wydaje się bardziej niezawodna niż inne metody i wydaje się, że zwraca identyfikator 0, nawet jeśli skrypt jest uruchamiany przez sudo.

 94
Author: Nathan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-27 23:29:34

W skrypcie bash, masz kilka sposobów, aby sprawdzić, czy uruchomiony użytkownik jest root.

Jako ostrzeżenie , nie sprawdzaj, czy użytkownik jest rootem, używając nazwy użytkownika root. Nic nie gwarantuje, że użytkownik o ID 0 zostanie wywołany root. Jest to bardzo silna konwencja, która jest szeroko przestrzegana, ale każdy może zmienić nazwę superużytkownika na inną.

Myślę, że najlepszym sposobem podczas używania bash jest użycie $EUID, ze strony man:

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

To lepszy sposób niż $UID które można zmienić i nie odzwierciedlać rzeczywistego użytkownika uruchamiającego skrypt.

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

Sposobem, w jaki podchodzę do tego rodzaju problemu, jest wstrzykiwanie sudo do moich poleceń, gdy nie są uruchamiane jako root. Oto przykład:

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

W ten sposób moje polecenie jest uruchamiane przez roota podczas korzystania z superużytkownika lub przez sudo gdy jest uruchamiane przez zwykłego użytkownika.

Jeśli twój skrypt ma być zawsze uruchamiany przez roota, po prostu ustaw odpowiednie prawa (0500).

 86
Author: sberder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-07 22:31:34
if [[ $(id -u) -ne 0 ]] ; then echo "Please run as root" ; exit 1 ; fi

Lub

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

:)

 66
Author: Dale_Reagan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-15 18:03:39

Istnieje proste sprawdzenie, czy użytkownik jest root.

Składnia [[ stuff ]] jest standardowym sposobem uruchamiania sprawdzania w 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

To również zakłada, że chcesz wyjść z 1, jeśli się nie uda. Funkcja error to jakiś styl, który ustawia tekst wyjściowy na czerwony(nie jest potrzebny, ale całkiem elegancki, jeśli O mnie chodzi).

 31
Author: Slater Victoroff,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-03-24 10:48:59

Jak wspomniał @wrikken w swoich komentarzach, id -u jest znacznie lepszym sprawdzeniem dla roota.

Dodatkowo, przy odpowiednim użyciu sudo, możesz sprawdzić skrypt i sprawdzić, czy działa jako root. Jeśli nie, niech sobie przypomni poprzez sudo, a następnie uruchomi z uprawnieniami roota.

W zależności od tego, co robi skrypt, inną opcją może być ustawienie wpisu sudo dla dowolnych specjalistycznych poleceń, których skrypt może potrzebować.

 30
Author: Jeremy J Starcher,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-13 18:07:03

W tej odpowiedzi, niech będzie jasne, zakładam, że czytelnik jest w stanie przeczytać bash oraz POSIX skrypty powłoki Jak dash.

Uważam, że nie ma tu zbyt wiele do wyjaśnienia, ponieważ wysoko głosowane odpowiedzi dobrze wyjaśniają wiele z nich.

Jeśli jednak jest coś do wyjaśnienia, nie wahaj się skomentować, postaram się wypełnić luki.


Zoptymalizowane wszechstronne rozwiązanie pod kątem wydajności i niezawodności; wszystkie powłoki compatible

Nowe rozwiązanie:

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

Benchmark (Zapisz do pliku is_user_root__benchmark)

#+------------------------------------------------------------------------------+
#|                           is_user_root() benchmark                           |
#|                  "Bash is fast while Dash is slow in this"                   |
#|                          Language: POSIX shell script                        |
#|                        Copyright: 2020 Vlastimil Burian                      |
#|                      M@il: info[..]vlastimilburian[..]cz                     |
#|                               License: GPL 3.0                               |
#|                                 Version: 1.1                                 |
#+------------------------------------------------------------------------------+

readonly iterations=10000

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

# bash is_user_root__benchmark
# dash is_user_root__benchmark

is_user_root () { [ ${EUID:-$(id -u)} -eq 0 ]; }

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

printf '%s\n' '___is_user_root()___'; print_start
                   
i=1; while [ $i -lt $iterations ]; do
    is_user_root
    i=$((i + 1))
done; print_finish

Przykłady użycia i czasu trwania:

$ dash is_user_root__benchmark 
___is_user_root()___
Start  : 03:14:04.81
Finish : 03:14:13.29

$ bash is_user_root__benchmark 
___is_user_root()___
Start  : 03:16:22.90
Finish : 03:16:23.08


Wyjaśnienie

Ponieważ jest wiele razy szybciej czytać $EUID standard bash zmienna, efektywny numer ID użytkownika, niż wykonanie id -u polecenia POSIX - ly znaleźć identyfikator użytkownika, To rozwiązanie łączy oba w ładnie spakowaną funkcję. Wtedy i tylko wtedy, gdy $EUID jest dla dowolnego powód niedostępny, polecenie id -u zostanie wykonane, upewniając się, że otrzymamy właściwą wartość zwracaną bez względu na okoliczności .


Dlaczego zamieszczam To rozwiązanie po tylu latach OP zapytał

Cóż, jeśli dobrze widzę, to wydaje się, że jest brakujący fragment kodu powyżej.

Widzisz, istnieje wiele zmiennych , które należy wziąć pod uwagę, a jedną z nich jest łączenie wydajności i niezawodność .


Portable POSIX rozwiązanie + przykład użycia powyższej funkcji

#!/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 # implicit, here it serves the purpose to be explicit for the reader
else
    echo 'You are just an ordinary user.' >&2
    exit 1
fi

Podsumowanie

Chociaż prawdopodobnie nie podoba Ci się to, środowisko Unix / Linux bardzo się urozmaiciło. Czyli są ludzie, którzy lubią bash tak bardzo, że nawet nie myślą o przenośności (POSIX powłoki). Inni tacy jak ja wolą POSIX powłoki. Jest to obecnie kwestia osobistego wyboru i potrzeb.

 18
Author: LinuxSecurityFreak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-08-05 01:21:10

Bardzo prosty sposób wystarczy umieścić:

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

Korzyść z używania tego zamiast id polega na tym, że możesz sprawdzić, czy dany użytkownik nie-root również uruchamia polecenie; np.

if [ "$(whoami)" == "john" ] ; then
    # you are john
else
    # you are not john
fi
 11
Author: Matthew Trotter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-22 10:27:07

0-przeczytaj oficjalną dokumentację GNU Linux, jest wiele sposobów, aby zrobić to poprawnie.

1 - Upewnij się, że umieściłeś podpis powłoki, aby uniknąć błędów w interpretacji:

 #!/bin/bash

2 - to jest mój skrypt

#!/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
Author: Sergio Abreu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-03 02:26:31

Jeśli skrypt naprawdę wymaga dostępu roota, jego uprawnienia do plików powinny to odzwierciedlać. Posiadanie skryptu głównego wykonywalnego przez użytkowników innych niż root byłoby czerwoną flagą. Zachęcam do nie kontrolowania dostępu za pomocą czeku if.

chown root:root script.sh
chmod u=rwx,go=r script.sh
 6
Author: John Kugelman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-13 18:06:57

Spróbuj użyć następującego kodu:

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

Lub

if [ `id -u` != "0" ]; then
    echo "Sorry, you are not root."
    exit 1
fi
 5
Author: MLSC,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-03 06:24:07

Jednym z prostych sposobów, aby skrypt mógł być uruchamiany tylko przez roota, jest uruchomienie skryptu z linii:

#!/bin/su root

 5
Author: alexandre1985,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-05-19 22:42:11

Z tego co wiem poprawnym sposobem sprawdzenia jest:

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

Zobacz sekcję "testowanie dla roota" tutaj:

Http://linuxcommand.org/lc3_wss0080.php

 3
Author: WebBrother,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-09 12:07:18

id -u jest znacznie lepszy niż whoami, ponieważ niektóre systemy, takie jak android, mogą nie dostarczać słowa root.

Przykład:

# whoami
whoami
whoami: unknown uid 0
 2
Author: Smeterlink,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-26 17:42:39

Sprawdź, czy jesteś rootem i zamknij, jeśli nie:

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

Lub w tym przykładzie spróbuj utworzyć katalog w lokalizacji root, a następnie spróbuj po zwiększeniu praw.

Sprawdź, czy jesteś root, a jeśli nie podnieś, jeśli to możliwe:

# 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)
 1
Author: Mike Q,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-10-15 20:03:09

Problem z użyciem: id-u, $EUID i whoami polega na tym, że wszystkie z nich dają fałszywy wynik pozytywny, gdy podrabiam korzeń, na przykład:

$ fakeroot

Id:

$ id -u
0

EUID:

$ echo $EUID
0

Whoami:

$ whoami
root

Niezawodnym i hakerskim sposobem jest sprawdzenie, czy użytkownik ma dostęp do katalogu / root:

 $ ls /root/ &>/dev/null && is_root=true || is_root=false; echo $is_root
 1
Author: Sr. Libre,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-12-18 13:53:51
#!/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

Uwaga edytora: jeśli nie potrzebujesz podwójnych nawiasów, użyj pojedynczych do przenoszenia kodu.

 0
Author: Pramod Kharade,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-01 20:43:31

Sprawdź root:

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

Testowane i uruchamiane w roocie.

 -1
Author: fvillalba89,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-06 16:11:39