systemd服务管理深入实践从入门到自定义服务

本文系统讲解systemd的核心概念、服务管理、自定义Unit文件编写,以及常见问题排查。

前言

如果你还在用service xxx start或者写init.d脚本,是时候全面拥抱systemd了。

systemd是现代Linux的标准初始化系统,管理着系统启动、服务运行、日志记录等核心功能。

今天来彻底搞懂它。


一、systemd基础

1.1 什么是systemd

systemd是Linux系统的初始化系统和服务管理器,取代了传统的SysVinit。

主要功能:

  • 系统初始化
  • 服务管理
  • 日志管理(journald)
  • 定时任务(timer)
  • 设备管理

1.2 核心概念:Unit

systemd管理的基本单位是Unit,有多种类型:

类型 后缀 说明
Service .service 服务进程
Socket .socket 套接字激活
Timer .timer 定时器(替代cron)
Mount .mount 挂载点
Target .target 启动目标(类似runlevel)
Path .path 路径监控

1.3 Unit文件位置

复制代码
/etc/systemd/system/        # 系统管理员创建的(优先级最高)
/run/systemd/system/        # 运行时创建的
/lib/systemd/system/        # 软件包安装的
/usr/lib/systemd/system/    # 发行版提供的

优先级:/etc > /run > /lib


二、常用命令

2.1 服务管理

bash 复制代码
# 启动服务
systemctl start nginx

# 停止服务
systemctl stop nginx

# 重启服务
systemctl restart nginx

# 重载配置(不重启进程)
systemctl reload nginx

# 查看状态
systemctl status nginx

# 开机自启
systemctl enable nginx

# 取消开机自启
systemctl disable nginx

# 开机自启并立即启动
systemctl enable --now nginx

2.2 查看服务

bash 复制代码
# 列出所有服务
systemctl list-units --type=service

# 列出启用的服务
systemctl list-unit-files --type=service --state=enabled

# 列出失败的服务
systemctl list-units --failed

# 查看服务依赖
systemctl list-dependencies nginx

# 查看服务属性
systemctl show nginx

2.3 系统管理

bash 复制代码
# 重启系统
systemctl reboot

# 关机
systemctl poweroff

# 进入救援模式
systemctl rescue

# 重载systemd配置
systemctl daemon-reload

三、编写Service Unit

3.1 基本结构

ini 复制代码
# /etc/systemd/system/myapp.service

[Unit]
Description=My Application
Documentation=https://example.com/docs
After=network.target
Wants=network-online.target

[Service]
Type=simple
User=www-data
Group=www-data
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/bin/start.sh
ExecStop=/opt/myapp/bin/stop.sh
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

3.2 [Unit]段详解

ini 复制代码
[Unit]
# 描述
Description=My Web Application

# 文档链接
Documentation=man:nginx(8)
Documentation=https://nginx.org/

# 启动顺序(在...之后)
After=network.target mysql.service

# 依赖(需要...存在)
Requires=mysql.service

# 弱依赖(希望...存在,但不强制)
Wants=redis.service

# 冲突(不能和...同时运行)
Conflicts=apache2.service

3.3 [Service]段详解

ini 复制代码
[Service]
# 服务类型
Type=simple          # 默认,ExecStart进程就是主进程
Type=forking         # 父进程退出,子进程成为主进程(传统daemon)
Type=oneshot         # 一次性任务
Type=notify          # 服务启动完成后通知systemd
Type=idle            # 其他任务执行完后再启动

# 运行用户/组
User=www-data
Group=www-data

# 工作目录
WorkingDirectory=/opt/myapp

# 启动命令
ExecStart=/opt/myapp/start.sh

# 启动前执行
ExecStartPre=/opt/myapp/check.sh

# 启动后执行
ExecStartPost=/opt/myapp/notify.sh

# 停止命令
ExecStop=/opt/myapp/stop.sh

# 重载命令
ExecReload=/bin/kill -HUP $MAINPID

# 重启策略
Restart=no              # 不重启
Restart=always          # 总是重启
Restart=on-success      # 正常退出时重启
Restart=on-failure      # 异常退出时重启
Restart=on-abnormal     # 信号终止时重启

# 重启间隔
RestartSec=5

# 环境变量
Environment=NODE_ENV=production
Environment=PORT=3000
EnvironmentFile=/etc/myapp/env

# 资源限制
LimitNOFILE=65535
LimitNPROC=4096

3.4 [Install]段详解

ini 复制代码
[Install]
# 被哪个target启用(开机自启)
WantedBy=multi-user.target    # 多用户模式(常用)
WantedBy=graphical.target     # 图形界面模式

# 别名
Alias=myapp.service

四、实战案例

4.1 Node.js应用

ini 复制代码
# /etc/systemd/system/node-app.service

[Unit]
Description=Node.js Application
After=network.target

[Service]
Type=simple
User=node
WorkingDirectory=/home/node/app
ExecStart=/usr/bin/node /home/node/app/server.js
Environment=NODE_ENV=production
Environment=PORT=3000
Restart=on-failure
RestartSec=10

# 日志
StandardOutput=journal
StandardError=journal
SyslogIdentifier=node-app

[Install]
WantedBy=multi-user.target

4.2 Java应用

ini 复制代码
# /etc/systemd/system/java-app.service

[Unit]
Description=Java Spring Boot Application
After=network.target

[Service]
Type=simple
User=java
WorkingDirectory=/opt/java-app
ExecStart=/usr/bin/java -jar /opt/java-app/app.jar
ExecStop=/bin/kill -SIGTERM $MAINPID

# JVM参数
Environment=JAVA_OPTS=-Xms512m -Xmx1024m

Restart=on-failure
RestartSec=10
SuccessExitStatus=143

[Install]
WantedBy=multi-user.target

4.3 Python应用

ini 复制代码
# /etc/systemd/system/python-app.service

[Unit]
Description=Python Flask Application
After=network.target

[Service]
Type=simple
User=www-data
WorkingDirectory=/opt/flask-app
ExecStart=/opt/flask-app/venv/bin/gunicorn -w 4 -b 0.0.0.0:8000 app:app
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure

[Install]
WantedBy=multi-user.target

4.4 组网客户端自启

如果使用组网软件(如星空组网),可以配置开机自启:

ini 复制代码
# /etc/systemd/system/xingkong.service

[Unit]
Description=Xingkong Network Client
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
ExecStart=/opt/xingkong/client
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target
bash 复制代码
# 启用
systemctl daemon-reload
systemctl enable xingkong
systemctl start xingkong

这样每次开机都会自动连接组网,方便远程管理。


五、Timer定时任务

5.1 Timer vs Cron

特性 Timer Cron
日志 完整的journal日志 需要自己重定向
依赖 可以依赖其他服务
随机延迟 支持 不支持
错过执行 可以配置补执行

5.2 Timer示例

ini 复制代码
# /etc/systemd/system/backup.service
[Unit]
Description=Daily Backup

[Service]
Type=oneshot
ExecStart=/opt/scripts/backup.sh
ini 复制代码
# /etc/systemd/system/backup.timer
[Unit]
Description=Daily Backup Timer

[Timer]
# 每天凌晨3点
OnCalendar=*-*-* 03:00:00

# 随机延迟0-30分钟(避免同时执行)
RandomizedDelaySec=1800

# 错过的执行在下次启动时补上
Persistent=true

[Install]
WantedBy=timers.target
bash 复制代码
# 启用
systemctl enable backup.timer
systemctl start backup.timer

# 查看定时器
systemctl list-timers

5.3 OnCalendar语法

ini 复制代码
# 每分钟
OnCalendar=*-*-* *:*:00

# 每小时
OnCalendar=*-*-* *:00:00
OnCalendar=hourly

# 每天凌晨
OnCalendar=*-*-* 00:00:00
OnCalendar=daily

# 每周一
OnCalendar=Mon *-*-* 00:00:00
OnCalendar=weekly

# 每月1号
OnCalendar=*-*-01 00:00:00
OnCalendar=monthly

# 工作日每天9点
OnCalendar=Mon..Fri *-*-* 09:00:00

六、日志管理

6.1 journalctl基础

bash 复制代码
# 查看所有日志
journalctl

# 查看指定服务日志
journalctl -u nginx

# 实时跟踪
journalctl -u nginx -f

# 最近100行
journalctl -u nginx -n 100

# 今天的日志
journalctl -u nginx --since today

# 指定时间范围
journalctl -u nginx --since "2024-01-01" --until "2024-01-02"

# 内核日志
journalctl -k

# 系统启动日志
journalctl -b

6.2 日志级别

bash 复制代码
# 只看错误
journalctl -u nginx -p err

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

6.3 日志清理

bash 复制代码
# 查看日志占用空间
journalctl --disk-usage

# 保留最近1周
journalctl --vacuum-time=1week

# 限制大小
journalctl --vacuum-size=500M

# 配置文件
# /etc/systemd/journald.conf
[Journal]
SystemMaxUse=500M
MaxRetentionSec=1week

七、故障排查

7.1 服务启动失败

bash 复制代码
# 查看详细状态
systemctl status myapp -l

# 查看完整日志
journalctl -u myapp -n 50

# 常见问题:
# 1. 权限问题:检查User/Group
# 2. 路径问题:检查WorkingDirectory/ExecStart
# 3. 依赖问题:检查After/Requires

7.2 检查Unit文件语法

bash 复制代码
# 验证语法
systemd-analyze verify /etc/systemd/system/myapp.service

# 查看服务属性
systemctl show myapp

# 查看启动时间
systemd-analyze blame

7.3 重载配置

bash 复制代码
# 修改Unit文件后必须执行
systemctl daemon-reload

# 然后重启服务
systemctl restart myapp

八、高级特性

8.1 资源限制

ini 复制代码
[Service]
# CPU限制(100%=1核)
CPUQuota=50%

# 内存限制
MemoryMax=512M
MemoryHigh=400M

# IO限制
IOWeight=100
IOReadBandwidthMax=/dev/sda 10M

# 进程数限制
TasksMax=100

8.2 安全隔离

ini 复制代码
[Service]
# 只读文件系统
ProtectSystem=strict
ReadWritePaths=/var/lib/myapp

# 私有/tmp
PrivateTmp=true

# 禁止网络
PrivateNetwork=true

# 禁止提权
NoNewPrivileges=true

# 能力限制
CapabilityBoundingSet=CAP_NET_BIND_SERVICE

8.3 Socket激活

ini 复制代码
# /etc/systemd/system/myapp.socket
[Unit]
Description=MyApp Socket

[Socket]
ListenStream=8080
Accept=false

[Install]
WantedBy=sockets.target

启用后,服务只在有连接时才启动,节省资源。


九、总结

systemd服务管理要点:

  1. 基本操作:start/stop/restart/enable/status
  2. Unit文件:[Unit]/[Service]/[Install]三段结构
  3. 服务类型:simple最常用,forking用于传统daemon
  4. 重启策略:on-failure适合大多数场景
  5. 定时任务:Timer替代cron,功能更强
  6. 日志管理:journalctl查看,定期清理

快速模板:

ini 复制代码
[Unit]
Description=XXX
After=network.target

[Service]
Type=simple
User=xxx
WorkingDirectory=/path/to/app
ExecStart=/path/to/app/start
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

参考资料

  1. systemd官方文档:https://systemd.io/
  2. Arch Wiki - systemd:https://wiki.archlinux.org/title/Systemd
  3. man systemd.service

💡 建议:把常用的服务都改成systemd管理,比写脚本放/etc/rc.local优雅多了。

相关推荐
June`3 小时前
SSH连接原理与守护进程实战
linux·运维·服务器
JH灰色3 小时前
【大模型】-LangChain--stream流式同步异步
服务器·前端·langchain
专业开发者3 小时前
近距离检测功能亮点
网络·tcp/ip·安全
水天需0103 小时前
Grep 例程大全
linux
杼蛘3 小时前
XXL-Job工具使用操作记录
linux·windows·python·jdk·kettle·xxl-job
CQ_YM3 小时前
Linux进程基础
linux·服务器·进程
_OP_CHEN4 小时前
【Git原理与使用】(五)Git 多人协作:从分支协作到冲突解决,团队开发效率翻倍秘籍
linux·运维·git·团队开发·运维开发·企业级组件·git多人协作
添砖java‘’4 小时前
常见的进程间通信方式详解
linux·c++·操作系统·信息与通信·进程通信