systemd详解

一、systemctl命令详解

systemctl是systemd的核心命令,基本语法是:systemctl [选项] [命令] [服务名]

启动服务最常用的就是start命令:
systemctl start nginx
停止服务用stop: systemctl stop nginx
重启服务用restart,这个命令会先停止服务再启动: systemctl restart nginx
还有一个reload命令,这个比较有意思,它不会停止服务,而是重新加载配置文件。不过不是所有服务都支持reload,比如nginx支持,但有些服务就不支持。 systemctl reload nginx
有时候你不确定服务是否支持reload,可以用reload
-or-restart,如果支持reload就reload,不支持就restart: systemctl reload-or-restart nginx
查看服务状态 status命令是我用得最多的,它能显示服务的详细状态信息: systemctl status nginx 输出信息包括服务是否运行、进程ID、最近的日志等等。有时候服务启动失败,通过status命令基本就能看出问题所在。
如果只想知道服务是否在运行,可以用is
-active: systemctl is-active nginx
检查服务是否启用(开机自启动)用is
-enabled: systemctl is-enabled nginx
开机自启动管理 这个功能特别重要,生产环境的服务基本都需要开机自启动。 启用开机自启动: systemctl enable nginx
禁用开机自启动: systemctl disable nginx
有时候你想启用服务的同时立即启动它,可以用enable
--now: systemctl enable --now nginx
相应的,disable
--now会禁用并停止服务: systemctl disable --now nginx
列出服务 list
-units命令可以列出所有活动的单元: systemctl list-units
如果只想看服务类型的单元: systemctl list
-units --type=service
list
-unit-files可以列出所有单元文件及其状态: systemctl list-unit-files --type=service 这个命令特别有用,你可以看到哪些服务是enabled、disabled或者static状态。

二、systemd单元文件详解

要深入理解systemd,就必须了解单元文件(unit file)。每个服务都有对应的单元文件,定义了服务的启动方式、依赖关系等信息。

单元文件通常位于以下目录:

/usr/lib/systemd/system/ - 系统默认的单元文件
/etc/systemd/system/ - 管理员创建或修改的单元文件
/run/systemd/system/ - 运行时创建的单元文件
优先级是从低到高的,也就是说/etc/systemd/system/下的文件会覆盖/usr/lib/systemd/system/下的同名文件。

1.单元文件结构

一个典型的service单元文件包含三个主要部分:

[Unit]部分定义了单元的基本信息和依赖关系:

[Unit]
Description=The nginx HTTP and reverse proxy server
After=network.target remote-fs.target nss-lookup.target

Description就是服务的描述信息,After指定了启动顺序,表示这个服务要在network.target等启动之后再启动。

[Service]部分定义了服务的具体行为:

[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx
ExecReload=/bin/kill -s HUP $MAINPID
KillSignal=SIGQUIT
TimeoutStopSec=5
KillMode=process
PrivateTmp=true

Type=forking 定义服务为 forking 类型,即主进程启动后会 fork 出子进程然后退出,子进程继续运行; PIDFile=/run/nginx.pid 指定 PID 文件位置,让 systemd 能够跟踪主进程; ExecStartPre=/usr/sbin/nginx -t 在启动前先测试配置文件语法,防止配置错误导致启动失败; ExecStart=/usr/sbin/nginx 定义实际的服务启动命令; ExecReload=/bin/kill -s HUP $MAINPID 通过向主进程发送 HUP 信号实现配置重载,不中断现有连接; KillSignal=SIGQUIT 设置停止服务时使用 SIGQUIT 信号进行优雅关闭; TimeoutStopSec=5 设置 5 秒的停止超时时间,超时后强制杀死进程; KillMode=process 指定只杀死主进程而不影响子进程; PrivateTmp=true 为服务创建独立的临时目录以提高安全性和隔离性。整体配置确保了 Nginx 服务能够在 systemd 环境中稳定、安全、可控地运行,支持优雅的启动、重载和关闭操作。

[Install]部分定义了安装信息,主要是开机自启动相关:

[Install]
WantedBy=multi-user.target
WantedBy指定了这个服务被哪个target需要,multi
-user.target相当于传统的运行级别3。

2.创建自定义服务

有时候我们需要为自己的应用创建systemd服务。比如我之前写了一个监控脚本,需要作为服务运行。

首先创建单元文件/etc/systemd/system/myapp.service:
[Unit]
Description=My Application
After=network.target

[Service]
Type=simple
User=myapp
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/bin/myapp
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target

然后重载systemd配置: systemctl daemon
-reload
启用并启动服务: systemctl enable
--now myapp

三、日志管理与故障排查

systemd集成了journald日志系统,这让服务的日志管理变得更加统一和方便。

 journalctl命令使用
查看特定服务的日志:
journalctl -u nginx
查看实时日志(类似tail
-f): journalctl -u nginx -f
查看最近的日志: journalctl
-u nginx -n 50

按时间范围查看日志: journalctl -u nginx --since "2024-01-01" --until "2024-01-02"

查看启动相关的日志: journalctl -u nginx --since today

四、高级功能和技巧

1.Target管理

systemd使用target来替代传统的运行级别概念。常用的target有:
• graphical.target - 图形界面模式
• multi-user.target - 多用户命令行模式
• rescue.target - 救援模式
查看当前target: systemctl
get-default
设置默认target: systemctl set-default multi-user.target
切换到指定target: systemctl isolate rescue.target

2.服务依赖管理

systemd的依赖管理比SysV强大很多。主要的依赖类型有:
• Requires - 强依赖,依赖的服务失败则本服务也失败
• Wants - 弱依赖,依赖的服务失败不影响本服务
• After/Before - 启动顺序依赖
查看服务的依赖关系: systemctl list
-dependencies nginx 这个命令会显示服务的依赖树,对理解服务启动顺序很有帮助。

3.资源控制

systemd支持cgroup资源控制,可以限制服务的CPU、内存等资源使用。
在单元文件的[Service]部分添加:
[Service]
CPUQuota=50%
MemoryLimit=1G
这样就限制了服务最多使用50
%的CPU和1GB内存。

4.定时任务

systemd还可以替代cron来执行定时任务,通过timer单元实现。
创建一个service单元文件/etc/systemd/system/backup.service:

[Unit]
Description=Backup Script
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
然后创建对应的timer单元文件
/etc/systemd/system/backup.timer: [Unit] Description=Run backup daily Requires=backup.service [Timer] OnCalendar=daily Persistent=true [Install] WantedBy=timers.target
启用定时器: systemctl enable
--now backup.timer
查看所有定时器状态: systemctl list
-timers 相比cron,systemd timer的优势是可以更好地与系统集成,支持更复杂的时间表达式,还能处理系统休眠等情况。

五、性能监控和优化

1.服务启动时间分析

systemd提供了很好的启动时间分析工具。查看系统启动时间:
systemd-analyze
查看详细的启动时间分解: systemd
-analyze blame
这个命令会列出每个服务的启动时间,按时间长短排序。如果系统启动慢,通过这个命令基本就能找到罪魁祸首。
生成启动过程的SVG图表: systemd
-analyze plot > boot.svg 这个图表可以直观地看到各个服务的启动时间线和依赖关系。

2.服务状态监控

除了基本的status命令,还可以用show命令查看服务的详细属性:
systemctl show nginx
这会输出大量信息,包括内存使用、CPU时间、文件描述符数量等等。

如果只想看特定属性:
systemctl show nginx -p MainPID,LoadState,ActiveState

3.批量操作

有时候需要对多个服务进行批量操作。比如重启所有web相关的服务:
systemctl restart nginx php-fpm mysql
或者使用通配符: systemctl restart
'php*' 不过通配符要小心使用,特别是在生产环境,避免误操作。

六、实际应用场景和案例

1.开机自启动失效

有时候明明设置了enable,但重启后服务还是没有自动启动。
检查服务是否真的被启用:
systemctl is-enabled nginx
检查target依赖关系: systemctl list
-dependencies multi-user.target | grep nginx 有时候是因为服务的依赖没有满足,导致启动失败。这种情况下需要检查依赖的服务是否正常。

2.服务假死问题

有些服务进程还在,但实际上已经不响应请求了。这种情况systemctl status可能显示正常,但服务实际不可用。
可以通过健康检查脚本来检测:
curl -f http://localhost/ || systemctl restart nginx

或者在systemd单元文件中配置健康检查: [Service] ExecStartPost=/bin/sleep 5 ExecStartPost=/usr/bin/curl -f http://localhost/

3.日志轮转问题

systemd journal的日志可能会占用大量磁盘空间。可以配置日志轮转:
编辑/etc/systemd/journald.conf:
SystemMaxUse=1G
SystemMaxFileSize=100M
MaxRetentionSec=1month
然后重启journald: systemctl restart systemd
-journald
手动清理旧日志: journalctl
--vacuum-time=7d journalctl --vacuum-size=500M

七、最佳实践和建议

1.服务配置方面

• 尽量使用系统包管理器安装的软件,它们通常已经包含了合适的systemd单元文件
• 自定义服务的单元文件放在/etc/systemd/system/目录下
• 修改单元文件后记得执行systemctl daemon-reload
• 合理设置服务的重启策略,生产环境建议使用Restart=always

2.监控和维护方面

• 定期检查服务状态,可以写脚本自动化
• 关注系统日志,特别是启动失败的服务
• 定期清理journal日志,避免占用过多磁盘空间
• 备份重要的配置文件和单元文件

3.安全方面

• 服务尽量不要以root用户运行
• 使用systemd的安全特性,比如PrivateTmp、NoNewPrivileges等
• 定期更新系统和软件包
• 监控异常的服务重启和失败

4.性能优化方面

• 使用systemd-analyze分析启动性能
• 禁用不必要的服务
• 合理配置服务的资源限制
• 优化服务的依赖关系

抄自于:https://mp.weixin.qq.com/s/Xh2WncSmwT2MUgyZkweaKA

 

posted @ 2025-08-19 19:37  百衲本  阅读(89)  评论(0)    收藏  举报
cnblogs_post_body { color: black; font: 0.875em/1.5em "微软雅黑" , "PTSans" , "Arial" ,sans-serif; font-size: 15px; } cnblogs_post_body h1 { text-align:center; background: #333366; border-radius: 6px 6px 6px 6px; box-shadow: 0 0 0 1px #5F5A4B, 1px 1px 6px 1px rgba(10, 10, 0, 0.5); color: #FFFFFF; font-family: "微软雅黑" , "宋体" , "黑体" ,Arial; font-size: 23px; font-weight: bold; height: 25px; line-height: 25px; margin: 18px 0 !important; padding: 8px 0 5px 5px; text-shadow: 2px 2px 3px #222222; } cnblogs_post_body h2 { text-align:center; background: #006699; border-radius: 6px 6px 6px 6px; box-shadow: 0 0 0 1px #5F5A4B, 1px 1px 6px 1px rgba(10, 10, 0, 0.5); color: #FFFFFF; font-family: "微软雅黑" , "宋体" , "黑体" ,Arial; font-size: 20px; font-weight: bold; height: 25px; line-height: 25px; margin: 18px 0 !important; padding: 8px 0 5px 5px; text-shadow: 2px 2px 3px #222222; } cnblogs_post_body h3 { background: #2B6695; border-radius: 6px 6px 6px 6px; box-shadow: 0 0 0 1px #5F5A4B, 1px 1px 6px 1px rgba(10, 10, 0, 0.5); color: #FFFFFF; font-family: "微软雅黑" , "宋体" , "黑体" ,Arial; font-size: 18px; font-weight: bold; height: 25px; line-height: 25px; margin: 18px 0 !important; padding: 8px 0 5px 5px; text-shadow: 2px 2px 3px #222222; } 回到顶部 博客侧边栏 回到顶部 页首代码 回到顶部 页脚代码