在操作系统中,"服务"指后台常驻的进程或守护程序(
daemon)——它们在系统启动时自动运行,在后台默默工作,提供各种功能(如时间同步、防火墙、计划任务、
Web 服务器、数据库等)。现代 Linux 使用 systemd
统一管理这些服务,提供了强大的依赖管理、并行启动、日志集成等功能。本文会从
systemd 的核心概念讲起,深入 systemctl
命令的使用,讲解常见服务(时间同步、防火墙、计划任务、
SSH)的配置与排障,并教你如何自定义服务、让自己的程序开机自启。如果你是运维人员或需要管理
Linux
服务器,这篇文章会让你从"会启停服务"升级到"能写自定义服务、能排障、能优化启动顺序"。
systemd 核心概念:为什么要用它、它解决了什么问题
为什么需要服务管理器
在操作系统中,"服务"( Service)是指那些长期运行在后台、对系统或用户提供某种功能的进程或守护程序( daemon)。例如:
- 时间同步服务( ntpd / ntpsec):定期与时间服务器同步,确保系统时钟准确
- 防火墙服务( firewalld / iptables):控制网络流量,保护系统安全
- SSH 服务( sshd):允许远程登录
- Web 服务器( nginx / apache):处理 HTTP 请求,提供网站访问
- 数据库服务( mysql / postgresql):存储和查询数据
- 计划任务服务( crond):按时间表自动执行脚本
这些服务通常需要: 1. 开机自动启动(不需要手动启动) 2. 崩溃后自动重启(提高可用性) 3. 依赖关系管理(例如 Web 服务依赖网络服务,网络服务依赖网卡驱动) 4. 日志集成(方便排障) 5. 资源限制(防止某个服务占用过多 CPU/内存)
服务管理器就是用来统一管理这些服务的工具。
systemd vs SysV init(旧系统)
在 systemd 出现之前, Linux 使用 SysV init 作为服务管理器( CentOS 6 、 Ubuntu 14.04 及更早版本)。它的特点是:
- 服务脚本放在
/etc/init.d/目录下 - 使用
service <service> start/stop/restart管理服务 - 使用
chkconfig配置开机自启 - 串行启动:服务按顺序一个一个启动,慢(尤其是服务很多时)
- 依赖关系靠脚本手动处理:容易出错
systemd 是现代 Linux 发行版的服务管理器( CentOS 7+、 Ubuntu 16.04+、 Debian 8+),它的优点是:
- 并行启动:多个服务同时启动,快很多
- 依赖关系自动处理: systemd 知道服务之间的依赖关系,自动按顺序启动
- 统一的日志系统( journald):所有服务的日志都集中管理,方便查询
- Socket 激活:某些服务可以按需启动(有连接时才启动,节省资源)
- Cgroup 集成:可以限制服务的 CPU/内存使用
- 统一的命令:
systemctl一个命令管理所有服务
兼容性: systemd 向下兼容 SysV init
的命令(service 和 chkconfig 在 systemd
系统上仍然可用,但底层调用的是 systemctl)。
systemd 的核心概念: unit
在 systemd 中,一切皆 unit(单元)。 Unit 是 systemd 管理的最小单位,常见的 unit 类型有:
| Unit 类型 | 说明 | 示例 |
|---|---|---|
| service | 最常见的类型,代表一个后台服务(进程) | sshd.service、nginx.service |
| socket | 代表一个 IPC 或网络套接字,用于按需激活服务 | sshd.socket、docker.socket |
| target | 代表一组 unit 的集合(类似 SysV 的 runlevel) | multi-user.target、graphical.target |
| mount | 代表一个挂载点(文件系统) | home.mount、tmp.mount |
| timer | 代表一个定时任务(替代 cron) | logrotate.timer、apt-daily.timer |
| device | 代表一个设备(如 USB 、网卡) | dev-sda.device |
| path | 监控文件/目录变化,触发服务启动 | systemd-tmpfiles-clean.path |
最常用的是 service 类型(.service
后缀),所以我们通常说的"服务"就是指 service unit 。
systemd 启动流程简述
- 内核启动:内核加载完成后,启动 systemd( PID 1,第一个用户空间进程)
- systemd 读取配置:读取
/etc/systemd/system/和/usr/lib/systemd/system/下的 unit 文件 - 确定启动目标:通常是
multi-user.target(多用户文本模式)或graphical.target(图形界面) - 解析依赖关系:根据 unit 文件中的
Requires、After、Before等字段,确定启动顺序 - 并行启动服务:同时启动多个没有依赖关系的服务(提高启动速度)
- 进入目标状态:所有依赖的服务都启动完成后,系统进入目标状态(如登录提示符)
systemctl 命令:日常使用的"肌肉记忆"
systemctl 是 systemd
的主要命令行工具,用于管理服务。这部分是你日常操作最常用的命令。
基本操作(启动、停止、重启、查看状态)
1 | # 启动服务(立即生效,但重启后失效) |
示例: 1
2
3systemctl start sshd # 启动 SSH 服务
systemctl status sshd # 查看 SSH 服务状态
systemctl reload nginx # 重新加载 nginx 配置(不停止服务)
开机自启管理
1 | # 设置开机自启(创建符号链接到 /etc/systemd/system/multi-user.target.wants/) |
示例: 1
2
3systemctl enable sshd # 设置 SSH 服务开机自启
systemctl is-enabled sshd # 输出: enabled
systemctl disable firewalld # 取消防火墙开机自启
查看服务列表
1 | # 列出所有正在运行的服务 |
示例输出: 1
2● sshd.service loaded active running OpenBSD Secure Shell server
● nginx.service loaded active running A high performance web server
查看服务详细信息
1 | # 查看服务的 unit 文件内容 |
示例: 1
2
3systemctl cat sshd.service # 查看 sshd 的 unit 文件
systemctl list-dependencies sshd.service # 查看 sshd 依赖哪些服务
systemd-analyze blame # 查看所有服务的启动耗时(按耗时排序)
自定义服务:让你的程序开机自启
假设你有一个 Python 脚本或编译好的二进制程序,想让它开机自启、崩溃后自动重启,怎么做?写一个 systemd unit 文件即可。
最小可用示例
假设你有一个脚本 /usr/local/bin/myapp.sh:
1
2
3
4
5
while true; do
echo "MyApp is running..."
sleep 10
done
创建 unit 文件 /etc/systemd/system/myapp.service:
1
2
3
4
5
6
7
8
9
10
11
12
13
14[Unit]
Description=My Custom Application
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/bin/myapp.sh
Restart=always
RestartSec=10
User=nobody
Group=nogroup
[Install]
WantedBy=multi-user.target
然后启动并启用: 1
2
3
4sudo systemctl daemon-reload # 重新加载 systemd 配置
sudo systemctl start myapp
sudo systemctl enable myapp
sudo systemctl status myapp
unit 文件详解
[Unit] 部分(描述和依赖关系)
1 | [Unit] |
[Service] 部分(服务的启动方式和行为)
1 | [Service] |
[Install] 部分(开机自启配置)
1 | [Install] |
常见 Type 的区别
| Type | 说明 | 适用场景 |
|---|---|---|
| simple | 启动后立即认为服务已准备好(默认) | 大部分服务(如 nginx 、 python 脚本) |
| forking | 服务会 fork 一个子进程后退出(父进程退出后,子进程成为主进程) | 传统的 daemon 程序(如老版本的 Apache) |
| oneshot | 执行完就退出(不是常驻进程) | 一次性初始化任务(如挂载文件系统) |
| notify | 服务启动后会主动通知 systemd "我准备好了"(需要程序支持 sd_notify) | 高级服务(如 systemd-networkd) |
修改 unit 文件后必须重新加载
1 | sudo systemctl daemon-reload # 告诉 systemd 重新读取 unit 文件 |
journalctl: systemd 的统一日志系统
systemd 自带了 journald,所有服务的日志都集中存储在
/var/log/journal/ 或
/run/log/journal/(重启后清空),可以用
journalctl 查询。
基本用法
1 | # 查看所有日志(从最早到最新) |
高级用法
1 | # 查看日志并显示详细信息(包括 PID 、 UID 等) |
日志持久化
默认情况下, journald 的日志存储在
/run/log/journal/(内存中,重启后清空)。如果要持久化日志:
创建目录:
1
2sudo mkdir -p /var/log/journal
sudo systemd-tmpfiles --create --prefix /var/log/journal重启 journald:
1
sudo systemctl restart systemd-journald
之后日志会保存在 /var/log/journal/,重启后仍然存在。
常见服务配置与排障
这部分讲解几个最常见的系统服务的配置和排障方法。
时间同步服务( ntpd / ntpsec / timedatectl)
为什么需要时间同步
在分布式系统、集群、日志分析等应用场景下,时间同步至关重要:
- 定时任务的执行(如 cron 任务):如果时间不一致,任务可能提前或延后执行
- 日志对比和分析:如果多台服务器时间不一致,日志时间戳会错乱,无法关联
- 数据同步(如数据库主从复制):时间不一致可能导致数据顺序混乱
- 安全协议(如 Kerberos 身份认证、 TLS 证书):时间差太大会导致认证失败
方案 1:使用 ntpsec(推荐)
ntpsec 是传统 ntpd 的现代化版本,安全性更高、代码更精简。
安装与启动: 1
2
3sudo apt install ntpsec # Debian/Ubuntu
sudo yum install ntpsec # CentOS/RHEL
sudo systemctl enable --now ntpsec
配置:编辑
/etc/ntpsec/ntp.conf,添加时间服务器(推荐使用国内服务器,延迟低):
1
2
3server ntp.aliyun.com iburst prefer
server ntp.tencent.com iburst
server cn.pool.ntp.org iburst
iburst:启动时快速同步(发送 8 个包而不是 1 个)prefer:优先使用这个服务器
重启服务: 1
sudo systemctl restart ntpsec
查看同步状态: 1
ntpq -p # 查看当前连接的时间服务器
方案 2:使用 timedatectl(更简单)
timedatectl 是 systemd 自带的时间管理工具,底层使用
systemd-timesyncd 进行 NTP 同步。
启用 NTP 同步: 1
sudo timedatectl set-ntp true
查看状态: 1
timedatectl
输出示例: 1
2
3
4
5
6
7 Local time: Mon 2025-02-03 12:00:00 UTC
Universal time: Mon 2025-02-03 12:00:00 UTC
RTC time: Mon 2025-02-03 12:00:00
Time zone: UTC (UTC, +0000)
System clock synchronized: yes
NTP service: active
RTC in local TZ: no
设置时区(如果需要): 1
sudo timedatectl set-timezone Asia/Shanghai
查看可用时区: 1
timedatectl list-timezones | grep Shanghai
ntpdate(一次性同步,不推荐常驻使用)
如果只需要临时同步一次时间(不是常驻服务): 1
sudo ntpdate ntp.aliyun.com
缺点:
- 暴力修改时间(直接跳变),可能导致依赖时序的程序出错(如定时任务、数据库同步)
- ntpd / ntpsec 采用平滑调整,避免时间跳变
推荐:使用 ntpsec 或 timedatectl 进行长时间运行的同步,避免 ntpdate 的问题。
防火墙服务( firewalld)
基本介绍
防火墙( Firewall)是一种网络安全工具,用于控制和过滤网络流量,防止未经授权的访问。在 Linux 中,常见的防火墙有:
- iptables(传统,规则是有顺序的,配置复杂)
- firewalld(现代,动态规则,支持 zone 概念, RHEL/CentOS 默认)
- ufw( Ubuntu 友好型防火墙,简化了 iptables)
firewalld 是基于 iptables/nftables 的动态防火墙,提供了更友好的命令行接口。
启用与关闭
1 | sudo systemctl start firewalld |
基本规则操作
开放/关闭端口
1 | # 开放 80 端口( TCP) |
--permanent:写入永久规则(否则重启后失效)--reload:重新加载规则(使永久规则生效)
开放/关闭服务
1 | # 开放 HTTP 服务(包含 80 端口) |
常见服务名:http、https、ssh、ntp、mysql、postgresql
等。
zone 概念
firewalld 使用 zone(区域)来定义不同的安全级别:
| Zone 名称 | 信任级别 | 默认策略 | 典型应用场景 |
|---|---|---|---|
| drop | 最低 | 丢弃所有传入流量,不回应 | 最高安全性,完全隐藏设备 |
| public | 低 | 默认拒绝所有入站,仅允许 SSH | 公共网络(如 WiFi 热点) |
| work | 高 | 允许内部可信网络访问,默认允许 SSH 、 Samba | 公司内部网络 |
| home | 高 | 允许家用网络访问 | 家庭网络 |
| trusted | 最高 | 允许所有流量 | 完全信任的环境 |
查看当前默认 zone: 1
sudo firewall-cmd --get-default-zone
修改默认 zone: 1
sudo firewall-cmd --set-default-zone=work
计划任务( crontab)
计划任务让系统在指定时间自动执行某些脚本或命令,例如:
- 定时备份数据库(每天凌晨 2 点)
- 定时清理日志文件或临时文件夹(每周日)
- 定时同步时间(每小时)
编辑与查看
1 | crontab -e # 编辑当前用户的计划任务 |
格式
1 | MIN HOUR DAY MONTH WEEKDAY command |
MIN:分钟( 0-59)HOUR:小时( 0-23)DAY:日期( 1-31)MONTH:月份( 1-12)WEEKDAY:星期( 0-7, 0 和 7 都表示周日)command:要执行的命令(建议使用绝对路径)
特殊符号:
*:表示"每"(如*在分钟位表示每分钟)-:表示范围(如1-5表示 1 到 5)/:表示间隔(如*/10表示每 10 个单位),:表示多个值(如1,2,6表示 1 、 2 、 6)
示例
1 | # 每天凌晨 1:30 运行备份脚本 |
查看日志
1 | grep CRON /var/log/syslog # Debian/Ubuntu |
SSH 服务配置与安全加固
SSH 是远程管理 Linux 服务器的标准方式。在"Linux
使用基础"里已经讲了基本用法(ssh user@host、免密登录),这里讲一些
sshd 配置和安全加固。
配置文件
配置文件:/etc/ssh/sshd_config
修改后需要重启服务: 1
sudo systemctl restart sshd
常见配置项
1 | # 监听端口(默认 22,建议改成其他端口减少被扫描) |
安全加固建议
- 改端口:把默认端口 22 改成其他端口(如 22222),减少被扫描的概率
- 禁止 root
登录:
PermitRootLogin no,只允许普通用户登录,需要权限时再sudo - 禁止密码登录:
PasswordAuthentication no,只允许密钥登录(防止暴力破解) - 安装 fail2ban:自动封禁暴力破解的 IP(连续失败多次后自动封禁)
- 配置防火墙:只允许特定 IP 连接 SSH(如果有固定 IP)
- 使用 SSH 密钥: 4096 位 RSA 或 Ed25519 密钥(比密码安全得多)
服务排障流程:服务起不来怎么办
当服务起不来时,按这个流程排查:
1. 查看服务状态
1 | sudo systemctl status <service> |
关注:
- Active:是否显示
active (running)或failed - Main PID:主进程 PID(如果是 0 说明进程已退出)
- 最近的日志:通常会显示最后几行日志,看有没有错误信息
2. 查看详细日志
1 | sudo journalctl -u <service> -xe |
-x:显示额外的解释信息-e:跳到日志末尾(最新的日志)
3. 检查配置文件语法
很多服务提供配置文件语法检查工具:
- nginx:
nginx -t - apache:
apachectl configtest - sshd:
sshd -t
4. 检查端口冲突
1 | sudo ss -lntp | grep <port> # 查看端口是否被占用 |
5. 检查文件权限
服务可能因为权限不足而无法启动: 1
2ls -l /path/to/config
ls -l /var/log/<service>
确保服务运行的用户(如
www-data、nginx、nobody)有权限读写相关文件。
6. 检查 SELinux / AppArmor
如果开启了 SELinux( RHEL/CentOS)或 AppArmor( Ubuntu/Debian),可能会阻止服务启动。
临时关闭 SELinux(仅用于排查): 1
sudo setenforce 0 # 设置为 Permissive 模式
查看 SELinux 日志: 1
sudo ausearch -m avc -ts recent
临时关闭 AppArmor: 1
sudo systemctl stop apparmor
7. 检查依赖关系
1 | sudo systemctl list-dependencies <service> |
如果依赖的服务没有启动,当前服务也无法启动。
总结与扩展阅读
这篇文章涵盖了 systemd 服务管理的核心内容: 1. ✅ systemd 的核心概念( unit 、依赖关系、启动流程) 2. ✅ systemctl 的日常使用(启停、开机自启、查看状态) 3. ✅ 自定义服务(如何让自己的程序开机自启) 4. ✅ journalctl 日志管理(查询、过滤、清理) 5. ✅ 常见服务配置(时间同步、防火墙、计划任务、 SSH) 6. ✅ 服务排障流程(服务起不来怎么办)
扩展阅读:
- systemd 官方文档: https://www.freedesktop.org/wiki/Software/systemd/
- systemd for Administrators 系列: http://0pointer.de/blog/projects/systemd-for-admins-1.html
- journalctl 手册:
man journalctl - systemd.service 手册:
man systemd.service
下一步:
- 《 Linux 软件包管理》:学习如何安装/卸载/更新软件包( apt/yum/dnf/rpm)
- 《 Linux 进程与资源管理》:学习如何监控和限制进程的 CPU/内存使用
- 《 Linux 用户管理》:学习如何管理用户/组/权限
到这里,建议已经从"会启停服务"升级到"能写自定义服务、能排障、能优化启动顺序"。服务管理是 Linux 运维的核心技能,掌握了 systemd,你就能更好地管理服务器。
- 本文标题:Linux 系统服务管理
- 本文作者:Chen Kai
- 创建时间:2019-12-13 09:15:00
- 本文链接:https://www.chenk.top/Linux-%E7%B3%BB%E7%BB%9F%E6%9C%8D%E5%8A%A1%E7%AE%A1%E7%90%86/
- 版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!