Запуск сценарію як інший користувач


12

Я створив сценарій у /etc/init.d/, який повинен запускати кілька інших сценаріїв від інших (непривілейованих користувачів) користувачів з їхніх домашніх каталогів, як ніби вони їх запускали.

Я запускаю ці сценарії за допомогою: sudo -b -u <username> <script_of_a_particular_user>

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

Отже, моє запитання таке: як я можу запустити (розщедрити) інший скрипт із існуючого bash-скрипту як іншого користувача та залишити його як осиротілого (самостійного) процесу?

Більш детальне пояснення:
я в основному намагаюся надати іншим користувачам на машині засіб для запуску матеріалів при запуску системи або відключенні системи, запустивши виконувані файли, знайдені у відповідних підкаталогах, знайдених у їхньому домашньому каталозі під назвою .startUp та .shutDown. Оскільки я не знайшов інших засобів для цього, я написав свій скрипт bash, який робить саме це, і я налаштував його як службовий скрипт (наслідуючи приклад скелета) в /etc/init.d/, тому під час його запуску з аргументом start він запускає все з каталогів .startUp, а коли він запускається із аргументом stop, він запускає все з каталогів .shutDown всіх користувачів, як їх.

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

ОНОВЛЕННЯ
Я трохи озирнувся і знайшов це питання: /unix/22478/detach-a-daemon-using-sudo

Прийнята відповідь там, на використання:, sudo -u user sh -c "daemon & disown %1"працює для мене. Але я також намагався без відмови% 1, і це те саме. Отже, це для мене працює, як я і очікував:

sudo -u <username> bash -c "<script_of_a_particular_user> &"

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

ОНОВЛЕННЯ 2

Мабуть, це теж працює:

su <username> -c "<script_of_a_particular_user> &"

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

ОНОВЛЕННЯ 3
Обидва ці методи із су або судо тепер створюють новий процес запуску (єдиний процес, що працює як root) після завантаження машини. Видимий у списку процесів як:

startpar -f -- <name_of_my_init.d_script>

Чому цей процес породжений? Очевидно, що я роблю щось не так, оскільки жоден інший скрипт init.d не працює.

ОНОВЛЕННЯ 4
Проблема зі запуском програми вирішена. Я почав ще одне питання для цього:
процес запуску запуску зліва висів під час запуску процесів з rc.local або init.d

І ще одне питання для подальшого обговорення механізмів запуску для непривілейованих користувачів:
Надання нормальним користувачам (не-root) можливостей ініціалізації та відключення автоматичного запуску

Відповіді:


18

Правильна відповідь на це полягала в тому, що для правильної "демонізації" стандартний ввід, стандартний вихід і стандартна помилка повинні бути перенаправлені на / dev / null (або якийсь реальний файл):

su someuser -c "nohup some_script.sh >/dev/null 2>&1 &"

su - підміняти ідентифікацію користувача на someuser
-c - аргумент su для запуску вказаної команди
nohup - Запустіть команду, імунну на зависання. Для запобігання випадків, коли батьківський процес припинить дочірній процес. Додано сюди про всяк випадок. Але насправді це не має ефекту в моєму конкретному випадку. Є чи це необхідно в залежності від навколишнього середовища (перевірка shopt )
> / Dev / нуль - Переспрямувати стандартний висновок ні до чого, в основному відключити.
2> & 1 - перенаправлення стандартної помилки (2) на стандартний вихід (1), який перенаправляється на null
& - від'єднати до фону, це також перенаправить стандартний ввід також на / dev / null.

Це по суті саме те, що в основі є утиліта start-stop-демон від Debian dpkg. Ось чому я вважаю за краще запускати сценарії таким чином, а не вводити ще один виклик зовнішньої утиліти у свій код. start-stop-daemon корисний у тих випадках, коли у вас є повномасштабні програми демонів, які потрібно запустити, і тоді вам потрібна додаткова функціональність, яку надає старт-стоп-демон (наприклад, перевірка, чи вказаний процес вже запущений, щоб він не працював не запускати його знову).

Варто також зазначити, що ви також можете закрити дескриптори файлів вашого процесу, а не перенаправляти їх у / dev / null , наприклад:

su someuser -c "some_script.sh 0<&- 1>&- 2>&- &"

0 <& - Закрити стандартний вхід (0)
1> & - Закрити стандартний вихід (1)
2> & - Закрити стандартну помилку (2) вихід

Напрямок знаків <> не має значення, оскільки вказано довгий номер дескриптора файлу. Тож це однаково добре:

su someuser -c "some_script.sh 0>&- 1>&- 2>&- &"

або

su someuser -c "some_script.sh 0<&- 1<&- 2<&- &"

Однак є трохи коротший спосіб написати, що без цифр для stdin та stdout, де напрямок має значення:

su someuser -c "some_script.sh <&- >&- 2>&- &" 

Коли дескриптори файлів закриті або перенаправлені на / dev / null ( start-stop-daemon робить перенаправлення на / dev / null), процес безпечно запускатись у фоновому режимі як демон. Отже, це те, що потрібно, щоб уникнути проблем ( startpar ) із запуском скриптів під час завантаження.

Я реалізував ціле рішення з моєї початкової ідеї і розмістив його на GitHub:
https://github.com/ivankovacevic/userspaceServices


Іване, чи краще використовувати su або su -login? Я читаю людину су, але не можу зрозуміти для цього конкретного випадку.
Массімо

1
@Massimo, вибачте за затримку моєї відповіді! Перевірте це запитання: unix.stackexchange.com/questions/318572/… там є краща сторінка керівництва, де це пояснюється. В основному різниця полягає у встановленні робочої директорії та змінних середовища. Я б сказав, що для таких випадків використання (роблячи щось як інший користувач) це може бути кращим варіантом фактичного використання -login
Іван Ковачевич


2

Я не до кінця перевірив це, але думаю, що щось на кшталт:

/sbin/start-stop-daemon --background --start --exec /home/USER/.startUp --user USER --pidfile=/home/USER/.startUp.pid --make-pidfile

при запуску, а потім

/sbin/start-stop-daemon --stop --user USER --pidfile=/home/USER/.startUp.pid

при відключенні.

Обробка сценарію .shutDown може бути виконана чимось на кшталт запуску, але ви не можете бути впевнені, що сценарії запускаються до кінця, оскільки завершення роботи повинно відбутися в будь-якому випадку :-)

Ви повинні зробити трюк, можливо, вам слід вписати певне перенаправлення вводу, але тоді вам доведеться турбуватися про заповнення файлів журналів.


2
По суті, це працювало б! start-stop-демон може успішно запускати процеси під час завантаження або іншим чином. Я перевірив це. І він також позбавляється від проблеми з висячим стартовим процесом. Однак у вашому стартовому дзвінку також не вистачає --chuid USER. Без цього він запустив би процес як корінь. Файл pid також, ймовірно, повинен бути записаний в / var / run /, оскільки в іншому випадку він генерує кореневий файл у домашньому каталозі користувачів. Але, на мій погляд, для загального запуску сценарію старт-стоп-демон здається дещо зайвим. Перевірте мою відповідь, де я намагався пояснити, чому.
Іван Ковачевич

1

Ви намагалися використовувати su?

su -c /home/user/.startUp/executable - user

-c каже su для виконання команди, а останній параметр - користувач, який виконує її як.


так, це працює, але з деякою котируванням та додаванням амперсанда. І мені здається, чистіше писати це так: su <username> -c "/some/path/script.sh &" В основному я використовував судо, оскільки він здавався чистішим, але тепер це здається кращим, ніж використання: sudo - u <username> bash -c "/some/path/script.sh &". Не знаю, чи є якісь відмінності у цих двох, проте
Іван Ковачевич
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.