Лучшая практика для запуска службы Linux от имени другого пользователя - PullRequest
135 голосов
/ 27 декабря 2008

Службы по умолчанию начинаются как root во время загрузки на моей RHEL коробке. Если я правильно помню, то же самое верно и для других дистрибутивов Linux, которые используют сценарии инициализации в /etc/init.d.

Какой, по вашему мнению, лучший способ запустить процессы как (статический) пользователь по моему выбору?

Единственный метод, к которому я пришел, это использовать что-то вроде:

 su my_user -c 'daemon my_cmd &>/dev/null &'

Но это кажется немного неопрятным ...

Есть ли какая-то магия, которая предоставляет простой механизм для автоматического запуска служб, как другие пользователи, не являющиеся пользователями root?

РЕДАКТИРОВАТЬ: Я должен был сказать, что процессы, которые я запускаю в этом случае, являются либо скриптами Python, либо Java-программами. Я бы предпочел не писать нативную оболочку вокруг них, поэтому, к сожалению, я не могу вызвать setuid () , как подсказывает черный .

Ответы [ 8 ]

67 голосов
/ 27 декабря 2008

В Debian мы используем утилиту start-stop-daemon, которая обрабатывает pid-файлы, изменяет пользователя, переводит демон в фоновый режим и многое другое.

Я не знаком с RedHat, но утилита daemon, которую вы уже используете (которая определена в /etc/init.d/functions, кстати) везде упоминается как эквивалент start-stop-daemon, так что она тоже может измените uid вашей программы, или способ, которым вы делаете это, уже является правильным.

Если вы посмотрите вокруг сети, есть несколько готовых оберток, которые вы можете использовать. Некоторые могут даже быть упакованы в RedHat. Посмотрите, например, daemonize.

53 голосов
/ 27 декабря 2008

Изучив все предложения, я обнаружил несколько вещей, которые, я надеюсь, будут полезны другим на моей должности:

  1. хоп правильно, чтобы указать мне в ответ на /etc/init.d/functions: daemon функция уже позволяет установить альтернативного пользователя:

    daemon --user=my_user my_cmd &>/dev/null &
    

    Это реализуется путем переноса вызов процесса с помощью runuser - Подробнее об этом позже.

  2. Джонатан Леффлер прав: в Python есть setuid:

    import os
    os.setuid(501) # UID of my_user is 501
    

    Я все еще не думаю, что вы можете настроить однако изнутри JVM.

  3. Ни su, ни runuser изящно справиться со случаем, когда вы попросить запустить команду от имени пользователя, которого вы уже есть. E.g.:

    [my_user@my_host]$ id
    uid=500(my_user) gid=500(my_user) groups=500(my_user)
    [my_user@my_host]$ su my_user -c "id"
    Password: # don't want to be prompted!
    uid=500(my_user) gid=500(my_user) groups=500(my_user)
    

Чтобы обойти это поведение su и runuser, я изменил свой скрипт инициализации на что-то вроде:

if [[ "$USER" == "my_user" ]]
then
    daemon my_cmd &>/dev/null &
else
    daemon --user=my_user my_cmd &>/dev/null &
fi

Спасибо всем за помощь!

5 голосов
/ 27 декабря 2008
  • Некоторые демоны (например, apache) делают это самостоятельно, вызывая setuid ()
  • Вы можете использовать флаг setuid-file для запуска процесса от имени другого пользователя.
  • Конечно, упомянутое вами решение также работает.

Если вы намереваетесь написать свой собственный демон, я рекомендую вызвать setuid (). Таким образом, ваш процесс может

  1. Используйте его привилегии root (например, открывайте файлы журнала, создавайте файлы pid).
  2. Отбрасывать свои привилегии root в определенный момент при запуске.
3 голосов
/ 08 марта 2013

на виртуальной машине CENTOS (Red Hat) для сервера svn: отредактировано /etc/init.d/svnserver изменить pid на что-то, что svn может написать:

pidfile=${PIDFILE-/home/svn/run/svnserve.pid}

и добавленная опция --user=svn:

daemon --pidfile=${pidfile} --user=svn $exec $args

Исходный файл pid был /var/run/svnserve.pid. Демон не запустился, потому что там мог писать только root.

 These all work:
/etc/init.d/svnserve start
/etc/init.d/svnserve stop
/etc/init.d/svnserve restart
3 голосов
/ 14 октября 2010

Просто добавьте еще несколько вещей, на которые стоит обратить внимание:

  • Sudo в скрипте init.d не годится, так как ему нужен tty ("sudo: извините, у вас должен быть tty для запуска sudo")
  • Если вы демонизируете Java-приложение, вы можете рассмотреть Java Service Wrapper (который предоставляет механизм для установки идентификатора пользователя)
  • Другой альтернативой может быть su --session-command = [cmd] [пользователь]
2 голосов
/ 17 февраля 2012

Почему бы не попробовать следующее в скрипте инициализации:

setuid $USER application_name

Это сработало для меня.

2 голосов
/ 05 августа 2009

На что нужно обратить внимание:

  • Как вы упомянули, su запросит пароль, если вы уже являетесь целевым пользователем
  • Аналогично, setuid (2) завершится ошибкой, если вы уже являетесь целевым пользователем (в некоторых ОС)
  • setuid (2) не устанавливает привилегии или элементы управления ресурсами, определенные в /etc/limits.conf (Linux) или / etc / user_attr (Solaris)
  • Если вы идете по маршруту setgid (2) / setuid (2), не забудьте вызвать initgroups (3) - подробнее об этом здесь

Обычно я использую / sbin / su для переключения на соответствующего пользователя перед запуском демонов.

0 голосов
/ 31 августа 2016

Мне нужно было запустить приложение Spring .jar в качестве службы, и я нашел простой способ запустить его как определенный пользователь:

Я изменил владельца и группу моего jar-файла на пользователя, от которого я хотел работать. Затем поместил ссылку на этот jar-файл в init.d и запустил службу.

Итак:

#chown myuser:myuser /var/lib/jenkins/workspace/springApp/target/springApp-1.0.jar

#ln -s /var/lib/jenkins/workspace/springApp/target/springApp-1.0.jar /etc/init.d/springApp

#service springApp start

#ps aux | grep java
myuser    9970  5.0  9.9 4071348 386132 ?      Sl   09:38   0:21 /bin/java -Dsun.misc.URLClassPath.disableJarChecking=true -jar /var/lib/jenkins/workspace/springApp/target/springApp-1.0.jar
...