以不同用户身份运行 Linux 服务的最佳实践
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/394984/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Best practice to run Linux service as a different user
提问by James Brady
Services default to starting as root
at boot time on my RHEL box. If I recall correctly, the same is true for other Linux distros which use the init scripts in /etc/init.d
.
root
在我的 RHEL 机器上,服务默认在启动时启动。如果我没记错的话,其他使用 .init 脚本的 Linux 发行版也是如此/etc/init.d
。
What do you think is the best way to instead have the processes run as a (static) user of my choosing?
您认为让进程以我选择的(静态)用户身份运行的最佳方式是什么?
The only method I'd arrived at was to use something like:
我到达的唯一方法是使用类似的方法:
su my_user -c 'daemon my_cmd &>/dev/null &'
But this seems a bit untidy...
但这似乎有点不整洁......
Is there some bit of magic tucked away that provides an easy mechanism to automatically start services as other, non-root users?
是否有一些隐藏的魔法可以提供一种简单的机制来自动启动其他非 root 用户的服务?
EDIT:I should have said that the processes I'm starting in this instance are either Python scripts or Java programs. I'd rather not write a native wrapper around them, so unfortunately I'm unable to call setuid()as Blacksuggests.
编辑:我应该说我在这个实例中启动的进程是 Python 脚本或 Java 程序。我宁愿不为它们编写本机包装器,因此不幸的是,我无法像Black建议的那样调用setuid()。
采纳答案by Black
On Debian we use the start-stop-daemon
utility, which handles pid-files, changing the user, putting the daemon into background and much more.
在 Debian 上,我们使用该start-stop-daemon
实用程序,它处理 pid 文件、更改用户、将守护程序置于后台等等。
I'm not familiar with RedHat, but the daemon
utility that you are already using (which is defined in /etc/init.d/functions
, btw.) is mentioned everywhere as the equivalent to start-stop-daemon
, so either it can also change the uid of your program, or the way you do it is already the correct one.
我不熟悉 RedHat,但是daemon
您已经在使用的实用程序(在 中定义/etc/init.d/functions
,顺便说一句。)在任何地方都被提及为等效于start-stop-daemon
,因此它也可以更改您的程序的 uid,或者您这样做的方式这已经是正确的了。
If you look around the net, there are several ready-made wrappers that you can use. Some may even be already packaged in RedHat. Have a look at daemonize
, for example.
如果您环顾网络,可以使用多种现成的包装纸。有些甚至可能已经打包在 RedHat 中。看看daemonize
,例如。
回答by Black
- Some daemons (e.g. apache) do this by themselves by calling setuid()
- You could use the setuid-file flagto run the process as a different user.
- Of course, the solution you mentioned works as well.
- 一些守护进程(例如 apache)通过调用setuid()自行完成此操作
- 您可以使用setuid-file 标志以不同的用户身份运行该进程。
- 当然,你提到的解决方案也有效。
If you intend to write your own daemon, then I recommend calling setuid(). This way, your process can
如果您打算编写自己的守护进程,那么我建议您调用 setuid()。这样,您的流程就可以
- Make use of its root privileges (e.g. open log files, create pid files).
- Drop its root privileges at a certain point during startup.
- 使用它的root 权限(例如打开日志文件,创建pid 文件)。
- 在启动期间的某个时刻删除其 root 权限。
回答by James Brady
After looking at all the suggestions here, I've discovered a few things which I hope will be useful to others in my position:
在查看了这里的所有建议之后,我发现了一些我希望对处于我职位的其他人有用的东西:
hopis right to point me back at
/etc/init.d/functions
: thedaemon
function already allows you to set an alternate user:daemon --user=my_user my_cmd &>/dev/null &
This is implemented by wrapping the process invocation with
runuser
- more on this later.Jonathan Leffleris right: there is setuid in Python:
import os os.setuid(501) # UID of my_user is 501
I still don't think you can setuid from inside a JVM, however.
Neither
su
norrunuser
gracefully handle the case where you ask to run a command as the user you already are. 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)
hop是正确地指出我
/etc/init.d/functions
:该daemon
功能已经允许您设置备用用户: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 内部设置 uid。
既
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)
To workaround that behaviour of su
and runuser
, I've changed my init script to something like:
为了解决su
and 的这种行为runuser
,我已将我的 init 脚本更改为以下内容:
if [[ "$USER" == "my_user" ]]
then
daemon my_cmd &>/dev/null &
else
daemon --user=my_user my_cmd &>/dev/null &
fi
Thanks all for your help!
感谢你的帮助!
回答by claymation
Some things to watch out for:
需要注意的一些事项:
- As you mentioned, su will prompt for a password if you are already the target user
- Similarly, setuid(2) will fail if you are already the target user (on some OSs)
- setuid(2) does not install privileges or resource controls defined in /etc/limits.conf (Linux) or /etc/user_attr (Solaris)
- If you go the setgid(2)/setuid(2) route, don't forget to call initgroups(3) -- more on this here
- 正如您所提到的,如果您已经是目标用户,su 将提示输入密码
- 同样,如果您已经是目标用户(在某些操作系统上),则 setuid(2) 将失败
- setuid(2) 不安装 /etc/limits.conf (Linux) 或 /etc/user_attr (Solaris) 中定义的权限或资源控制
- 如果您使用 setgid(2)/setuid(2) 路线,请不要忘记调用 initgroups(3) - 更多关于 这里
I generally use /sbin/su to switch to the appropriate user before starting daemons.
在启动守护进程之前,我通常使用 /sbin/su 切换到适当的用户。
回答by pdeschen
Just to add some other things to watch out for:
只是添加一些其他需要注意的事项:
- Sudo in a init.d script is no good since it needs a tty ("sudo: sorry, you must have a tty to run sudo")
- If you are daemonizing a java application, you might want to consider Java Service Wrapper (which provides a mechanism for setting the user id)
- Another alternative could be su --session-command=[cmd] [user]
- init.d 脚本中的 Sudo 不好,因为它需要一个 tty(“sudo:抱歉,你必须有一个 tty 才能运行 sudo”)
- 如果您正在守护 Java 应用程序,您可能需要考虑 Java Service Wrapper(它提供了一种设置用户 ID 的机制)
- 另一种选择可能是su --session-command=[cmd] [user]
回答by cyberJar
Why not try the following in the init script:
为什么不在初始化脚本中尝试以下操作:
setuid $USER application_name
It worked for me.
它对我有用。
回答by dulcana
on a CENTOS (Red Hat) virtual machine for svn server:
edited /etc/init.d/svnserver
to change the pid to something that svn can write:
在用于 svn 服务器的 CENTOS(红帽)虚拟机上:编辑/etc/init.d/svnserver
以将 pid 更改为 svn 可以写入的内容:
pidfile=${PIDFILE-/home/svn/run/svnserve.pid}
and added option --user=svn
:
并添加了选项--user=svn
:
daemon --pidfile=${pidfile} --user=svn $exec $args
The original pidfile was /var/run/svnserve.pid
. The daemon did not start becaseu only root could write there.
原始的 pidfile 是/var/run/svnserve.pid
. 守护进程没有启动,因为只有 root 可以在那里写入。
These all work:
/etc/init.d/svnserve start
/etc/init.d/svnserve stop
/etc/init.d/svnserve restart
回答by Somaiah Kumbera
I needed to run a Spring .jar application as a service, and found a simple way to run this as a specific user:
我需要将 Spring .jar 应用程序作为服务运行,并找到了一种以特定用户身份运行它的简单方法:
I changed the owner and group of my jar file to the user I wanted to run as. Then symlinked this jar in init.d and started the service.
我将 jar 文件的所有者和组更改为我想要运行的用户。然后在 init.d 中符号链接这个 jar 并启动服务。
So:
所以:
#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