以不同的用户身份运行Linux服务的最佳实践

在我的RHEL盒子上,服务默认以启动时的root身份启动。 如果我没有记错的话,对于在/etc/init.d使用init脚本的其他Linux发行版也是如此。

你认为最好的方式是让stream程像我select的(静态)用户一样运行。

我到达的唯一方法是使用像这样的东西:

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

但是这似乎有点不整洁

是否有一些隐藏的魔术提供了一个简单的机制来自动启动其他非root用户的服务?

编辑:我应该说,我在这个实例开始的进程是Python脚本或Java程序。 我宁愿不写一个本地包装在他们身边,所以不幸的是,我不能像黑色build议一样调用setuid() 。

在Debian上,我们使用start-stop-daemon实用程序来处理pid文件,更改用户,将守护程序放入后台等等。

我对RedHat并不熟悉,但是您已经使用的daemon实用程序(在/etc/init.d/functions中已经定义)在任何地方都被称为start-stop-daemon ,所以无论是它也可以改变你的程序的uid,或者你做的方式已经是正确的了。

如果你环顾networking,有几个现成的包装,你可以使用。 有些甚至可能已经包装在RedHat中。 例如,看看daemonize

在看了这里的所有build议后,我发现了一些我希望对我的立场有用的东西:

  1. hop是正确的指向我在/etc/init.d/functionsdaemonfunction已经允许你设置一个替代用户:

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

    这是通过用runuser包装进程调用来实现的,稍后再介绍。

  2. Jonathan Leffler是对的:Python中有setuid:

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

    但是,我仍然认为你不能从JVM里面设置setuid。

  3. surunuser都不会优雅地处理您要求以您已经是用户的身份运行命令的情况。 例如:

     [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) 

为了解决surunuser行为,我已经把我的初始化脚本改成如下所示:

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

感谢你的帮助!

  • 一些守护进程(例如apache)通过调用setuid()
  • 您可以使用setuid-file标志以不同的用户身份运行该进程。
  • 当然,你提到的解决scheme也适用。

如果您打算编写自己的守护进程,那么我build议调用setuid()。 这样,你的过程可以

  1. 利用它的根特权(例如打开日志文件,创buildpid文件)。
  2. 在启动过程中的某一时刻放弃其root权限。

只是添加一些其他的事情要注意:

  • 在一个init.d脚本中的Sudo是不好的,因为它需要一个tty(“sudo:对不起,你必须有一个tty来运行sudo”)
  • 如果您正在守护一个Java应用程序,您可能需要考虑Java Service Wrapper(它提供了一个设置用户标识的机制)
  • 另一种select可能是su –session-command = [cmd] [user]

在svn服务器的CENTOS(Red Hat)虚拟机上:编辑/etc/init.d/svnserver ,将pid更改为svn可以编写的内容:

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

并添加了选项--user=svn

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

原始的/var/run/svnserve.pid/var/run/svnserve.pid 。 守护进程没有启动becaseu只有根可以写在那里。

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

有些事情要注意:

  • 正如你所提到的,如果你已经是目标用户,su会提示input密码
  • 同样,如果您已经是目标用户(在某些操作系统上),setuid(2)将会失败,
  • setuid(2)不会安装在/etc/limits.conf(Linux)或/ etc / user_attr(Solaris)中定义的特权或资源控制,
  • 如果你去setgid(2)/ setuid(2)路线,不要忘记调用initgroups(3) – 在这里更多

在启动守护进程之前,我通常使用/ sbin / su切换到相应的用户。

为什么不在init脚本中尝试以下内容:

 setuid $USER application_name 

它为我工作。

我需要运行一个Spring .jar应用程序作为一个服务,并find一个简单的方法来运行这个特定的用户:

我将我的jar文件的所有者和组更改为我想运行的用户。 然后在init.d中将这个jar声明并启动服务。

所以:

 #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