linux:systemd之守护进程

环境:

  • debian13.7

参考:

《linux:debian13.7安装.net10》

一、systemd 介绍

systemd 是现代 Linux 系统中一套核心的系统和服务管理器,它作为 PID 1 运行,负责在内核启动后初始化用户空间,并持续管理系统的服务、设备、挂载点、网络、日志等。

1.1 systemd 不只是一个 init 程序,而是一个庞大的工具集,包含:

  • init 守护进程:PID 1,启动并管理所有用户空间进程。
  • 服务管理器:用声明式单元文件管理服务生命周期。
  • 日志系统:systemd-journald 收集内核和用户空间日志。
  • 登录管理:systemd-logind 管理用户会话、电源操作。
  • 网络管理:systemd-networkd、systemd-resolved。
  • 时间同步:systemd-timesyncd。
  • 定时任务:systemd.timer 替代 cron。
  • 设备管理:systemd-udevd 处理内核设备事件。

1.2 优点与争议

优点:

  • 启动快、依赖管理强、配置统一。
  • 日志集中、查询方便。
  • 资源控制、沙箱、安全特性丰富。
  • 活跃开发,主流发行版默认采用。

争议:

  • 违反 Unix"小而专"哲学,功能过于庞大。
  • 二进制日志不便于直接用文本工具处理。
  • 复杂性高,学习曲线陡。
  • 与部分发行版和社区理念冲突(如 Devuan、Artix 等衍生版专门去除 systemd)。

1.3 现状

主流发行版: Ubuntu、Debian、Fedora、RHEL、CentOS、Arch、openSUSE、Deepin、openEuler 等均默认使用 systemd。

非 systemd 发行版: Alpine(OpenRC)、Gentoo(可选 OpenRC)、Void(runit)、Devuan(sysvinit)、Artix(多种)等。

容器与嵌入式: systemd 也用于部分容器和嵌入式系统,但轻量级替代品(如 OpenRC、runit、s6)仍有优势。

二、配置一个简单的后台服务

抛开复杂的功能不谈,我们最常用的就是使用 systemd 配置一个后台服务,下面我们基于 .net10 的单文件配置一个 web 服务

2.1 准备 .net10 单文件 web服务器代码

文件: /root/Program.cs

csharp 复制代码
#:sdk Microsoft.NET.Sdk.Web

var builder = WebApplication.CreateBuilder();
var app = builder.Build();

// 启动时打印到日志(会进入 journald)
var aspnetEnv = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
var MY_VAR= Environment.GetEnvironmentVariable("MY_VAR");
Console.WriteLine($"启动环境: ASPNETCORE_ENVIRONMENT={aspnetEnv}, MY_VAR={MY_VAR}");

app.MapGet("/echo", () => $"echo {DateTime.Now}\n");

app.Run();

2.2 写 *.service 文件

新建文件 /etc/systemd/system/webecho.service

text 复制代码
[Unit]
Description=ASP.NET Core Echo Web Service (single-file)
After=network.target

[Service]
Type=simple
WorkingDirectory=/root
ExecStart=/usr/bin/dotnet run /root/Program.cs
Environment=ASPNETCORE_ENVIRONMENT=Test123
Environment="MY_VAR=hello world"
Restart=on-failure
RestartSec=5
User=root
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target

2.3 重载 systemd ,开启web服务

配置好后,重新加载 systemd 并启动服务:

shell 复制代码
systemctl daemon-reload  # 重载systemd
systemctl start webecho  # 运行服务
systemctl enable webecho # 开机自启动

查看日志:

shell 复制代码
journalctl -u webecho -f

整体效果如下:

然后,我们换个终端:

查看服务状态:systemctl status webecho.service

然后,访问下这个web服务:curl httpL//localhost:5000/echo

这样,一个简单的守护进程服务就配置好了,即使中间程序挂掉 linux 也会自动拉起,并且机器重启也会自动启动。

三、systemctl 管理命令

3.1 常见命令

shell 复制代码
# 针对一个服务
systemctl start webecho               # 启动
systemctl stop webecho                # 停止
systemctl restart webecho             # 重启
systemctl status webecho              # 查看服务状态

systemctl enable webecho              # 创建符号链接,让服务开机自启
systemctl disable webecho             # 删除符号链接,取消开机自启
systemctl mask webecho                # 把服务链接到 /dev/null,彻底禁止启动
systemctl unmask webecho              # 删除指向 /dev/null 的链接,恢复服务

systemctl cat webecho                 # 查看最终生效的单元文件
systemctl edit webecho                # 创建 override 片段并编辑
systemctl edit --full webecho         # 编辑完整单元文件
systemctl show webecho                # 显示所有属性
systemctl list-dependencies webecho   # 查看依赖关系
systemctl reset-failed webecho        # 清除失败状态

# 不针对具体服务
systemctl list-units --type=service       # 列出所有活动服务
systemctl list-unit-files --type=service  # 列出所有服务文件及启用状态
systemctl daemon-reload                   # 修改单元文件后必须重载

3.2 解释 enable/disable/mask/unmask

只针对 systemd unit(.service 服务文件) ,控制开机自启 和能否启动 ,不影响当前正在运行的服务(启停是 start/stop)

3.2.1. systemctl enable xxx.service

作用:设置开机自动启动

  • 本质:创建软链接,把 unit 加入开机目标(multi-user.target.wants 等)
  • ✅ 开机时自动拉起服务
  • ✅ 你依然可以手动 systemctl start xxx 启动 /stop 停止
  • ❗ enable ≠ 现在就运行服务,只是配置开机策略
shell 复制代码
systemctl enable myapp.service

3.2.2 systemctl disable xxx.service

作用:取消开机自动启动

  • 本质:删除 enable 创建的软链接
  • ❌ 开机不再自动启动
  • ✅ 仍然可以手动 start 启动服务
shell 复制代码
systemctl disable myapp.service

3.2.3 systemctl mask xxx.service

作用:彻底锁定、禁止启动服务(最强限制)

  • 本质:将服务链接到 /dev/null
  • ❌ 开机不会启动
  • ❌ 就算手动 systemctl start 也启动失败

用来防止意外启动,比如冲突服务、废弃服务

shell 复制代码
systemctl mask myapp.service

3.2.4 systemctl unmask xxx.service

作用:解除 mask 锁定

  • 删掉指向 /dev/null 的链接,恢复服务文件原始状态
  • unmask 之后,才能 start /enable
shell 复制代码
systemctl unmask myapp.service

3.2.5一句话对比表

命令 开机自启 能否手动 start 核心目的
enable ✅ 是 ✅ 可以 设置开机自启
disable ❌ 否 ✅ 可以 关闭开机自启
mask ❌ 否 ❌ 不可以 禁止任何方式启动
unmask 保持原有状态 ✅(解锁后) 解除 mask 锁定

3.2.6 重要组合逻辑

  1. mask 优先级 > enable。mask 之后,enable 失效,哪怕你 enable 了也无法启动
  2. mask 不会自动 disable;mask + enable 这种组合:开机不启动,手动也不能启动
  3. 查看状态:
shell 复制代码
# 查看是否开机自启 + 是否被mask
systemctl is-enabled myapp.service

返回值:

  • enabled:已 enable 开机自启
  • disabled:已关闭开机自启
  • masked:被 mask 锁定

3.3 如何新建一个后台服务

常用组合为:

shell 复制代码
systemctl daemon-reload  # 重载systemd
systemctl start webecho  # 运行服务
systemctl enable webecho # 开机自启动

3.4 如何删除一个后台服务

直接删除 .service 文件通常不够,因为 systemd 可能还在内存里保留着这个单元,而且如果服务正在运行,删文件并不会停止进程。正确做法是:先停止、禁用、解除屏蔽,再删文件,最后重载 systemd。

正确的删除步骤:

shell 复制代码
# 1. 停止正在运行的服务
systemctl stop webecho

# 2. 取消开机自启(删除 enable 生成的符号链接)
systemctl disable webecho

# 3. 如果之前 mask 过,先解除屏蔽
systemctl unmask webecho

# 4. 删除服务文件
rm -f /etc/systemd/system/webecho.service

# 5. 如果有 override 片段目录,也一并删除
rm -rf /etc/systemd/system/webecho.service.d

# 6. 重新加载 systemd 配置
systemctl daemon-reload

# 7. 清除失败状态(可选)
systemctl reset-failed webecho

四、查看服务日志

systemd 日志:journalctl(你部署 .net echo 服务直接用)

journald 是 systemd 的日志守护进程,日志二进制存储,用 journalctl 查询;systemctl status xxx 只会展示最近几行日志,详细日志靠 journalctl

4.1 最常用

shell 复制代码
# 查看 webecho 服务全部日志
journalctl -u webecho.service

# 实时跟踪日志(类似 tail -f,调试接口最常用)
journalctl -u webecho.service -f

# 只看本次开机后的 webecho 日志
journalctl -u webecho.service -b

# 看上次开机的日志(服务上次崩溃重启排查)
journalctl -u webecho.service -b -1

# 看最近20条日志
journalctl -u webecho.service -n 20

4.2 时间过滤 --since /--until

shell 复制代码
# 最近30分钟日志
journalctl -u webecho.service --since "30 min ago"

# 今天0点至今
journalctl -u webecho.service --since today

# 指定时间段
journalctl -u webecho.service --since "2026-10-02 07:00:00" --until "2026-10-02 09:00:00"

4.3 日志级别过滤 -p

级别:0 emerg、1 alert、2 crit、3 err、4 warn、5 notice、6 info、7 debug

shell 复制代码
# 只看错误及更严重(err、crit、alert、emerg)
journalctl -u webecho.service -p err

# 警告到错误区间
journalctl -u webecho.service -p warn..err

4.4 输出格式 -o

shell 复制代码
# json格式,方便程序解析
journalctl -u webecho.service -o json-pretty

# 精确时间戳
journalctl -u webecho.service -o short-iso

4.4 日志磁盘管理(journal 占用清理)

shell 复制代码
# 查看journal日志占用大小
journalctl --disk-usage

# 保留最近500M日志,旧的删除
journalctl --vacuum-size=500M

# 只保留最近7天日志
journalctl --vacuum-time=7d

五、其他问题

5.1 自己新建个服务,它必须以 *.service 后缀吗?

是的,而且必须调用 systemctl daemon-reload systemd 才会加载的内存

5.2 什么是 target?*.sevice 中的 WantedBy=multi-user.target 是什么意思?

在 systemd 中,target 是一组 unit 的集合,用来把系统启动或运行过程中的相关服务、挂载、套接字等组织在一起,形成一个同步点或阶段。它本身通常不执行实际工作,而是通过依赖关系把其他 unit "拉"起来。

target 与 service 的关系:

  • service 是"干活"的单元。
  • target 是"组织"的单元,把一组 service 聚合起来。
  • service 通过 WantedBy= 声明自己属于哪个 target。
  • target 可以嵌套依赖其他 target,形成启动链。

那么,service 如何和 target 关联起来呢?通过 service 文件的 WantedBy=multi-user.target 关联,可以通过下面查看依赖以及启动关系:systemd-analyze critical-chain

5.3 怎么控制服务依赖启动呢?

5.4 linux一般自带了哪些 service 呢?

相关推荐
用户4107192013251 小时前
VMware 虚拟机 Ubuntu 无法连接网络
linux
酬谢神明则必安2 小时前
git学习记录01
linux·git·学习
Ruiery2 小时前
Linux 6.6内核 CPU 深度解析(五):CPU 空闲状态机 cpuidle
linux·运维·服务器
XS0301062 小时前
Nginx 学习指南
运维·nginx
Lsetea2 小时前
OpenSSL verify报invalid CA certificate:basicConstraints与keyCertSign排查
运维·https·ssl证书·openssl·证书链
Data analyse4562 小时前
Cookie过期引发UV上涨的复核方法
服务器·前端·数据分析·uv
殷色玫瑰3 小时前
C语言编译和链接:从 .c到 .exe,程序到底经历了什么?
linux·c语言·c++·算法
菜鸟~noob2333 小时前
【太空电子战】午夜锤行动中的电磁静默区:可逆干扰的实战验证【含matlab代码】
linux·开发语言·matlab·电子战
程序猿老A3 小时前
云服务器怎么配置OSS?
运维·服务器