Як перевірити, чи працює він як root у скрипті bash


274

Я пишу сценарій, який вимагає дозволів кореневого рівня, і хочу зробити так, що якщо сценарій не запускається як root, він просто повторюється "Будь ласка, запустіть як root". і виходить.

Ось псевдокод для того, що я шукаю:

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

  else (do stuff)
fi

exit

Як я міг найкраще (чисто і надійно) це досягти? Дякую!

Ах, просто для уточнення: частина (робити речі) передбачає виконання команд, які самі по собі вимагають root. Отже, запустивши його як звичайний користувач, просто з’явиться помилка. Це просто призначено для чистого запуску сценарію, який вимагає кореневих команд, не використовуючи sudo всередині сценарію, я просто шукаю синтаксичний цукор.


8
(1) зробити його не виконуваним нічим іншим, а потім root (2) також організувати подальші дозволи. (3) id -uповертає 0для root.
Wrikken

Відповіді:


403

Змінна середовища $ EUID містить UID поточного користувача. UID кореня дорівнює 0. Використовуйте щось подібне у своєму сценарії:

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

Примітка. Якщо ви 2: [: Illegal number:перевірите, чи є #!/bin/shу вас вгорі, і змініть його на #!/bin/bash.


Здається, хороші дозволи та наявність цього - подвійний рівень безпеки
Колобський каньйон

25
Я думаю, що краще порівняти рядок із рядком, число з числом. використовуючи подвійні дужки, ви можете користуватися> безпосередньо без жодної лапки [[$ EUID> 0]]
Серхіо Абреу

7
Я отримав 2: [: Illegal number:попередження, поки не змінив його на версію Серхіо.
alexeydemin

1
@ thekiwi5000 Точка з комою потрібна лише у тому випадку, якщо знак thenзнаходиться на тій же лінії, що і умова ...
ptierno

1
@StephenAngelico Судо має працювати. Якщо ви тестуєте це, роблячи $ sudo echo $ EUID; це поганий тест і не вдасться, оскільки $ EUID розширюється до передачі команди в sudo. Спробуйте помістити echo $ EUID в тестовий сценарій і запустити це з sudo.
користувач1169420

79

У сценарії bash у вас є кілька способів перевірити, чи працює він користувачем root.

Як застереження , не перевіряйте, чи користувач користується root, використовуючи rootім'я користувача. Ніщо не гарантує, що користувач з ідентифікатором 0 викликаєтьсяroot . Це дуже сильна конвенція, яку широко дотримуються, але хтось може перейменувати суперпользователя іншим ім'ям.

Я думаю, що найкращим способом при використанні bash є використання $EUIDзі сторінки man:

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

Це кращий спосіб, $UIDякий можна змінити і не відображати справжнього користувача, що виконує сценарій.

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

Спосіб, до якого я підходжу до такої проблеми, полягає у введенні sudoмоїх команд, коли не працює як root. Ось приклад:

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

Таким чином моя команда запускається під коренем при використанні суперпользователя або sudoпри запуску звичайним користувачем.

Якщо ваш сценарій завжди повинен запускатися під коренем, просто встановіть права відповідно ( 0500).


Якщо особа, яка намагається запустити скрипт, не має привілеїв sudo, це призведе до того, що помилка буде видалена, і команда не запуститься? Просто хочу переконатися, я правильно розумію.
Caperneoignis

1
Я не впевнений, що ця відповідь на 100% повністю правильна. На RHEL7.2 за допомогою Bash 4.2.46 ... якщо я printf $EUIDз судо або без нього, я отримую свій власний UID. Якщо я використовую, id -uя отримую свій UID, і коли я викликаю його судо, я отримую 0 назад. Я щось не так зробив?
0xSheepdog

4
@ 0xSheepdog, можливо, що на bash cli розширення змінної $ EUID спочатку вирішується, а потім sudo змінює користувача. Тому ви отримаєте таку поведінку, але в сценаріях все-таки буде добре.
Олександр Птах

@AlexanderBird Добрий момент, дякую! Я не робив жодного реального тестування, просто повідомив про свій досвід.
0xШепдог

3
Використовуйте "herestring" для свого тесту, щоб запобігти локальному розширенню оболонки змінної. Порівняйте sudo bash <<<'echo $EUID'з bash <<<'echo $EUID'. Більше про гередок, схожий на гередок, на tldp.org/LDP/abs/html/x17837.html
Бруно Броноський

75

Дано кілька відповідей, але виявляється, що найкращим методом є:

  • id -u
  • Якщо запустити як root, поверне ідентифікатор 0.

Це здається більш надійним, ніж інші методи, і, здається, він повертає ідентифікатор 0, навіть якщо сценарій запускається sudo.


1
Чудово це найкраща відповідь
Дан Ортега

59
if [[ $(id -u) -ne 0 ]] ; then echo "Please run as root" ; exit 1 ; fi

або

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

:)


Ви можете розглянути можливість інтеграції відповіді Джеремі Дж Старчера з цією частиною, врешті-решт, це завжди ті самі речі ...
realnice

Я знаю, що з терміналу, коли я забуваю щось префіксувати за допомогою, sudoя можу просто набрати, sudo !!і це спрацює для мене, а не натискаючи стрілку вгору, переходячи до початку рядка і додаючи sudo вручну. Не впевнений, що це річ BASH чи річ SUDO чи інша, але вона працює майже весь час.
0xSheepdog

@ 0xSheepdog: це справа Баша (і особливість деяких інших оболонок, таких як csh, де IIRC він виник).
Призупинено до подальшого повідомлення.

Загалом, я би видалив підзаконену частину в цілому і переписав би рядок ОК if [ "$(id -u)" -ne 0 ]; then echo 'Please run as root.' >&2; exit 1; fi. Ура.
LinuxSecurityFreak

29

Як згадував @wrikken у своїх коментарях, id -uце набагато краща перевірка на root.

Крім того, при правильному використанні sudoви можете перевірити сценарій і побачити, чи працює він як root. Якщо ні, то згадайте про себе через, sudoа потім запустіть з правами root.

Залежно від того, що робить сценарій, іншим варіантом може бути налаштування sudoзапису для будь-яких спеціалізованих команд, які сценарій може знадобитися.


Чи є витончений спосіб пригадати програму про себе? Можливо, є якась змінна bash з абсолютним шляхом до програми?
Натан

1
Наразі я не поруч із запитом BASH для тестування, але $0має ім'я запущеного сценарію. Є кілька прикладів тут , які можуть допомогти вам.
Jeremy J Starcher

25

Існує проста перевірка того, чи користувач має root.

[[ stuff ]]Синтаксис стандартний спосіб запуску перевірки в Баш.

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

Це також передбачає, що ви хочете вийти з 1, якщо ви не вдається. errorФункція деякий чуття , що набори висновок текст на червоний (не потрібно, але досить класний , якщо ви запитаєте мене).


Що це за errorкоманда? Моя система, схоже, її не має. . .
ruakh

О, це лише невеличкий нюх. Не важливо все так багато, але я прикладу це.
Слейтер Вікторов

4
Це дуже круто! Якщо я можу запропонувати кілька вдосконалень: (1) перенести новий рядок до кінця; (2) записувати на стандартну помилку, а не на стандартний вихід; (3) встановити колір лише у тому випадку, якщо стандартною помилкою є термінал (а не ризик записувати втечі символів у файли журналу lessчи щось таке); і (4) встановити колір фону, тому текст буде читабельним незалежно від кольору фону терміналу користувача. Отже, щось на кшталт function error () { if [[ -t 2 ]] ; then echo $'\033[31;2;47m'"$@"$'\033[0m' ; else echo "$@" ; fi >&2 ; }. (Заправити за бажанням.)
Поправити за ruakh

3
Чи не повинно це бути "-ne" замість "-eq"?
Карлос Рендон

2
@CarlosRendon Код Слейтера - це запобігання запуску чогось як root. (Це навпаки, про що просила ОП, але метод перевірки був би таким же.)
Джошуа Тейлор

11

Дуже просто, просто кажучи:

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

Перевага використання цього замість цього idполягає в тому, що ви можете перевірити, чи виконує команду певний некористувач; напр.

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

якщо ви перевіряєте користувача за допомогою рядка "root", чи не дозволяєте ви запускати когось із ім'ям "root"?
pcarvalho

Ви забули ';' після if
Triskeldeian

1
@peteroak хто ще назвав би корінь, крім кореня?
ptierno

3
+1 за те, що реально відповів на питання про те, whoamiа не використовувати id; whoamiкоманда також може бути використана для перевірки інших користувачів , ніж корінь, на ім'я.
Jez

10

0- Прочитайте офіційну документацію GNU Linux, існує багато способів зробити це правильно.

1- обов’язково поставте підпис оболонки, щоб уникнути помилок в інтерпретації:

 #!/bin/bash

2- це мій сценарій

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

У цій відповіді, нехай це буде зрозуміло, я припускаю, що читач вміє читати bashта подібні сценарії оболонки POSIXdash .

Я вважаю, що тут пояснювати не так багато, оскільки відповіді, що отримали високий голос, добре пояснюють багато цього.

Але, якщо є щось пояснити далі, не соромтесь коментувати, я зроблю все можливе, щоб заповнити прогалини.


Оптимізоване всебічне (не тільки bash) рішення щодо продуктивності та надійності; всі оболонки сумісні

Нове рішення:

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

Тест (зберегти у файл 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

Оригінальне рішення:

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

^^^ Рішення, яке викреслило, було доведено, що воно не пришвидшує справи, але воно існувало вже давно, тому я збираюся тримати його тут, поки вважаю за потрібне.


Пояснення

Оскільки в багато разів швидше зчитувати $EUIDстандартну bashзмінну, ефективний номер ідентифікатора користувача, ніж виконувати id -uкоманду для POSIX-тільки знайти ідентифікатор користувача, це рішення поєднує в собі як добре упаковану функцію. Якщо, і тільки якщо, з $EUIDбудь-якої причини немає, id -uкоманда буде виконуватися, гарантуючи, що ми отримаємо належне повернене значення незалежно від обставин .


Чому я розміщую це рішення після стількох років, що запитувала ОП

Що ж, якщо я правильно бачу, то, здається, вище відсутній фрагмент коду.

Розумієте, існує багато змінних, які потрібно враховувати, і одна з них - це поєднання продуктивності та надійності .


Портативне рішення POSIX + Приклад використання вищевказаної функції

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

Висновок

Настільки, наскільки ви, можливо, не любите це, середовище Unix / Linux багато в чому відрізняється. Тобто є люди, яким bashтак подобається , вони навіть не думають про портативність ( оболонки POSIX ). Інші, як я, віддають перевагу оболонкам POSIX . Сьогодні це питання особистого вибору та потреб.


6

Якщо сценарій дійсно вимагає кореневого доступу, то його права повинні відображати це права. Маючи кореневий скрипт, який виконується некористувальниками, було б червоним прапором. Я закликаю вас не контролювати доступ за допомогою ifчека.

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

4
Якщо хтось має свої дозволи для того, щоб це було чудово, але я відчуваю, що надмірне використання 777бомби робить цю перевірку трохи несправною для тих користувачів, які б в першу чергу помилилися.
Слейтер Вікторов

7
Це за умови, що користувач виконує виконуваний сценарій. Якщо користувач просто дзвонить, bash /path/to/scriptйого все одно можна o=r
запустити,

5

Один з простих способів зробити сценарій тільки виконуваним під корінь - це запустити сценарій з рядка:

#!/bin/su root


1
Мені цікаво, чому ця відповідь не проголосується вище? Це здається найпростішим і чистішим. Чи є тут недоліки?
Басинатор

@Bassinator Я вважаю, що деякі люди кажуть, що вона не працюватиме на певних nix, але вона працює бездоганно на моєму Linux. Спробуй це! Можливо, ця відповідь запізнилася на перегони, але я намагаюся додати знання прості для спільноти (замість того, щоб давати подібні відповіді, як більшість у цій темі: /) Проголосуйте за це, якщо вам пощастить прочитати це та це працює на вашій машині
alexandre1985

@TamusJRoyce Якщо метою є перевірка того, чи ти працюєш як root, а не змушує сценарій запускатись лише як root, чому тоді у кожній відповіді, після перевірки, чи працює як root, вони роблять скрипт exit? І все-таки ці відповіді підтримуються? Я думаю, люди неявно не хочуть, щоб сценарій запускався як root. Тож я слідую за таким способом мислення, з більш простою відповіддю. Але так, ви також можете дізнатися з більш детальних відповідей вище
alexandre1985,

@ alexandre1985 Рівно. Сценарій: Якщо запускається як root, можливо, ви хочете, щоб сценарій за замовчуванням встановив програму глобально, коли він запитує, як ви хочете її встановити. В іншому випадку за замовчуванням встановлено локальну установку. Замість того, щоб натиснути клавішу "Вхід", користувач міг вибрати глобальну чи локальну установку. Але якщо їм подобається за замовчуванням, вони можуть натиснути Enter. І пароль не буде запропонований. Ваш шебанг ніколи не "перевірить", якщо ви є коренем (за назвою). Але я все ж думаю, що ця відповідь корисна.
TamusJRoyce

@TamusJRoyce абсолютно має сенс ваш коментар. Дійсно викликає занепокоєння, і це рішення не для цього випадку використання. Ви відкрили мої перспективи. Ти правий. Спасибі
alexandre1985

4

спробуйте наступний код:

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

АБО

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

3

Наскільки я знаю правильний спосіб перевірити це:

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

Дивіться розділ "Тестування на корінь" тут:

http://linuxcommand.org/lc3_wss0080.php


1
замінити = "0"з-eq 0
LinuxSecurityFreak

1
@LinuxSecurityFreak, я заміню його, якщо ви поясните, чому я повинен це робити.
WebBrother

2

id -uнабагато краще whoami, оскільки деякі системи, такі як Android, можуть не забезпечити слово root.

Приклад:

# whoami
whoami
whoami: unknown uid 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

Примітка редактора: Якщо вам не потрібні подвійні дужки, використовуйте одиничні для перенесення коду.


3
Ви не пояснили, чому ви дали альтернативну відповідь на 5-річне запитання, на яке вже є кілька відповідей.
Стіфон

0

Перевірте, чи ви root, і закрийте, якщо ви не:

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

Або в цьому прикладі спробуйте створити каталог у кореневому розташуванні, а потім спробуйте після того, як права були підвищені.

Перевірте, чи є ви кореневим, а якщо не підвищуєте, якщо можливо:

# 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

Перевірте наявність кореня:

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

Випробуваний і працює в корені.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.