Як скрипт може перевірити, чи він запускається як root?


104

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

Просто щоб бути ясно:
Що простий спосіб , щоб написати сценарій foo.sh , так що команда ./foo.shвиводить 0, і команда sudo ./foo.shвиводить 1?

Відповіді:


148
#!/bin/bash
if [[ $EUID -ne 0 ]]; then
   echo "This script must be run as root" 
   exit 1
fi

7
Я приймаю цю причину (після деякого тестування) за допомогою системної змінної EUID виявився (приблизно в 100 разів) швидшим, ніж виконання команди (id -u), але всі відповіді спрацювали чудово.
Малабарба

18
Також є $UIDі $EUIDбашизми. Просто оболонки, сумісні з POSIX, не мають цих змінних, і їх потрібно використовувати id(1)замість цього.
Девід Фоерстер

3
у баш-скрипті, який ви можете використати if ((EUID)); then, дивіться коментар @ geirha
jfs

7
@Andrew: Змінні підміняються перед їх передачею sudo. Якщо ви запустите, sudo sh -c 'echo $EUID'ви побачите очікувані результати.
М. Дадлі

6
@Andrew - Я знаю, я запізнився тут, але для нащадків: $EUIDце башизм (як згадував вище @DavidFoerster), і ваш /bin/sh, швидше за все, посилання на /bin/dash, ні /bin/bash. sudo bash -c 'echo $EUID'дасть очікуваний результат.
Адріан Гюнтер

118

Користувачу root не потрібно називати "root". whoamiповертає перше ім’я користувача з ідентифікатором користувача 0. $USERмістить ім’я користувача, який увійшов у систему, який може мати ідентифікатор користувача 0, але має інше ім’я.

Єдина надійна програма, яка перевіряє, чи обліковий запис увійшов як root, чи ні:

id -u

Я використовую -uдля ефективного ідентифікатора користувача, а не -rдля реального ідентифікатора користувача. Права доступу визначаються з допомогою ефективного ідентифікатора користувача, а НЕ реальні один.

Тести

/etc/passwdмістить такі імена користувачів з ідентифікатором користувача 0у заданому порядку:

rootx
root2

Увійшов як root2, дає наступні результати:

  • whoami: rootx
  • echo $USER: root2(це повертає порожню рядок, якщо програма була запущена в порожньому середовищі, наприклад env -i sh -c 'echo $USER')
  • id -u: 0 Як бачимо, інші програми не вдалися до цієї перевірки, лише id -uпройшли.

Оновлений сценарій виглядає приблизно так:

#!/bin/bash
if ! [ $(id -u) = 0 ]; then
   echo "I am not root!"
   exit 1
fi

5
Вам не потрібно id -uв bash askubuntu.com/questions/30148/…
jfs

5
Я завжди намагаюся залишатися максимально сумісним з POSIX, використовуючи sh( dash) як інтерпретатор замість bash. Але гарний удар, рятує ще один вил :)
Лекенштейн

Після того, як на деякий час не було холодно, я повернувся і подивився. Метод Лекенштейна справді здається кращим. Тепер його відповідь - нова прийнята відповідь. +1 вам, Лекенштейн, esp. для отримання цього важкодоступного значка від цього питання;)
Thomas Ward

Дякую за те, що чекали, що прийняли моє запитання: DI отримав Золотий Популістський знак та бронзовий Приємний відповідь за цю відповідь :) Цікаво, як це питання набуло такої популярності, 345 переглядів за день!
Лекенштейн

3
Я бачив коротші версії, [ -w / ]. Ідея залишається такою ж. Примітка: у певних хротонах [ -w /etc/shadow ]не вдасться, оскільки /etc/shadowне існує, тому підхід із /переважним є. Шлях краще перевірити фактичну потребу в кореневих правах. Якщо сценарій потрібно записати /etc/someconfig, просто перевірте, чи цей файл піддається запису АБО файл не існує і він /etcможе бути записаний.
Лекенштейн

30

Як сказав @Lekensteyn, ви повинні використовувати ефективний ідентифікатор користувача. Вам не потрібно дзвонити id -uв bash:

#!/bin/bash

if [[ $EUID -ne 0 ]]; then
   echo "You must be root to do this." 1>&2
   exit 100
fi

@ geirha пропозиція з коментарів використовує арифметичну оцінку:

#!/bin/bash

if (( EUID != 0 )); then
   echo "You must be root to do this." 1>&2
   exit 100
fi

7
Взагалі слід використовувати ((..))для тестування чисел, а також [[..]]для тестування рядків і файлів, тому я б зробив це if (( EUID != 0 )); thenзамість цього, або простоif ((EUID)); then
geirha

@geirha: Я додав вашу пропозицію.
jfs

2
EUIDповинні стати $EUID. Замість використання (( $EUID != 0 ))використовуйте [ $EUID != 0 ]. Так само буде працювати dash.
Лекенштейн

2
@Lekensteyn: EUIDпрацює чудово. Питання позначено bashне dash. Команда env -i sh -c '[ $EUID != 0 ]'не працює, але env -i bash -c '(( EUID != 0 ))'працює. btw, dashне працює для деяких символів , що не належать ascii на Ubuntu stackoverflow.com/questions/5160125/… Це 2011 рік, і є люди, які використовують інші мови.
jfs

Після того, як я оглянувся на цьому, коли я жахливо нудьгував, і випробував, я буду використовувати цей метод, як перераховано тут, з $EUIDматеріалами з цього моменту вперед. Я змінив прийняту відповідь як результат.
Thomas Ward

20

Ви можете досягти цього за допомогою whoamiкоманди, яка повертає поточного користувача:

#!/bin/bash

if [ `whoami` != 'root' ]
  then
    echo "You must be root to do this."
    exit
fi

...

Якщо запустити вище, буде надруковано, You must be root to do this.якщо поточний користувач ні root.


Примітка: альтернативою в деяких випадках є просто перевірити $USERзмінну:

if [ $USER != 'root' ]

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

4
@George Edison: Я рекомендую не використовувати $USER, особливо таким чином. $USERвстановлюється оболонкою входу, вона не обов'язково поширюється на програму ( env -i sh -c 'echo $USER'). Таким чином, $USERпорожній і виникає синтаксична помилка.
Лекенштейн

1
@Lekensteyn Не тільки $USERвстановлена ​​оболонка, вона також є легкою підробкою. Whoami поверне фактичного користувача.
Пол де Врієзе

2
@PauldeVrieze Який сенс обдурити цю перевірку?
htorque

1
@andrewsomething: $USERінтерпретується вашою оболонкою, ваш приклад повинен бути sudo sh -c 'echo $USER'для того, щоб бути значимим. @George: він робить неправильне припущення, що whoamiзавжди повертатиметься rootдля UID 0.
sam hocevar

11

Беручи до уваги ефективність, ви можете спробувати спершу EUIDзмінну середовища, а потім, якщо її немає, викликати стандартну idкоманду:

if ((${EUID:-0} || "$(id -u)")); then
  echo You are not root.
else
  echo Hello, root.
fi

Таким чином, завдяки ярлику АБО ви уникаєте виклику системної команди, надаючи пріоритет на запит змінної в пам'яті.

Повторне використання коду:

function amIRoot() {
  ! ((${EUID:-0} || "$(id -u)"))
}

Я боюся, що ви цього не зробили, і я займаю це саме той самий час id -u. Дивіться сценарій стенду разом з результатами під ним тут: pastebin.com/srC3LWQy
LinuxSecurityFreak


2

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


1
Не робіть цього. Він намагається увійти безпосередньо як root, тоді як sudo може знадобитися в багатьох системах, оскільки перша заборонена. Крім того, shebang призначений для того, щоб ваш сценарій запускався у тому, для якого він був розроблений, тоді як ваш метод спричинить запуск сценарію в оболонці за замовчуванням root, чого неможливо передбачити, якщо сценарій керує хтось, крім автора. Тому використання shebang для підняття привілеїв сценарію сильно порушить його портативність і призведе до помилок у багатьох системах. (su: Помилка автентифікації)
StarCrashr


1

Цей фрагмент:

  • Перевіряйте на різних сесіях
  • пропонують використовувати sudo !!
  • і повернути помилку
if ["$ (whoami & 2> / dev / null)"! = "root"] && ["$ (id -un & 2> / dev / null)"! = "root"]
      тоді
      echo "Ви повинні мати root для запуску цього сценарію!"
      ехо "використовувати" судо !! "
      вихід 1
фі

1

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

#!/bin/bash
if ! [ $(id -u) = 0 ]; then
   gksudo -w $0 $@
   exit
fi

#here go superuser commands, e.g. (switch intel cpu into powersave mode):
echo 1 > /sys/devices/system/cpu/intel_pstate/no_turbo
cpupower frequency-set -g powersave

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

gksudoМоже бути недоступним у вашій системі , то встановіть його sudo apt-get install gksu.


0

Цей код працює як в Bash, так і в запасі Bourne sh (тестується в FreeBSD), що не визначає EUID. Якщо існує EUID, його значення повертається, інакше виконується команда 'id'. Це tad коротше, ніж приклад "або" вище, оскільки він використовує вбудовану оболонку ": -".

Корінь в ш:

# echo $EUID

# euid=${EUID:-`id -u`}
# echo $euid
0

In bash:
[chaapala@tenfwd2 ese]$ euid=${EUID:-`id -u`}
[chaapala@tenfwd2 ese]$ echo $euid
10260
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.