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
"一劳永逸" 的话,有是有的,而 "一劳永逸" 的事却极少