Linux 系统服务与 systemd 入门:开机自启、日志查看一次讲清
Linux 系统服务与 systemd 入门:开机自启、日志查看一次讲清
很多新手第一次在云服务器上部署程序都会遇到同一个问题:程序在终端里跑得好好的,一关终端就停了;服务器一重启,服务又得手动再起一遍。解决这个问题的标准办法,就是把程序交给 systemd 管理。本文从零讲清 systemd 的基本概念与常用操作,读完你就能自己写一个开机自启的服务。
一、systemd 是什么
systemd 是现代 Linux 发行版默认的系统与服务管理器,负责系统启动、服务启停、开机自启、日志收集等工作。你可以把它理解成服务器的“管家”:系统启动时它按依赖关系依次拉起各个服务;服务崩溃时它可以按策略自动重启;你也可以随时查询某个服务的状态和日志。
判断系统是否使用 systemd 很简单,执行 systemctl --version,能输出版本号就说明在用。Ubuntu 16.04 之后、CentOS 7 之后、Debian 8 之后的版本默认都使用 systemd。
二、核心概念:unit 与 service
systemd 管理的对象叫 unit,类型有很多,常见的有:
- service:后台服务,如 Nginx、MySQL、你自己写的程序;
- timer:定时任务,可以替代部分 cron 场景;
- socket:套接字激活;
- target:启动目标,类似旧的运行级别,如 multi-user.target 对应多用户命令行模式。
我们日常打交道最多的就是 service。一个 service 由一个 .service 文件描述,系统自带的文件放在 /lib/systemd/system/ 或 /usr/lib/systemd/system/,自己写的放在 /etc/systemd/system/,后者优先级更高、也不会被软件包升级覆盖。
三、一个最简单的服务文件
假设你要让一个 Python 脚本开机自启,脚本在 /opt/hello/app.py,用 python3 运行。新建 /etc/systemd/system/hello.service:
[Unit]
Description=My Hello Service
After=network.target
[Service]
Type=simple
User=www-data
WorkingDirectory=/opt/hello
ExecStart=/usr/bin/python3 /opt/hello/app.py
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
逐段解释:[Unit] 写描述和启动顺序,After=network.target 表示等网络就绪后再启动;[Service] 是核心,Type=simple 表示前台运行的普通进程,ExecStart 是启动命令(必须写绝对路径),Restart=on-failure 表示异常退出时自动重启,RestartSec=5 是重启前等待 5 秒;[Install] 的 WantedBy=multi-user.target 表示这个服务归属多用户目标,开机自启就靠这一行。
写好后依次执行:systemctl daemon-reload 让 systemd 重新读取配置文件;systemctl start hello 立即启动;systemctl enable hello 设置开机自启;systemctl status hello 查看状态。注意服务名不用加 .service 后缀,hello 和 hello.service 是同一个服务。
四、最常用的 systemctl 命令
- 查看状态:
systemctl status nginx,输出里Active: active (running)表示正在运行,enabled表示已设开机自启,disabled表示未设。 - 启动、停止、重启:
systemctl start/stop/restart nginx。 - 开机自启开关:
systemctl enable/disable nginx,enable --now可以启动并同时设为自启。 - 查看是否自启:
systemctl is-enabled nginx。 - 列出所有服务:
systemctl list-units --type=service,加--state=failed只看启动失败的服务,排错时很有用。
修改服务文件后一定要先 daemon-reload 再 restart,否则改动不会生效,这是新手最常踩的坑。
五、日志:journalctl
systemd 的日志由 journald 统一收集,用 journalctl 查看,比到处找日志文件方便得多:
- 看某个服务的日志:
journalctl -u nginx; - 实时跟踪:
journalctl -u nginx -f,类似tail -f; - 只看本次启动后的日志:
journalctl -u nginx -b; - 只看最近 100 行:
journalctl -u nginx -n 100; - 按时间过滤:
journalctl -u nginx --since "2026-11-05 09:00" --until "2026-11-05 10:00"; - 只看报错:
journalctl -u nginx -p err。
服务起不来时,先 systemctl status 看简要报错,再 journalctl -u 服务名 -n 50 看最近日志,多数问题都能定位到:最常见的是 ExecStart 路径写错、配置文件语法错误、端口被占用、运行用户没有文件权限。
六、给自己程序写服务的注意事项
第一,ExecStart 必须用绝对路径,环境变量也不会自动继承 shell 的配置,程序依赖的环境变量要在服务文件里用 Environment= 显式写出,或者用 EnvironmentFile= 指向一个 env 文件。第二,User= 尽量不要用 root,用专用的低权限用户,配合 WorkingDirectory 把工作目录定死。第三,需要等数据库、网络等依赖就绪时,用 After= 声明顺序,必要时再加 Requires= 或 Wants= 声明依赖关系。第四,程序本身要能前台运行,不要在启动命令里加 & 后台化,也不要用 nohup,这些都交给 systemd 来管。
七、常见问题排查清单
服务启动失败时按这个顺序查:服务文件语法有没有问题(systemd-analyze verify /etc/systemd/system/hello.service 可以校验);改完文件有没有 daemon-reload;启动命令在终端里手动跑一遍能不能跑通;端口是不是被别的进程占了(ss -tlnp 查看);运行用户对工作目录和日志目录有没有读写权限;最后看 journalctl 的完整报错。
结语
掌握 systemd 之后,部署就从“终端挂着程序”变成了“服务交给系统管”:开机自启、崩溃重启、统一日志都有了标准做法。建议从一个自己的小服务练起,写一遍 service 文件、走一遍 enable 和 status、再用 journalctl 查一次日志,这套流程以后部署 Nginx、数据库、自己的应用都会反复用到。
- 点赞
- 收藏
- 关注作者
评论(0)