143

服务默认root在我的 RHEL 机器上启动时启动。如果我没记错的话,其他使用 init 脚本的 Linux 发行版也是如此/etc/init.d

您认为让进程作为我选择的(静态)用户运行的最佳方式是什么?

我到达的唯一方法是使用类似的东西:

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

但这似乎有点不整洁......

是否有一些神奇的东西可以提供一种简单的机制来以其他非 root 用户身份自动启动服务?

编辑:我应该说我在这个实例中启动的进程要么是 Python 脚本,要么是 Java 程序。我宁愿不围绕它们编写本机包装器,所以不幸的是我无法像Black建议的那样调用setuid() 。

4

8 回答 8

68

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

我对 RedHat 不熟悉,但是daemon您已经在使用的实用程序(/etc/init.d/functions顺便说一句start-stop-daemon,在它已经是正确的了。

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

于 2008-12-27T13:53:34.423 回答
53

在查看了这里的所有建议之后,我发现了一些我希望对我所在职位的其他人有用的东西:

  1. 是正确的指向我回来/etc/init.d/functions:该 daemon功能已经允许您设置备用用户:

    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. 既不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为了解决and的这种行为runuser,我将初始化脚本更改为:

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

感谢你的帮助!

于 2008-12-27T19:59:21.503 回答
5

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

  1. 利用它的 root 权限(例如打开日志文件,创建 pid 文件)。
  2. 在启动期间的某个时间点删除其 root 权限。
于 2008-12-27T13:22:55.983 回答
3

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

  • init.d 脚本中的 Sudo 不好,因为它需要一个 tty(“sudo:抱歉,您必须有一个 tty 才能运行 sudo”)
  • 如果您正在对 Java 应用程序进行守护进程,您可能需要考虑 Java Service Wrapper(它提供了一种设置用户 ID 的机制)
  • 另一种选择可能是su --session-command=[cmd] [user]
于 2010-10-14T14:41:52.657 回答
3

在 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

原来的 pidfile 是/var/run/svnserve.pid. 守护进程没有启动,因为只有 root 可以写在那里。

 These all work:
/etc/init.d/svnserve start
/etc/init.d/svnserve stop
/etc/init.d/svnserve restart
于 2013-03-08T01:31:54.610 回答
2

需要注意的一些事项:

  • 正如您所提到的,如果您已经是目标用户,su 将提示您输入密码
  • 同样,如果您已经是目标用户(在某些操作系统上), setuid(2) 将失败
  • setuid(2) 不安装 /etc/limits.conf (Linux) 或 /etc/user_attr (Solaris) 中定义的权限或资源控制
  • 如果您使用 setgid(2)/setuid(2) 路线,请不要忘记调用 initgroups(3) - 更多信息请 点击此处

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

于 2009-08-05T18:00:47.370 回答
2

为什么不在 init 脚本中尝试以下操作:

setuid $USER application_name

它对我有用。

于 2012-02-17T10:05:39.180 回答
0

我需要将 Spring .jar 应用程序作为服务运行,并找到了一种以特定用户身份运行它的简单方法:

我将 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
于 2016-08-31T07:47:48.063 回答