Как остановить запуск скрипта, если он не root (и вывести «Не запускается как root! Выход ...»)

17

Вот мой источник:

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

Он очищает кеши и прочее и повторяет, что его нужно запускать от имени пользователя root в терминале. Я просто хочу, чтобы скрипт прекратил работу, если обнаружит, что он не выполняется от имени пользователя root.

Пример:

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

Если запустить с повышенными привилегиями, он будет работать как обычно. Есть идеи? Благодарность!

М. Кнеппер
источник
Возможный дубликат Как помешать root запустить скрипт
muru
2
@muru, за исключением того, что другой вопрос противоположен: не запускайте скрипт, если он выполняется от имени пользователя root.
Стефан
3
@ StéphaneChazelas ах, мой плохой. Убирались
Мура
Альтернативой является ограничение объема выполняемой работы, так как rootпрефикс префикса всех команд, которые должны выполняться, как rootс sudo.
фоторепортаж

Ответы:

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

Пользователь root имеет UID 0 (независимо от имени учетной записи «root»). Если возвращаемый эффективный UID id -uне равен нулю, пользователь не выполняет сценарий с привилегиями root. Используется id -ruдля проверки реального идентификатора (UID пользователя, вызывающего скрипт).

Не используйте $EUIDв скрипте, поскольку это может быть изменено непривилегированным пользователем:

$ bash -c 'echo $EUID'
1000

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

Если пользователь сделал это, это, очевидно, не приведет к повышению привилегий, но может привести к тому, что команды в сценарии не смогут выполнить то, что они должны делать, и файлы будут созданы с неправильным владельцем и т. Д.

Кусалананда
источник
1
Примечание: в Solaris 5.10 /bin/id -uвыдает/bin/id: illegal option -- u Usage: id [-ap] [user]
jrw32982 поддерживает Monica
1
@ jrw32982 Чтобы получить доступ к утилитам POSIX в Solaris, вам нужно быть на /usr/xpg4/binраннем этапе $PATH.
Кусалананда
1
Дело в том, что -uопция idне является универсальной, и поэтому это решение универсально только с предупреждением о том, что версия POSIX idдолжна встречаться первой в вашей переменной PATH.
jrw32982 поддерживает Монику
1
@ jrw32982 Чтобы ваш скрипт выбрал правильные утилиты POSIX в Solaris, измените его $PATHв верхней части сценария так, чтобы /usr/xpg4/binон был раньше /bin. Если вы настаиваете на использовании не POSIX id, то, очевидно, вам придется придумать более портативное решение.
Кусалананда
1
@Harry Да, чтобы скрипт мог использовать PATH=$( getconf PATH )или установить какой-либо другой явный путь по умолчанию, или использовать явный путь для вызова id.
Кусалананда
19

Я думаю, что вы хотите скорее проверить, что у вас есть привилегии суперпользователя, то есть, что ваш эффективный идентификатор пользователя равен 0.

zshи bashсделайте это доступным в $EUIDпеременной, так что вы можете сделать:

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

С любыми POSIX-подобными оболочками вы можете использовать idстандартную команду:

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

Обратите внимание, что все id -unили whoamiили $USERNAMEпеременная in zshполучат первое имя пользователя для uid. В системах, в которых есть другие пользователи с идентификатором 0, это может не произойти, rootдаже если процесс является потомком того, который был аутентифицирован как root.

$USERбудет , как правило , дают вам пользователю , что проверка подлинности, но полагаться на него довольно хрупкими. Это не задаются оболочкой, но, как правило , устанавливается командой проверки подлинности (например login, su(на системах GNU / Linux, не обязательно другие), sudo, sshd(одного из OpenSSH , по крайней мере) ...). Хотя это не всегда (изменение uid не устанавливает эту переменную автоматически, это должно быть сделано явно приложением, меняющим uid), и это также могло быть изменено каким-то другим процессом в происхождении оболочки. $LOGNAMEс тем же предупреждением более надежно, как указано в POSIX (первоначально из FIPS 151-2)

Стефан Шазелас
источник
12

Вы можете использовать $USERили whoamiдля проверки текущего пользователя.

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
источник
1
NP. Я предлагаю буквально просто прочитать руководство по bash [ gnu.org/software/bash/manual/bashref.html] . Это на самом деле удивительно легко готово. Для этого ответа, в частности, я предлагаю ссылки: 3.2.4.2 Conditional Constructs 3.5.4 Command Substitution
Jesse_b
9
Команда id -uс -nопцией или без нее является альтернативой использованию whoami. Без -n и сравнение с нулем лучше соответствует тесту, которое фактически выполняет ядро. Все, что заботит ядро ​​- это идентификатор, а не имя из файла паролей.
Икар
6
Я считаю, что использование $(id -u)лучше. В некоторых (злонамеренных) случаях $USERможет быть неправильно.
Старынкевич,
1
Для тех, кто заинтересован в ссылке, предоставленной @Jesse_b: есть опечатка. Он должен быть gnu.org/software/bash/manual/bashref.html
Kryten
1
Некоторые системы не используют «root» в качестве имени привилегированной учетной записи, имеющей uid 0. QNAP приходит на ум как единое целое. Таким образом, вы должны проверить только uid 0, а не имя учетной записи root.
Ройма
10

На самом деле вы хотите определить, есть ли у вас доступ для выполнения этих операций. Проверять, действительно ли вы root вместо этого, считается плохой практикой.

Если система настроена так, чтобы пользователь без полномочий root мог изменять кеш страниц подкачки и удаления, почему этот пользователь не должен запускать ваш скрипт?

Вместо этого вы можете просто попробовать выполнить операцию и выйти с полезным сообщением, если оно завершится неудачно:

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
тот другой парень
источник
Пользователь без полномочий root отключает своп?
Кусалананда
2
Да. Вы можете настроить это с помощью SELinux. Кроме того, вы можете отключить корневой процесс от этого.
тот другой парень
1
Вы можете не захотеть, чтобы exitпосле чего-то произошел сбой, в случае, если пользователь хочет сделать столько, сколько он может со своими текущими привилегиями. (Но для типичной системы, где все это требует root, выход будет более полезным / менее шумным.)
Peter Cordes
2
Я бы не сказал, что это «плохая практика» - проверять, являетесь ли вы пользователем root. Особенно, если это именно то , что вы хотите знать. Я понимаю, что лучше всего проверить, достаточно ли у вас разрешений, чтобы делать то, что вы хотите.
Эрик Беннет