Jak zatrzymać uruchamianie skryptu, jeśli nie jest on rootem (i echo „Nie działa jako root! Wychodzenie z…”)

17

Oto moje źródło:

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

Czyści pamięć podręczną i inne rzeczy, i przypomina, że ​​musi być uruchomiony jako root w terminalu. Zasadniczo chcę, aby skrypt przestał działać, jeśli wykryje, że nie jest wykonywany jako root.

Przykład:

"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..."

Jeśli działa z podwyższonymi uprawnieniami, działa po prostu normalnie. Jakieś pomysły? Dzięki!

M. Knepper
źródło
2
@muru, z tym wyjątkiem, że inne pytanie jest przeciwne: błąd skryptu, jeśli działa jako root.
Stéphane Chazelas
3
@ StéphaneChazelas ah, my bad. Cofnięty
muru
Alternatywą jest ograniczenie ilości pracy wykonanej rootprzez prefiksowanie prefiksu wszystkich poleceń, które muszą być uruchomione tak jak rootz sudo.
reinierpost

Odpowiedzi:

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

Użytkownik root ma identyfikator UID 0 (niezależnie od nazwy konta „root”). Jeśli efektywny identyfikator UID zwracany przez id -unie jest równy zero, użytkownik nie wykonuje skryptu z uprawnieniami administratora. Służy id -rudo testowania rzeczywistego identyfikatora (UID użytkownika wywołującego skrypt).

Nie używaj $EUIDw skrypcie, ponieważ może zostać zmodyfikowany przez nieuprzywilejowanego użytkownika:

$ bash -c 'echo $EUID'
1000

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

Jeśli użytkownik to zrobi, nie spowoduje to oczywiście eskalacji uprawnień, ale może spowodować, że polecenia w skrypcie nie będą mogły wykonać tego, co powinny, a pliki zostaną utworzone z niewłaściwym właścicielem itp.

Kusalananda
źródło
1
Uwaga: w /bin/id -u/bin/id: illegal option -- u Usage: id [-ap] [user]
systemie
1
@ jrw32982 Powinieneś mieć /usr/xpg4/binwcześnie, $PATHaby uzyskać dostęp do narzędzi POSIX w systemie Solaris.
Kusalananda
1
Chodzi o to, że -uopcja idnie jest uniwersalna, a zatem to rozwiązanie jest uniwersalne tylko z zastrzeżeniem, że wersja POSIX idmusi najpierw wystąpić w ŚCIEŻCE.
jrw32982 obsługuje Monikę
1
@ jrw32982 Aby skrypt mógł pobrać odpowiednie narzędzia POSIX w systemie Solaris, zmodyfikuj go $PATHu góry skryptu, tak jak /usr/xpg4/binpoprzednio /bin. Jeśli nalegasz na używanie innych niż POSIX id, oczywiście będziesz musiał wymyślić bardziej przenośne rozwiązanie.
Kusalananda
1
@Harry Tak, aby skrypt mógł użyć PATH=$( getconf PATH )lub ustawić inną jawną domyślną ścieżkę lub użyć jawnej ścieżki do wywoływania id.
Kusalananda
19

Myślę, że chcesz raczej sprawdzić, czy masz uprawnienia superużytkownika, czyli że Twój efektywny identyfikator użytkownika to 0.

zshi bashudostępnij to w $EUIDzmiennej, abyś mógł:

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

Z dowolnymi powłokami podobnymi do POSIX, możesz użyć idstandardowego polecenia:

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

Zauważ, że wszystkie id -unlub whoamilub $USERNAMEzmienną zshbędzie Ci pierwszą nazwę użytkownika uid. W systemach, które mają innych użytkowników o identyfikatorze 0, może to nie być rootnawet jeśli proces jest potomkiem tego, który został uwierzytelniony jako root.

$USERbędzie zazwyczaj daje użytkownikowi, że uwierzytelnione, ale opierając się na nim jest dość kruche. Nie jest ustawiane przez powłokę, ale zwykle jest ustawiane przez polecenie uwierzytelniające (jak login, su(w systemach GNU / Linux, niekoniecznie inne) sudo, sshd((przynajmniej od openssh) ...). Nie zawsze jednak (zmiana identyfikatora użytkownika nie ustawia automatycznie tej zmiennej, musi to zostać wyraźnie wykonane przez aplikację zmieniającą identyfikator użytkownika), a także mogła zostać zmodyfikowana przez jakiś inny proces z przodków powłoki. $LOGNAME, z tym samym zastrzeżeniem jest bardziej niezawodne, ponieważ jest określone przez POSIX (pierwotnie z FIPS 151-2)

Stéphane Chazelas
źródło
12

Możesz użyć $USERlub, whoamiaby sprawdzić bieżącego użytkownika.

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
źródło
1
NP. Sugeruję dosłownie po prostu przeczytać bezpośrednio instrukcję obsługi bash [ gnu.org/software/bash/manual/bashref.html] . To jest naprawdę zaskakująco łatwe. W szczególności dla tej odpowiedzi sugeruję odniesienie: 3.2.4.2 Conditional Constructs 3.5.4 Command Substitution
Jesse_b
9
Polecenie id -uz -nopcją lub bez jest alternatywą dla korzystania z whoami. Bez -n i porównywanie do zera jest lepszym dopasowaniem do testu, który faktycznie wykonuje jądro. Jedyne, na czym zależy jądro, to identyfikator, a nie nazwa z pliku haseł.
icarus
6
Uważam, że używanie $(id -u)jest lepsze. W niektórych (złośliwych) przypadkach $USERmoże być źle.
Basile Starynkevitch,
1
Dla tych, którzy są zainteresowani linkiem dostarczonym przez @Jesse_b: jest literówka. Powinien to być gnu.org/software/bash/manual/bashref.html
Kryten
1
Niektóre systemy nie używają „root” jako nazwy konta uprzywilejowanego z identyfikatorem UID 0. QNAP przychodzi na myśl jako jedno. Dlatego powinieneś sprawdzić tylko identyfikator użytkownika 0, a nie nazwę konta root.
roaima
10

To, czego naprawdę chcesz, to ustalić, czy masz dostęp do wykonywania tych operacji. Sprawdzanie, czy zamiast tego jesteś rootem, jest uważane za złą praktykę.

Jeśli system został skonfigurowany tak, aby zezwolić użytkownikowi innemu niż root na modyfikowanie zamiany i upuszczanie pamięci podręcznej strony, dlaczego ten użytkownik nie powinien uruchomić skryptu?

Zamiast tego możesz po prostu spróbować wykonać operację i wyjść z pomocnym komunikatem, jeśli się nie powiedzie:

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
ten inny facet
źródło
Użytkownik inny niż root wyłączający swap?
Kusalananda
2
Tak. Możesz to skonfigurować za pomocą SELinux. Podobnie możesz wyłączyć wykonywanie procesu root.
ten drugi facet
1
Możesz nie chcieć, exitgdy coś się nie powiedzie, na wypadek, gdyby użytkownik chciał zrobić tyle, ile może, korzystając z obecnych uprawnień. (Ale w typowym systemie, w którym wszystko to wymaga rootowania, wyjście byłoby bardziej użyteczne / mniej głośne.)
Peter Cordes
2
Nie posunąłbym się nawet do stwierdzenia, że ​​„złą praktyką” jest sprawdzanie, czy jesteś rootem. Zwłaszcza jeśli dokładnie to chcesz wiedzieć. Uważam, że najlepiej jest sprawdzić, czy masz wystarczające uprawnienia do robienia tego, co chcesz.
Erik Bennett,