以不同的用户身份运行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议后,我发现了一些我希望对我的立场有用的东西:
-
hop是正确的指向我在
/etc/init.d/functions
:daemon
function已经允许你设置一个替代用户:daemon --user=my_user my_cmd &>/dev/null &
这是通过用
runuser
包装进程调用来实现的,稍后再介绍。 -
Jonathan Leffler是对的:Python中有setuid:
import os os.setuid(501) # UID of my_user is 501
但是,我仍然认为你不能从JVM里面设置setuid。
-
su
和runuser
都不会优雅地处理您要求以您已经是用户的身份运行命令的情况。 例如:[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
感谢你的帮助!
- 一些守护进程(例如apache)通过调用setuid()
- 您可以使用setuid-file标志以不同的用户身份运行该进程。
- 当然,你提到的解决scheme也适用。
如果您打算编写自己的守护进程,那么我build议调用setuid()。 这样,你的过程可以
- 利用它的根特权(例如打开日志文件,创buildpid文件)。
- 在启动过程中的某一时刻放弃其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