Запуск сценария от имени другого пользователя
Я создал сценарий в /etc/init.d/, который должен запускать несколько других сценариев от других (без привилегий root) пользователей из их домашних каталогов, как будто они их запустили.
Я запускаю эти скрипты с: sudo -b -u <username> <script_of_a_particular_user>
И это работает. Но для каждого пользовательского скрипта, который продолжает работать (например, для некоторого сторожевого таймера), я вижу соответствующий родительский процесс sudo, все еще работающий и работающий от имени пользователя root. Это создает беспорядок в списке активных процессов.
Итак, мой вопрос: как я могу запустить (разветвить) другой скрипт из существующего скрипта bash от имени другого пользователя и оставить его как потерянный (автономный) процесс?
Более подробное объяснение:
Я в основном пытаюсь предоставить другим пользователям на машине средство запуска чего-либо при запуске системы или выключении системы путем запуска исполняемых файлов, найденных в соответствующих подкаталогах в их домашнем каталоге, с именами.startUp и.shutDown. Поскольку я не нашел другого способа сделать это, я написал свой bash-скрипт, который делает именно это, и я настроил его как служебный скрипт (следуя примеру скелета) в /etc/init.d/, поэтому, когда он запускается с аргументом start он запускает все из каталогов.startUp, а когда он запускается с аргументом stop, он запускает все из каталогов.shutDown всех пользователей как они.
В качестве альтернативы мне также интересно, если бы я мог использовать какое-то существующее решение для решения этой проблемы.
ОБНОВИТЬ
Я немного осмотрелся и нашел этот вопрос: https://unix.stackexchange.com/questions/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> &"
Мой дополнительный вопрос: почему он работает без отрешенности? я должен все еще оставить вызов disown, независимо, для некоторого потенциального особого случая?
ОБНОВЛЕНИЕ 2
Видимо это тоже работает:
su <username> -c "<script_of_a_particular_user> &"
Есть ли разница между этим вызовом и вызовом sudo? Я знаю, что это потенциально совершенно другой вопрос. Но так как я сам здесь нахожу ответы, может быть, ради этой темы кто-то мог бы прояснить это здесь.
ОБНОВЛЕНИЕ 3
Оба эти метода с использованием su или sudo теперь производят новый процесс startpar (один процесс, выполняющийся от имени пользователя root) после загрузки машины. Отображается в списке процессов как:
startpar -f -- <name_of_my_init.d_script>
Почему этот процесс порожден? Очевидно, что я делаю что-то не так, поскольку ни один другой скрипт init.d не запускает этот процесс.
ОБНОВЛЕНИЕ 4
Проблема с startpar решена. Я начал другой вопрос для этого:
процесс startpar зависает при запуске процессов из rc.local или init.d
И еще один вопрос для дальнейшего обсуждения механизмов запуска для непривилегированных пользователей:
Предоставление обычным пользователям (без полномочий root) возможностей инициализации и автоматического запуска
4 ответа
Правильный ответ на это заключался в том, что для правильной "демонизации" стандартный ввод, стандартный вывод и стандартная ошибка должны быть перенаправлены в /dev/null (или в какой-то реальный файл):
su someuser -c "nohup some_script.sh >/dev/null 2>&1 &"
su - заменить идентификатор пользователя на someuser
-c - аргумент su для запуска указанной команды
nohup - Запустите команду, невосприимчивую к зависаниям. Для предотвращения случаев, когда родительский процесс завершит дочерний процесс. Добавлено здесь на всякий случай. Но на самом деле не имеет никакого эффекта в моем конкретном случае. Нужно ли это, зависит от окружающей среды (проверьте покупателя)
> / dev / null - Перенаправить стандартный вывод в ничто, отключив его.
2> & 1 - Перенаправить стандартный вывод ошибки (2) на стандартный вывод (1), который перенаправляется на ноль
& - отсоединиться от фона, это перенаправит стандартный ввод также в /dev/null.
По сути, это именно то, что делает утилита start-stop-daemon из Debian dpkg в своей основе. Вот почему я предпочитаю запускать сценарии таким образом, а не вводить в код другой вызов внешней утилиты. start-stop-daemon полезен в тех случаях, когда у вас есть полнофункциональные программы-демоны, которые вам нужно запустить, и когда вам понадобятся дополнительные функции, которые предоставляет 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
Вы можете использовать start-stop-daemon из init.d с --user
вариант.
Я не полностью проверил это, но я думаю, что-то вроде:
/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 может быть сделана чем-то вроде запуска, но вы не можете быть уверены, что скрипты будут работать до конца, так как в любом случае должно произойти завершение работы:-)
следует сделать свое дело, возможно, вам следует добавить некоторое перенаправление ввода, но тогда вам придется беспокоиться о заполнении файлов журнала.
Вы пытались использовать su
?
su -c /home/user/.startUp/executable - user
-c
говорит su выполнить команду, а последний параметр - это пользователь, который ее выполняет.