当前位置:首页>Linux>每天学一个Linux命令系列(26):systemctl - systemd时代,别再service xxx start了

每天学一个Linux命令系列(26):systemctl - systemd时代,别再service xxx start了

  • 2026-09-06 00:05:28
每天学一个Linux命令系列(26):systemctl - systemd时代,别再service xxx start了
运
运维少年 · 科技观察

这个命令是干啥的

我刚入行那会儿,用的还是CentOS 6,管理服务全靠 service 和 chkconfig。那时候启动个nginx要敲 service nginx start,设置开机自启还得 chkconfig nginx on。后来换到CentOS 7,发现这些命令虽然还能用,但系统会提示你"推荐用systemctl"。现在主流发型版基本都切systemd了,Ubuntu 16.04+、CentOS 7+、Debian 8+、Fedora都是。

systemctl 是systemd的主管理工具。说白了,它就是管系统里那些"后台进程"(也就是服务)的。启动、停止、重启、看状态、设置开机自启,全用它。

基本用法(3分钟上手)

先来最常用的,查个服务状态:

# 查看nginx服务的运行状态
systemctl status nginx

输出大概长这样:

● nginx.service - A high performance web server and a reverse proxy server
   Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled)
   Active: active (running) since Mon 2026-06-22 08:30:00 CST; 1h ago

注意看几个关键字段:Loaded后面有没有enabled,表示开机自启有没有开;Active后面的active (running)才是真在跑。

常用命令就这几条:

# 启动服务
systemctl start nginx

# 停止服务
systemctl stop nginx

# 重启服务(先停再启)
systemctl restart nginx

# 重新加载配置(不中断服务,适合改配置后)
systemctl reload nginx

# 设置开机自启
systemctl enable nginx

# 关闭开机自启
systemctl disable nginx

# 查看所有正在运行的服务
systemctl list-units --type=service --state=running

# 查看所有服务,包括没启动的
systemctl list-units --type=service --all

有个参数我经常用:--failed,一键找出挂了哪些服务:

# 列出所有失败的服务
systemctl --failed

我巡检机器的时候,习惯先跑一下这个,比一个个查省事多了。

进阶骚操作

写自己的service单元文件

有时候我们自己编译安装的程序,也想像系统服务一样用systemctl管理。比如我自己编译了个nginx,想写个service文件。

路径在 /usr/lib/systemd/system/ 或者 /etc/systemd/system/(推荐放后者,优先级高)。

我写过一个简单的:

# 创建用户自定义的service文件,放在/etc目录下不会被系统更新覆盖
vim /etc/systemd/system/myapp.service

内容:

[Unit]
Description=我的自定义应用
After=network.target

[Service]
Type=simple
User=www
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/myapp --config /etc/myapp.conf
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

几个关键点:
- After=network.target:等网络好了再启动
- Restart=on-failure:挂了自己重启
- RestartSec=5:停5秒再重启,防止频繁刷日志

写完后重载配置:

# 重新加载所有service单元文件
systemctl daemon-reload

# 启动自定义服务
systemctl start myapp

# 设置开机自启
systemctl enable myapp

看依赖关系

服务之间有依赖,比如nginx依赖网络,mysql依赖磁盘挂载。可以用这个看:

# 查看nginx依赖了啥
systemctl list-dependencies nginx

反过来,想看哪些服务依赖某个target(相当于运行级别):

# 查看多用户模式依赖了哪些服务
systemctl list-dependencies multi-user.target

系统启动耗时分析

# 查看系统启动各阶段的耗时
systemd-analyze

# 查看每个服务的启动耗时
systemd-analyze blame

有次我发现服务器启动特别慢,一查 systemd-analyze blame,发现一个没用的服务占了30秒。直接disable掉,启动时间从2分钟降到20秒。

避坑指南

坑1:改了service文件没reload

我最开始犯过这个错:改了 /etc/systemd/system/xxx.service,然后直接 systemctl restart xxx。结果发现改的参数根本没生效。因为systemd缓存了配置。

正确做法:改完一定要先 systemctl daemon-reload,再restart。

坑2:enable了但机器重启没自动启动

这情况我踩过两次。排查方向:

1. 先看enable状态:systemctl is-enabled xxx,返回enabled才行
2. 看有没有依赖问题:systemctl list-dependencies xxx
3. 看启动日志:journalctl -u xxx,看看启动时出了啥错
4. 最坑的一种:服务启动得太早,依赖的网络或磁盘还没好,导致启动失败。这时要检查 After= 和 Wants= 配置对不对

坑3:Type配错

Type=simple 是默认的,意思是ExecStart指定的进程启动就算服务OK了。但有些程序会fork子进程(像传统的nginx),父进程启动完就退出。这时如果你用Type=simple,systemctl会以为服务挂了。

解决方案:如果是forking模式的服务,要写成 Type=forking,还要配 PIDFile= 指到pid文件位置。

坑4:kill模式导致数据丢失

默认情况下,systemctl stop是发SIGTERM,过一段时间没响应就SIGKILL。如果是数据库类服务,你这样粗暴杀可能丢数据。

我就在redis上吃过亏。解决方案是在service文件里加:

[Service]
TimeoutStopSec=30
KillMode=process

KillMode=process 只杀主进程,让子进程自己处理退出。当然这要看你具体服务支持不支持。

实战场景(重点!结合真实运维场景)

场景1:nginx挂了的自动恢复

有次公司线上nginx挂了,被报警系统发现才去重启,中间大概断了5分钟业务。后来我在service单元文件里加了自愈机制:

[Service]
Restart=always
RestartSec=3
StartLimitInterval=60
StartLimitBurst=3

意思是挂了就重启,但如果60秒内挂了3次以上,就不重启了(防止死循环)。配合monit或者supervisor,基本能做到秒级恢复。

场景2:批量巡检服务器

我写过一个脚本,批量连接几十台机器检查服务状态:

# 批量检查所有机器的nginx和mysql是否正常
for host in `cat server_list.txt`; do
    echo "=== $host ==="
    ssh $host "systemctl is-active nginx && echo 'nginx OK' || echo 'nginx 挂了'"
    ssh $host "systemctl is-active mysql && echo 'mysql OK' || echo 'mysql 挂了'"
done

systemctl is-active返回0或非0,很适合脚本里判断。

场景3:排查业务响应慢

有次业务反馈响应慢,我先用systemctl排查是不是服务自动重启了:

# 查看最近5次服务重启记录
journalctl -u myapp --since "1 hour ago" | grep -i "start\|stop\|fail"

发现服务在半小时内自动重启了3次。进一步看日志才发现是OOM killer把进程杀了,systemd又自动拉起来,导致服务间歇性不可用。

后来优化了内存配置,同时加上了RestartSec的延时,给监控系统足够的时间报警而不是让进程频繁重启。

场景4:单独看某个服务的启动日志

journalctl是systemd的日志神器,配合systemctl很好用:

# 查看某个服务的启动日志
journalctl -u nginx

# 只看最近10分钟
journalctl -u nginx --since "10 min ago"

# 实时追踪日志
journalctl -u nginx -f

今日作业

写一个自定义systemd service文件,启动一个Python HTTP服务(假设你的Python脚本路径是 /opt/myserver/app.py,它监听8080端口,使用 python3 /opt/myserver/app.py 启动,工作目录为 /opt/myserver),要求:
1. 网络就绪后才启动
2. 挂了自动重启,等待5秒
3. 开机自启
4. 给出完整的service文件内容和启动命令

写完service文件后,列出你需要的完整操作步骤(从创建文件到服务正常运行的每一步命令)。

E N D

运维少年 · 科技观察

最新文章

随机文章