Лучшая практика для запуска службы Linux как другого пользователя

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

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

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

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

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

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

EDIT: Я должен был сказать, что процессы, которые я запускаю в этом примере, - это скрипты Python или Java-программы. Я бы предпочел не писать родную оболочку вокруг них, так что, к сожалению, я не могу назвать setuid() как Black.

Ответ 1

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

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

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

Ответ 2

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

  • hop имеет право указать мне назад при /etc/init.d/functions: Функция daemon уже позволяет вам для установки альтернативного пользователя:

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

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

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

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

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

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

    [[email protected]_host]$ id
    uid=500(my_user) gid=500(my_user) groups=500(my_user)
    [[email protected]_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, я изменил свой init script на что-то вроде:

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

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

Ответ 3

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

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

  • Использовать свои корневые привилегии (например, открывать файлы журналов, создавать файлы pid).
  • Откажитесь от своих привилегий root в определенный момент во время запуска.

Ответ 4

Просто добавьте еще кое-что, на что можно обратить внимание:

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

Ответ 5

на виртуальной машине 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

Первоначальный pidfile был /var/run/svnserve.pid. Демон не начинался, потому что там мог писать только корень.

 These all work:
/etc/init.d/svnserve start
/etc/init.d/svnserve stop
/etc/init.d/svnserve restart

Ответ 6

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

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

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

Ответ 7

Почему бы не попробовать следующее в init script:

setuid $USER application_name

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

Ответ 8

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

Я сменил владельца и группу моего файла jar на пользователя, которого я хотел запустить. Затем symlinked этот банку в 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