跳转至

服务与系统管理

服务与系统管理

📌 学习时间:2-3天 📌 难度级别:⭐⭐⭐ 中级 📌 前置知识:Linux基础、进程管理


📚 章节概述

服务管理和系统调优是 Linux 运维的核心工作。本章深入讲解 systemd 服务管理体系、Crontab 定时任务、日志系统(syslog/rsyslog/logrotate)、init 系统对比、开机自启动配置以及系统性能调优基础。

🎯 学习目标

  • 深入理解 systemd 体系(systemctl/journalctl)
  • 掌握 Crontab 定时任务配置
  • 理解日志系统(syslog/rsyslog/logrotate)
  • 了解 SysVinit vs systemd 的区别
  • 掌握开机自启动配置
  • 了解系统性能调优基础

📖 1. systemd 详解

1.1 systemd 概述

Bash
# systemd 是现代 Linux 的标准 init 系统(PID=1)
# 取代了传统的 SysVinit 和 Upstart

# systemd 的核心概念:Unit(单元)
# 常见 Unit 类型:
# .service  — 服务(最常用)
# .socket   — 套接字激活
# .timer    — 定时器(替代 cron)
# .mount    — 挂载点
# .target   — 目标(类似运行级别)
# .path     — 路径监控
# .slice    — 资源控制组

# 查看 systemd 版本
systemd --version

1.2 systemctl — 服务管理

Bash
# 基本操作
sudo systemctl start nginx            # 启动服务
sudo systemctl stop nginx             # 停止服务
sudo systemctl restart nginx          # 重启服务
sudo systemctl reload nginx           # 重新加载配置(不中断服务)
sudo systemctl status nginx           # 查看服务状态

# 输出示例:
# ● nginx.service - A high performance web server
#    Loaded: loaded (/lib/systemd/system/nginx.service; enabled)
#    Active: active (running) since Mon 2024-01-15 10:30:00 CST; 5h ago
#  Main PID: 1234 (nginx)
#     Tasks: 3
#    Memory: 15.0M
#    CGroup: /system.slice/nginx.service
#            ├─1234 nginx: master process
#            ├─1235 nginx: worker process
#            └─1236 nginx: worker process

# 开机自启动
sudo systemctl enable nginx           # 开机自启
sudo systemctl disable nginx          # 取消自启
sudo systemctl enable --now nginx     # 启动并设置自启
sudo systemctl is-enabled nginx       # 检查是否自启

# 查看服务列表
systemctl list-units --type=service                    # 活动的服务
systemctl list-units --type=service --all              # 所有服务
systemctl list-units --type=service --state=running    # 运行中的
systemctl list-units --type=service --state=failed     # 失败的
systemctl list-unit-files --type=service               # 所有服务文件

# 查看服务依赖
systemctl list-dependencies nginx
systemctl list-dependencies nginx --reverse  # 被谁依赖

# 其他操作
sudo systemctl mask nginx              # 彻底禁用(无法启动)
sudo systemctl unmask nginx            # 取消禁用
sudo systemctl daemon-reload           # 重新加载服务文件(修改后必须执行)
sudo systemctl isolate multi-user.target  # 切换到多用户模式

1.3 自定义 systemd 服务

Bash
# 创建自定义服务文件
# 注意:不能用 sudo cat > file(重定向在当前Shell执行,没有sudo权限)
# 正确做法是用 sudo tee
sudo tee /etc/systemd/system/myapp.service > /dev/null << 'EOF'
[Unit]
Description=My Application
Documentation=https://example.com/docs
After=network.target
Wants=network-online.target

[Service]
Type=simple
User=myapp
Group=myapp
WorkingDirectory=/opt/myapp
ExecStartPre=/opt/myapp/check_config.sh
ExecStart=/opt/myapp/bin/myapp --config /etc/myapp/config.yaml
ExecReload=/bin/kill -HUP $MAINPID
ExecStop=/bin/kill -TERM $MAINPID
Restart=on-failure
RestartSec=5
LimitNOFILE=65535

# 安全加固
ProtectSystem=full
ProtectHome=true
NoNewPrivileges=true
PrivateTmp=true

# 环境变量
Environment=NODE_ENV=production
EnvironmentFile=/etc/myapp/env

# 日志
StandardOutput=journal
StandardError=journal
SyslogIdentifier=myapp

[Install]
WantedBy=multi-user.target
EOF

# 重新加载并启动
sudo systemctl daemon-reload
sudo systemctl enable --now myapp
sudo systemctl status myapp

# Service Type 类型说明
# simple  — 默认,ExecStart 的进程就是主进程
# forking — 进程 fork 后主进程退出,需设 PIDFile
# oneshot — 一次性任务(如初始化脚本)
# notify  — 服务就绪后通过 sd_notify 通知 systemd
# idle    — 等待其他任务完成后才启动

# Restart 策略
# no              — 不重启
# on-success      — 正常退出时重启
# on-failure      — 异常退出时重启(推荐服务使用)
# on-abnormal     — 异常信号时重启
# on-abort        — abort 信号时重启
# on-watchdog     — 看门狗超时时重启
# always          — 总是重启

1.4 journalctl — 日志查看

Bash
# journalctl 是 systemd 的日志查看工具

# 查看所有日志
journalctl                             # 所有日志(从旧到新)
journalctl -r                          # 逆序(最新在前)
journalctl -f                          # 实时跟踪(类似 tail -f)

# 按服务过滤
journalctl -u nginx                    # nginx 的日志
journalctl -u nginx --since "1 hour ago"  # 最近1小时
journalctl -u nginx -f                 # 实时跟踪 nginx 日志

# 按时间过滤
journalctl --since "2024-01-15 10:00:00"
journalctl --since "2024-01-15" --until "2024-01-16"
journalctl --since "1 hour ago"
journalctl --since yesterday
journalctl -b                          # 本次启动的日志
journalctl -b -1                       # 上次启动的日志

# 按优先级过滤
journalctl -p err                      # 错误及以上
journalctl -p warning                  # 警告及以上
# 优先级(从高到低): emerg, alert, crit, err, warning, notice, info, debug

# 按进程/用户过滤
journalctl _PID=1234
journalctl _UID=1000
journalctl _COMM=sshd

# 输出格式
journalctl -o json                     # JSON 格式
journalctl -o json-pretty              # 格式化 JSON
journalctl -o short-iso                # 短格式带 ISO 时间

# 磁盘空间管理
journalctl --disk-usage                # 查看日志占用空间
sudo journalctl --vacuum-size=500M     # 限制日志大小
sudo journalctl --vacuum-time=30d      # 删除30天前的日志

📖 2. Crontab 定时任务

2.1 Crontab 格式

Bash
# 格式:分 时 日 月 周 命令
# ┌──────── 分钟 (0-59)
# │ ┌────── 小时 (0-23)
# │ │ ┌──── 日 (1-31)
# │ │ │ ┌── 月 (1-12)
# │ │ │ │ ┌ 周几 (0-7, 0和7都是周日)
# │ │ │ │ │
# * * * * * command

# 特殊字符
# *     任意值
# ,     多个值(1,3,5)
# -     范围(1-5)
# /     间隔(*/5 = 每5个单位)

# 示例
# 每分钟
* * * * * /path/to/script.sh

# 每小时第30分钟
30 * * * * /path/to/script.sh

# 每天凌晨2点
0 2 * * * /path/to/backup.sh

# 每周一到周五早上9点
0 9 * * 1-5 /path/to/report.sh

# 每月1日凌晨3点
0 3 1 * * /path/to/monthly_task.sh

# 每5分钟
*/5 * * * * /path/to/check.sh

# 每两小时
0 */2 * * * /path/to/task.sh

# 工作日每天9:30和17:30
30 9,17 * * 1-5 /path/to/notify.sh

# 特殊时间标记
@reboot    /path/to/startup.sh          # 开机执行
@yearly    /path/to/annual.sh           # 每年(0 0 1 1 *)
@monthly   /path/to/monthly.sh          # 每月(0 0 1 * *)
@weekly    /path/to/weekly.sh           # 每周(0 0 * * 0)
@daily     /path/to/daily.sh            # 每天(0 0 * * *)
@hourly    /path/to/hourly.sh           # 每小时(0 * * * *)

2.2 Crontab 管理

Bash
# 编辑当前用户的 crontab
crontab -e

# 查看当前用户的 crontab
crontab -l

# 删除当前用户的 crontab(危险!)
crontab -r

# 编辑其他用户的 crontab(需要root)
sudo crontab -u alice -e
sudo crontab -u alice -l

# 系统级 crontab
cat /etc/crontab
ls /etc/cron.d/                     # 系统 cron 配置目录
ls /etc/cron.daily/                 # 每天执行的脚本
ls /etc/cron.weekly/                # 每周执行的脚本
ls /etc/cron.monthly/               # 每月执行的脚本

# Crontab 最佳实践
# 1. 使用绝对路径
0 2 * * * /usr/bin/python3 /opt/myapp/task.py

# 2. 设置环境变量
PATH=/usr/local/bin:/usr/bin:/bin
SHELL=/bin/bash
MAILTO=admin@example.com

# 3. 记录日志
0 2 * * * /opt/backup.sh >> /var/log/backup.log 2>&1

# 4. 避免重复执行(使用 flock)
*/5 * * * * /usr/bin/flock -n /tmp/task.lock /opt/task.sh

# 5. 任务超时控制
0 2 * * * timeout 3600 /opt/long_task.sh

2.3 systemd Timer(Crontab 替代方案)

Bash
# systemd timer 可以替代 crontab,功能更强大

# 1. 创建服务文件(定义要执行的任务)
sudo tee /etc/systemd/system/backup.service > /dev/null << 'EOF'
[Unit]
Description=Daily Backup

[Service]
Type=oneshot
ExecStart=/opt/scripts/backup.sh
User=root
EOF

# 2. 创建 timer 文件
sudo tee /etc/systemd/system/backup.timer > /dev/null << 'EOF'
[Unit]
Description=Run backup daily at 2am

[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true
RandomizedDelaySec=300

[Install]
WantedBy=timers.target
EOF

# 3. 启用 timer
sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer

# 查看 timer 状态
systemctl list-timers --all
systemctl status backup.timer

# Timer 时间格式示例
# OnCalendar=hourly              每小时
# OnCalendar=daily               每天
# OnCalendar=weekly              每周
# OnCalendar=*-*-* 02:00:00     每天2点
# OnCalendar=Mon *-*-* 09:00:00 每周一9点
# OnCalendar=*-*-01 03:00:00    每月1号3点

📖 3. 日志系统

3.1 syslog / rsyslog

Bash
# rsyslog 是 syslog 的增强版,是大多数发行版默认的日志守护进程

# 配置文件
/etc/rsyslog.conf
/etc/rsyslog.d/*.conf

# 日志文件位置
/var/log/syslog              # 系统日志(Ubuntu)
/var/log/messages            # 系统日志(CentOS)
/var/log/auth.log            # 认证日志(Ubuntu)
/var/log/secure              # 认证日志(CentOS)
/var/log/kern.log            # 内核日志
/var/log/dmesg               # 启动日志
/var/log/cron                # cron 日志(CentOS)
/var/log/mail.log            # 邮件日志
/var/log/nginx/              # Nginx 日志
/var/log/mysql/              # MySQL 日志

# rsyslog 配置格式
# 设施.优先级    动作
# facility.priority    action

# Facility(设施):
# auth, authpriv, cron, daemon, kern, lpr, mail,
# news, syslog, user, uucp, local0-local7

# Priority(优先级,从低到高):
# debug, info, notice, warning, err, crit, alert, emerg

# 配置示例
# *.info;mail.none;authpriv.none  /var/log/messages
# authpriv.*                      /var/log/secure
# mail.*                          /var/log/maillog
# cron.*                          /var/log/cron
# *.emerg                         :omusrmsg:*

# 远程日志(收集其他服务器日志)
# 服务端配置(接收日志)
# /etc/rsyslog.conf
# module(load="imudp")
# input(type="imudp" port="514")

# 客户端配置(发送日志)
# *.* @log_server:514        # UDP
# *.* @@log_server:514       # TCP

# 使用 logger 命令记录日志
logger "这是一条测试日志"
logger -p auth.warning "登录警告"
logger -t myapp "应用日志消息"

3.2 logrotate — 日志轮转

Bash
# logrotate 自动管理日志文件的大小和数量

# 主配置文件
cat /etc/logrotate.conf

# 应用配置目录
ls /etc/logrotate.d/

# 配置示例
sudo tee /etc/logrotate.d/myapp > /dev/null << 'EOF'
/var/log/myapp/*.log {
    daily                   # 每天轮转
    rotate 30               # 保留30个轮转文件
    compress                # 压缩旧日志
    delaycompress           # 延迟压缩(最新的不压缩)
    missingok               # 日志不存在不报错
    notifempty              # 空日志不轮转
    create 0644 myapp myapp # 轮转后创建新文件
    dateext                 # 使用日期作为后缀
    dateformat -%Y%m%d      # 日期格式
    size 100M               # 超过100M才轮转

    postrotate              # 轮转后执行
        systemctl reload myapp 2>/dev/null || true  # &&前一个成功才执行后一个;||前一个失败才执行
    endscript
}
EOF

# 手动执行轮转
sudo logrotate -f /etc/logrotate.d/myapp   # 强制轮转
sudo logrotate -d /etc/logrotate.d/myapp   # 模拟运行(调试)

# 检查 logrotate 状态
cat /var/lib/logrotate/status

📖 4. init 系统对比

Bash
# SysVinit(传统)
# 运行级别:0-6
# 0: 关机
# 1: 单用户(维护模式)
# 2: 多用户(无网络)
# 3: 多用户(有网络,文本模式)
# 4: 未使用
# 5: 图形界面
# 6: 重启

# systemd 目标(Target)对应
# runlevel0 → poweroff.target
# runlevel1 → rescue.target
# runlevel3 → multi-user.target
# runlevel5 → graphical.target
# runlevel6 → reboot.target

# 查看/切换
systemctl get-default                         # 查看默认目标
sudo systemctl set-default multi-user.target  # 设为文本模式
sudo systemctl set-default graphical.target   # 设为图形模式
sudo systemctl isolate multi-user.target      # 临时切换

# SysVinit 对照
# service nginx start    → systemctl start nginx
# service nginx stop     → systemctl stop nginx
# chkconfig nginx on     → systemctl enable nginx
# /etc/init.d/nginx start → systemctl start nginx

📖 5. 系统性能调优基础

5.1 内核参数调优

Bash
# 查看内核参数
sysctl -a                        # 所有参数
sysctl net.ipv4.ip_forward       # 特定参数

# 临时修改
sudo sysctl -w net.ipv4.ip_forward=1

# 永久修改
sudo tee -a /etc/sysctl.conf > /dev/null << 'EOF'
# 网络优化
net.ipv4.ip_forward = 1
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_keepalive_time = 600

# 文件描述符
fs.file-max = 2097152

# 内存
vm.swappiness = 10
vm.overcommit_memory = 1
EOF

sudo sysctl -p                   # 立即生效

5.2 文件描述符限制

Bash
# 查看当前限制
ulimit -a                        # 所有限制
ulimit -n                        # 文件描述符限制

# 临时修改
ulimit -n 65535

# 永久修改 /etc/security/limits.conf
# *    soft    nofile    65535
# *    hard    nofile    65535
# *    soft    nproc     65535
# *    hard    nproc     65535

# systemd 服务的限制
# 在 service 文件中设置
# [Service]
# LimitNOFILE=65535

📖 6. 面试要点

Q1:如何创建一个开机自启动的服务?

编写 .service 文件放在 /etc/systemd/system/,设置 [Install] 中的 WantedBy=multi-user.target,然后执行 systemctl daemon-reloadsystemctl enable --now myservice

Q2:Crontab 中 */5 * * * * 是什么意思?

每5分钟执行一次。分钟字段的 */5 表示从0开始每隔5分钟。

Q3:如何查看某个服务为什么启动失败?

Bash
systemctl status myservice           # 查看状态和最近日志
journalctl -u myservice -n 50       # 查看详细日志
journalctl -u myservice --since "5 min ago"

Q4:logrotate 的作用和原理?

logrotate 自动管理日志文件,防止日志无限增长。它可以按时间或大小进行日志轮转(重命名旧日志、创建新文件、压缩归档、删除过期日志)。配置在 /etc/logrotate.d/ 中,由 cron 每天调用执行。


🔧 练习题

  1. 编写一个 systemd service 文件,管理一个简单的 Python HTTP 服务
  2. 配置 Crontab 每天凌晨2点备份 /etc 目录,保留7天
  3. 配置 logrotate 管理自定义应用的日志(每天轮转,保留30天,压缩)
  4. 使用 journalctl 查找系统中最近1小时的错误日志

✅ 自我检查

  • 能使用 systemctl 管理服务(启停/自启/状态)
  • 能编写自定义 systemd service 文件
  • 能使用 journalctl 查看和过滤日志
  • 能正确配置 Crontab 定时任务
  • 了解 logrotate 配置
  • 了解基本的系统调优参数

上一章07-网络管理 下一章09-包管理与软件安装