Чому "sudo su" в сценарії оболонки не запускає решту сценарію як корінь?


36

Зразок сценарію може бути наступним:

#!/bin/bash
sudo su
ls /root

Використовуючи ./test.shяк звичайного користувача, замість цього запустіть lsяк суперкористувача та вийдіть, він переходить на root; і коли я виходжу з системи, він виконується ls /rootяк звичайний користувач.

Чи може хтось розповісти мені про механізм щодо цього?


13
sudo suзмушує мене боліти очі.
gelraen

Він використовується тому, що люди недостатньо добре знають sudo, і тому їм потрібен спосіб запускати su в системах, де root захищений свідомо пошкодженим паролем. Але так, судо "скорочує" використання су.
Йохан

1
Ти не можеш просто використати sudo -s?
Джо З.

@ Джохан, я часто використовую, sudo suтому що більше звик до варіантів, suніж я з тих sudo. Я досить добре знаю варіанти судо, але я можу швидше набрати су. Але так, я думаю, це означає, що я не знаю досить добре судо.
user606723

1
Я щойно перевірив сторінку sudo man. Здається, sudo -iце схоже на su -той час, коли sudo -sдіє як su(без тире)
Йохан

Відповіді:


49

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

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

Що ви хочете зробити, це написати сценарій обгортки. Привілейовані команди переходять, наприклад, до основного сценарію~/main.sh

#!/bin/sh
ls /root

Скрипт обгортки викликає основний скрипт із дозволами root, як це

#!/bin/sh
su -c ~/main.sh root

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

Цю техніку обгортки можна використовувати для перетворення сценарію в обгортку навколо себе. В основному перевірте, чи працює він як root, якщо ні, використовуйте "su", щоб перезапустити себе.

$ 0 - це зручний спосіб змусити скрипт посилатися на себе, і команда whoami може сказати нам, хто ми є (чи ми root?)

Так стає основним сценарієм із вбудованою обгорткою

#!/bin/sh
[ `whoami` = root ] || exec su -c $0 root
ls /root

Зверніть увагу на використання exec. Це означає "замінити цю програму на", що фактично закінчує її виконання і запускає нову програму, запущену su, з root, щоб запустити зверху. Екземпляр заміни "root", тому він не виконує праву частину ||


1
fwiw, додаток до цього пункту. Якби я писав такий сценарій, я би просто зробив оператор if на початку, який перевіряє $ EUID, і якщо це не нульовий sudo сам і вихід, інакше продовжуйте виконання сценарію.
Братчлі

Погодився, і я оновлю відповідь, щоб пояснити це.
Йохан

2
Можливо, це трохи архаїчно, але я люблю абсолютні шляхи до кожного виконуваного файлу, тому хтось не може змінити сценарій ~ / main.sh на щось нечестиве. Напад на частину сценарію USER
artifex

2
Ви також можете захопити аргументи, які були передані йому, включивши посилання на $ *
Братчлі

@JoelDavis Я завжди натикаюся на стіну "що робити, якщо в аргументах є символи пробілів". Я ніколи не знайшов задовільного рішення. Одного разу я написав сценарій, який виклав свої аргументи у тимчасовий файл, один аргумент на рядок, а потім зателефонував все, що було потрібно, і передав цьому остаточному сценарію аргумент того, який файл слід прочитати, щоб знайти оригінальні аргументи.
Йохан

20

Використовуйте наступне у сценарії.

sudo su <<HERE
ls /root
HERE

Код між блоком HERE запускатиметься як root.


6
sudo suвикликає дві програми. Використовуйте sudo -s <<HEREDOCабо su user <<HEREDOC... Дурна 5-хвилинна межа.
Йохан

6

Без додаткових аргументів suзапустіть оболонку входу для root. Ось що насправді робить перший рядок вашого сценарію. При виході, Замкнута оболонки входу в систему , повертається су і ваш скрипт продовжує виконання, тобто у другому рядку: ls /root. Я думаю, що ти можеш просто sudo ls /rootробити те, що ти хочеш.


Так, я знаю, що можу це зробити ls, але це лише зразок. Насправді мені потрібно зробити набагато більше речей з привілеєм root :-) Тому я віддаю перевагу відповідь @ Ankit.
Hongxu Chen

1

Як тільки ви запустите sudo suновий процес з ефективним userid (euid=EUID)роздвоєнням суперкористувача, отже, у нас з'явився новий bash, який працює з різним ідентифікатором процесу, (pid=PID)пов'язаним з тим же терміналом (tname=TTY).

Пояснення

Припустимо, після вистрілу у ps -A | grep bashвас є 21460 pts/2 00:00:00 bashвихід. Тепер, коли ви виконаєте ./test.shобидві команди, sudo suі ls /rootви отримаєте змоту PID 21460. Після виконання, коли ви знову rootнатиснете на активного користувача ps -A | grep bash, ви помітите новий баш PID say, 21570. Вихід із root bashзагине щойно розщеплений баш, який повертається до цього, user's bashі, отже, виконує спільну команду ls /rootперед тим, як випустити підказку.


Якщо використання su або sudo було "стійким" у баші (або деінде), це створило б набагато більше проблем, ніж було вирішено. Вам потрібно зробити мінімально можливий як root для безпеки та безпеки. Головний сенс наявності су-судо (крім безпеки!) - змусити вас добре подумати про те, для чого потрібні привілеї root.
Джо
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.