systemd Unit文件结构与核心指令解析
systemd是现代Linux发行版(CentOS 7+、Ubuntu 16.04+、Debian 8+)的默认初始化系统,取代了传统的SysV init和Upstart。systemd通过Unit文件定义服务、挂载点、设备、定时器等资源,使用并行启动机制缩短系统启动时间。服务器运维工作中,正确编写systemd Unit文件是保证服务可靠运行的基础。
Unit文件存放在三个目录中:/etc/systemd/system(管理员自定义,优先级最高)、/usr/lib/systemd/system(软件包安装)、/run/systemd/system(运行时生成)。修改Unit文件后必须执行systemctl daemon-reload让systemd重新加载配置。
Service类型Unit配置实战
Service是最常用的Unit类型,定义一个需要长期运行的进程。以下是一个Go语言Web服务的完整Unit配置:
[Unit]
Description=Go Web Application Server
Documentation=https://example.com/docs
After=network-online.target postgresql.service
Wants=network-online.target
Requires=postgresql.service
[Service]
Type=simple
User=appuser
Group=appuser
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/bin/server --config /opt/myapp/config.yaml
ExecStop=/bin/kill -SIGTERM $MAINPID
ExecReload=/bin/kill -SIGHUP $MAINPID
Restart=on-failure
RestartSec=5s
StartLimitBurst=3
StartLimitIntervalSec=60
LimitNOFILE=65536
LimitNPROC=4096
MemoryMax=2G
CPUQuota=200%
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/opt/myapp/logs /opt/myapp/data
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
AmbientCapabilities=CAP_NET_BIND_SERVICE
StandardOutput=journal
StandardError=journal
SyslogIdentifier=myapp
[Install]
WantedBy=multi-user.target
Type=simple表示ExecStart启动的进程就是主进程,systemd会跟踪该进程的生命周期。如果服务需要fork子进程并在后台运行,应使用Type=forking并配合PIDFile指令。Restart=on-failure表示进程异常退出时自动重启,RestartSec控制重启间隔。
资源限制部分,MemoryMax设置内存使用上限,超出后systemd会发送SIGTERM终止进程。CPUQuota=200%允许服务使用最多2个CPU核心的算力。安全加固部分通过命名空间隔离限制服务的文件系统访问范围,ProtectSystem=strict使服务只能写入ReadWritePaths指定的目录。
Target依赖关系与启动顺序编排
systemd使用Target替代了传统的运行级别(runlevel)。After和Before控制启动顺序,Requires和Wants定义依赖关系:
# 查看当前启动目标
systemctl get-default
# 查看target包含的所有Unit
systemctl list-dependencies multi-user.target
# 切换启动目标
systemctl isolate multi-user.target
systemctl isolate graphical.target
Requires是强依赖,被依赖的服务启动失败时当前服务也不会启动。Wants是弱依赖,被依赖服务启动失败不影响当前服务。After/Before只控制顺序不定义依赖,如果A要在B之后启动且B失败时A也不启动,需要同时使用After=B和Requires=B。
Timer定时任务替代Cron配置
systemd Timer提供了比cron更精细的定时任务管理能力,支持单调时钟和实时时钟两种触发模式:
# /etc/systemd/system/backup.service
[Unit]
Description=Database Backup Task
[Service]
Type=oneshot
ExecStart=/opt/scripts/backup_db.sh
StandardOutput=journal
# /etc/systemd/system/backup.timer
[Unit]
Description=Run database backup daily
[Timer]
OnCalendar=*-*-* 02:30:00
Persistent=true
RandomizedDelaySec=300
[Install]
WantedBy=timers.target
systemctl enable backup.timer
systemctl start backup.timer
systemctl list-timers --all
OnCalendar使用日历表达式定义触发时间,语法比cron更直观。Persistent=true确保服务器关机期间错过的任务在下次启动时补执行。RandomizedDelaySec引入随机延迟,避免多个定时任务同时触发造成资源竞争。
systemd日志管理与journalctl查询
systemd统一通过journald收集日志,替代了传统的syslog。journalctl命令提供了强大的日志查询能力:
# 查看指定服务日志
journalctl -u myapp.service -f
# 按时间范围查询
journalctl --since "2026-08-21 09:00" --until "2026-08-21 12:00"
# 按优先级过滤
journalctl -p err -b
journalctl -p warning..err -b
# 按进程PID查询
journalctl _PID=12345
# 查看内核日志
journalctl -k
# 导出日志到文件
journalctl -u myapp.service --since today -o json > myapp_logs.json
# 日志磁盘占用管理
journalctl --disk-usage
journalctl --vacuum-size=500M
journalctl --vacuum-time=7d
journald默认将日志存储在/run/log/journal(易失性)或/var/log/journal(持久化)。在/etc/systemd/journald.conf中设置Storage=persistent启用持久化存储。日志轮转通过vacuum参数自动管理,避免磁盘被日志占满。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/linux-fu-wu-qi-systemd-fu-wu-guan-li-shi-zhan-unit-wen-jian/