我想了解如何systemd
启动服务,特别是以哪个用户身份启动服务,并且我想使用在我的 Linux PC 上运行的 Jenkins 作为示例。
我知道它init
是pid 1
Linux 中所有进程的母亲,在我的例子中pid 1
属于systemd
,我可以从运行中看到top
:
$ top
Tasks: 646 total, 1 running, 645 sleeping, 0 stopped, 0 zombie
%Cpu(s): 1.0 us, 0.6 sy, 0.0 ni, 97.0 id, 1.3 wa, 0.0 hi, 0.1 si, 0.0 st
MiB Mem : 257826.8 total, 198695.4 free, 28529.6 used, 30601.7 buff/cache
MiB Swap: 262012.0 total, 262012.0 free, 0.0 used. 227579.3 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1 root 20 0 171284 11196 7904 S 0.3 0.0 31:49.54 systemd
我天真地认为,因为systemd
以 root 身份运行root
,所以它运行的所有服务都将以 root 身份运行。
但我认为 Jenkins 正在admin
我的 PC 上运行。
我尝试用来systemctl
确定 Jenkins 正在以哪个用户身份运行,但我在标准输出中没有看到任何用户信息:
user@linux_box:~$ systemctl status jenkins
● jenkins.service - LSB: Start Jenkins at boot time
Loaded: loaded (/etc/init.d/jenkins; generated)
Active: active (exited) since Fri 2023-05-05 11:50:06 PDT; 3 days ago
Docs: man:systemd-sysv-generator(8)
Tasks: 0 (limit: 4915)
Memory: 0B
CGroup: /system.slice/jenkins.service
Warning: Journal has been rotated since unit was started. Log output is incomplete or unavailable.
user@linux_box:~$
...所以我尝试ps aux
:
user@linux_box:~$ ps aux | grep jenkins
admin 2042 0.0 0.0 14164 196 ? S May05 0:00 /usr/bin/daemon --name=admin --inherit --env=JENKINS_HOME=/home/admin/jenkins --output=/var/log/jenkins/jenkins.log --pidfile=/var/run/admin/admin.pid -- /usr/bin/java -Djava.awt.headless=true -jar /home/admin/jenkins/jenkins.war --webroot=/var/cache/jenkins/war --httpPort=8080
admin 2043 1.7 5.3 48146100 14118144 ? Sl May05 83:41 /usr/bin/java -Djava.awt.headless=true -jar /home/admin/jenkins/jenkins.war --webroot=/var/cache/jenkins/war --httpPort=8080
admin 29932 0.0 0.0 6204 892 pts/1 S+ 20:37 0:00 grep jenkins
...我认为最左边的专栏说詹金斯正在运行admin
,不是吗?
有人可以解释一下之间的关系吗systemd
有人可以解释一下, 用户它运行身份与服务运行的用户身份?如果答案能够将其与 Jenkins 在这台 Linux PC 上的具体情况联系起来,那就太好了。
答案1
systemd 用于运行系统服务的默认用户确实是root
,但当然可以使用该User
选项进行自定义。从man 5 systemd.exec
:
User=
,Group=
分别设置执行进程的 UNIX 用户或组。采用单个用户名、组名或数字 ID 作为参数。对于系统服务(由系统服务管理器运行的服务,即由 PID 1 管理的服务)和 root 用户的用户服务(由 root 的实例管理的服务
systemd --user
),默认为“root
”,但User=
可以用于指定不同的用户。 [...]
在您的 Jenkins 案例中,systemd 使用基于 sysv init script 的生成单元/etc/init.d/jenkins
,因此它不使用User
选项(生成的单元非常基本:systemd 如何使用 /etc/init.d 脚本?)。 init 脚本似乎正在调用/usr/bin/daemon
启动 Jenkins,并且从man 1 daemon
:
The preparatory tasks that daemon performs for other processes are:
[...]
• Change the process uid and gid if the --user option was supplied. Only root can use
this option. Note that the uid of daemon itself is changed, rather than just changing
the uid of the client process.
但是,输出中不存在此选项ps
,因此它可能使用其他方式来更改 UID。检查/etc/init.d/jenkins
脚本即可找到答案。
答案2
穆鲁的回答在大多数情况下是正确的,但我想添加有关--user
巴士的信息。
systemd
有两辆巴士: --system
和--user
。巴士--system
是默认的,穆鲁的答案适用于此。但您也可以在--user
公交车上启动服务。
单元文件位于/lib/systemd/user/
或中~/.config/systemd/user/
,这些文件将以调用该服务的用户身份启动。该WantedBy=default.target
服务将在用户登录时启动,或者WantedBy=graphical.target
该服务将在用户获得图形会话时启动。
用户总线不仅仅是User=
系统总线设置的替代方案。它提供了一种为每个用户创建服务实例的方法。例如,如果您想使用该用户的凭据将 sshfs 目录安装到主目录中的某个位置,则可以在用户总线上轻松完成此操作。
另一个特点是用户总线继承了用户的环境。这包括诸如DISPLAY
和 之类的东西XAUTHORITY
。这将帮助您在用户登录其桌面环境时启动 GUI 应用程序。相比之下,User=
系统总线上的设置将无法找到正确的显示(除非明确指定),并且通常会在 DE 启动之前尝试启动 GUI 应用程序。