mcpField
S
systemd-services

systemd-services

github.com/bagelhole云与 DevOps1.2k515 次安装23 周前更新
代码仓库

关于 systemd-services

systemd-services 是面向 Linux 系统管理员的 systemd 服务管理技能,说明如何配置服务、定时器和套接字激活,并涵盖依赖、资源限制与日志分析。

主要功能

  1. 01编写和管理服务单元
  2. 02配置 systemd 定时器
  3. 03设置套接字激活
  4. 04管理依赖与资源限制
  5. 05使用 journalctl 分析日志

适用场景

  1. 01将应用部署为后台服务
  2. 02用定时器替代 cron 任务
  3. 03排查服务启动或运行故障

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/bagelhole/devops-security-agent-skills --skill systemd-services

安装后在 Claude Code 中输入/systemd-services确认已加载。

详细介绍

Systemd 服务

创建、管理和监控 systemd 服务与定时器。涵盖单元文件编写、依赖管理、套接字激活、资源限制、journalctl 日志分析和生产环境加固。

适用场景

  • 将应用部署为受管理的后台服务
  • 用 systemd 定时器替代 cron 作业,以便更好地记录日志和控制依赖关系
  • 设置套接字激活,实现按需启动服务
  • 为服务配置资源限制(CPU、内存、I/O)
  • 调试服务启动失败和运行时崩溃
  • 管理服务依赖关系和启动顺序

前置条件

  • 运行 systemd 的 Linux 系统(大多数现代发行版均符合)
  • 创建系统级单元文件所需的 root 或 sudo 权限
  • 要作为服务运行的应用二进制文件或脚本
  • 了解应用的启动/停止生命周期

服务单元文件——完整示例

# /etc/systemd/system/myapp.service
[Unit]
Description=MyApp Production Server
Documentation=https://docs.example.com/myapp
After=network-online.target postgresql.service
Wants=network-online.target
Requires=postgresql.service

[Service]
Type=notify
User=myapp
Group=myapp
WorkingDirectory=/opt/myapp

# Environment configuration
EnvironmentFile=/etc/myapp/env
Environment=NODE_ENV=production
Environment=PORT=8080

# Execution
ExecStartPre=/opt/myapp/bin/migrate --check
ExecStart=/opt/myapp/bin/server --config /etc/myapp/config.yaml
ExecStartPost=/opt/myapp/bin/healthcheck.sh
ExecReload=/bin/kill -HUP $MAINPID
ExecStop=/opt/myapp/bin/graceful-stop.sh

# Restart behavior
Restart=on-failure
RestartSec=5
StartLimitIntervalSec=300
StartLimitBurst=5

# Timeouts
TimeoutStartSec=30
TimeoutStopSec=30
WatchdogSec=60

# Security hardening
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
ReadWritePaths=/var/lib/myapp /var/log/myapp
CapabilityBoundingSet=
AmbientCapabilities=

# Logging
StandardOutput=journal
StandardError=journal
SyslogIdentifier=myapp

[Install]
WantedBy=multi-user.target

服务管理命令

# Reload systemd after creating or modifying unit files
systemctl daemon-reload

# Start, stop, restart a service
systemctl start myapp
systemctl stop myapp
systemctl restart myapp

# Reload service configuration without restart (if supported)
systemctl reload myapp

# Enable service to start on boot
systemctl enable myapp

# Enable and start in one command
systemctl enable --now myapp

# Disable and stop
systemctl disable --now myapp

# Check service status
systemctl status myapp

# Check if a service is active, enabled, or failed
systemctl is-active myapp
systemctl is-enabled myapp
systemctl is-failed myapp

# List all running services
systemctl list-units --type=service --state=running

# List all failed services
systemctl list-units --type=service --state=failed

# Show all properties of a service
systemctl show myapp

# Show specific property values
systemctl show myapp -p MainPID,MemoryCurrent,CPUUsageNSec

# Mask a service (prevent it from being started at all)
systemctl mask myapp

# Unmask
systemctl unmask myapp

# Reset a failed service state
systemctl reset-failed myapp

定时器单元(替代 Cron)

定时器文件
# /etc/systemd/system/backup.timer
[Unit]
Description=Daily backup timer

[Timer]
# Run daily at 2:30 AM
OnCalendar=*-*-* 02:30:00
# If the system was off at the scheduled time, run when it boots
Persistent=true
# Add random delay up to 15 minutes to avoid thundering herd
RandomizedDelaySec=900
# Associate with a specific service (defaults to same name .service)
Unit=backup.service

[Install]
WantedBy=timers.target
对应的服务文件
# /etc/systemd/system/backup.service
[Unit]
Description=Daily backup job
After=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
User=backup
ExecStart=/usr/local/bin/run-backup.sh
StandardOutput=journal
StandardError=journal
定时器管理
# Common OnCalendar expressions:
# minutely, hourly, daily, weekly, monthly
# *-*-* 06:00:00       Daily at 6 AM
# Mon..Fri *-*-* 09:00 Weekdays at 9 AM
# *:0/15               Every 15 minutes

# Validate calendar expressions
systemd-analyze calendar "Mon..Fri *-*-* 09:00"

# List all active timers
systemctl list-timers --all

# Enable and start a timer
systemctl enable --now backup.timer

# Run the associated service immediately (for testing)
systemctl start backup.service

套接字激活

# /etc/systemd/system/myapp.socket
[Unit]
Description=MyApp Socket

[Socket]
ListenStream=8080
Accept=no
# Optionally bind to a specific IP
# ListenStream=10.0.1.10:8080

[Install]
WantedBy=sockets.target
# /etc/systemd/system/myapp.service
[Unit]
Description=MyApp Server
Requires=myapp.socket

[Service]
Type=notify
User=myapp
ExecStart=/opt/myapp/bin/server
# Service receives the socket file descriptor from systemd

[Install]
WantedBy=multi-user.target
# Enable the socket (service starts on first connection)
systemctl enable --now myapp.socket

# Check socket status
systemctl status myapp.socket

# List all listening sockets
systemctl list-sockets

依赖管理

# Key [Unit] directives for ordering and dependencies:
# After=            Start after these units (ordering only)
# Requires=         Hard dependency -- fail if this unit cannot start
# Wants=            Soft dependency -- try to start, don't fail if unavailable
# PartOf=           Stop this unit when the parent stops
# Conflicts=        Cannot run alongside this unit

# Visualize the dependency tree for a service
systemctl list-dependencies myapp

# Show reverse dependencies (who depends on this unit)
systemctl list-dependencies myapp --reverse

# Analyze boot order for a service
systemd-analyze critical-chain myapp.service

资源限制(cgroups v2)

# /etc/systemd/system/myapp.service.d/limits.conf
# (drop-in override file)
[Service]
# Memory limits
MemoryMax=1G
MemoryHigh=768M

# CPU limits
CPUQuota=200%          # Up to 2 full CPU cores
CPUWeight=100          # Relative weight (default=100)

# I/O limits
IOWeight=50
IOReadBandwidthMax=/dev/sda 100M
IOWriteBandwidthMax=/dev/sda 50M

# Process limits
LimitNOFILE=65535
LimitNPROC=4096
TasksMax=512

# Disable OOM killer (let the app handle it)
OOMPolicy=continue
# Apply drop-in overrides without editing the main unit file
mkdir -p /etc/systemd/system/myapp.service.d/

cat <<'EOF' > /etc/systemd/system/myapp.service.d/limits.conf
[Service]
MemoryMax=1G
CPUQuota=200%
EOF

systemctl daemon-reload
systemctl restart myapp

# View current resource usage for a service
systemctl status myapp                  # Shows Memory and CPU
systemd-cgtop                          # Real-time cgroup resource usage

# Edit a service's overrides interactively
systemctl edit myapp
# This creates a drop-in file automatically

Journalctl 日志分析

# Follow logs for a service in real time
journalctl -u myapp -f

# Show logs since last boot
journalctl -u myapp -b

# Show logs for a specific time range
journalctl -u myapp --since "2025-01-15 08:00" --until "2025-01-15 12:00"

# Show only error and above
journalctl -u myapp -p err

# Show the last 100 lines with full messages (no truncation)
journalctl -u myapp -n 100 --no-pager -l

# Show logs in JSON format (for parsing)
journalctl -u myapp -o json-pretty --no-pager | head -50

# Check journal disk usage and vacuum old entries
journalctl --disk-usage
journalctl --rotate
journalctl --vacuum-time=7d
journalctl --vacuum-size=500M

故障排查

症状诊断命令常见修复方法
服务无法启动systemctl status myapp、journalctl -u myapp -n 50检查 ExecStart 路径、权限和配置语法
服务不断重启journalctl -u myapp --since "5 min ago"检查 StartLimitBurst;在日志中查找崩溃信息
"Main process exited, code=exited, status=217"journalctl -u myapp单元文件中的用户或组不存在
"Failed to set up mount namespacing"检查 ProtectSystem/PrivateTmp内核版本过旧或 SELinux 阻止了操作;放宽相关指令
定时器未触发systemctl list-timers、systemctl status backup.timer确保定时器已启用;验证 OnCalendar 表达式
服务在依赖项之前启动检查 After= 和 Requires=添加 After=dependency.service 来指定顺序
被 OOM 杀死journalctl -k | grep oom、dmesg增大 MemoryMax 或优化应用内存使用
无法绑定到端口 80检查 AmbientCapabilities添加 CAP_NET_BIND_SERVICE 或使用更高的端口

相关技能

  • linux-administration -- 通用系统管理背景知识
  • performance-tuning -- 内核调优和资源优化
  • user-management -- 服务账户和权限
  • backup-recovery -- 使用 systemd 定时器安排备份

评论

支持 Markdown