代码之家  ›  专栏  ›  技术社区  ›  James Brady

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

  •  134
  • James Brady  · 技术社区  · 17 年前

    服务默认启动为 root 在开机时放在我的行李盒上。如果我记得正确的话,其他使用init脚本的linux发行版也一样。 /etc/init.d .

    您认为以我选择的(静态)用户身份运行进程的最佳方法是什么?

    我唯一能想到的方法是使用如下的东西:

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

    但这看起来有点乱…

    是否隐藏了一些魔力,提供了一种简单的机制,可以像其他非根用户一样自动启动服务?

    编辑: 我应该说,我在这个例子中开始的过程要么是Python脚本,要么是Java程序。我不想在它们周围写一个本地包装,所以很遗憾我无法调用 setuid() 作为 Black 建议。

    8 回复  |  直到 9 年前
        1
  •  67
  •   user3850    17 年前

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

    我不熟悉红帽,但是 daemon 已在使用的实用程序(在 /etc/init.d/functions (顺便说一句),到处都提到 开始-停止守护进程 ,因此它也可以更改程序的uid,或者您的方式已经是正确的。

    如果你看看周围的网络,有几个现成的包装,你可以使用。有些甚至可能已经用红帽包装。看一看 daemonize 例如。

        2
  •  53
  •   Community Mohan Dere    8 年前

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

    1. hop 把我指回来是对的 在 /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内部。

    3. 既不 su 也不 运行用户 优雅地处理案件 要求以用户身份运行命令 已经是。例如。:

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

    解决 运行用户 ,我已将初始化脚本更改为如下内容:

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

    谢谢大家的帮助!

        3
  •  5
  •   andyg0808 Lou Franco    9 年前
    • 一些守护进程(例如apache)通过调用 setuid()
    • 你可以用 setuid-file flag 以不同的用户身份运行进程。
    • 当然,您提到的解决方案也有效。

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

    1. 利用其根权限(例如,打开日志文件、创建PID文件)。
    2. 在启动过程中的某一点删除其根权限。
        4
  •  3
  •   pdeschen    15 年前

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

    • in it.d脚本中的sudo不好,因为它需要tty(“sudo:对不起,必须有tty才能运行sudo”)。
    • 如果您正在对Java应用程序进行后台编程,那么您可能需要考虑Java服务包装器(它提供了一种设置用户ID的机制)。
    • 另一种选择可能是 su--session命令=[cmd][user]
        5
  •  3
  •   fmendez    12 年前

    在用于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 . 守护进程没有启动,因为只有根可以在那里写入。

     These all work:
    /etc/init.d/svnserve start
    /etc/init.d/svnserve stop
    /etc/init.d/svnserve restart
    
        6
  •  2
  •   claymation    16 年前

    注意以下几点:

    • 正如您提到的,如果您已经是目标用户,su将提示输入密码。
    • 同样,如果您已经是目标用户(在某些OSS上),setuid(2)也会失败。
    • setuid(2)不安装/etc/limits.conf(linux)或/etc/user-attr(solaris)中定义的特权或资源控件
    • 如果你走setgid(2)/setuid(2)路线,不要忘记调用initgroups(3)——更多关于这个的信息 here

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

        7
  •  2
  •   cyberJar    13 年前

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

    setuid $USER application_name
    

    这对我很有用。

        8
  •  0
  •   Somaiah Kumbera    9 年前

    我需要运行一个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
    
    推荐文章