Linux系统管理进阶教程

教程简介

面向有基础的Linux系统管理进阶教程,涵盖systemd服务管理、磁盘分区与LVM、性能监控、日志分析、Bash自动化脚本、内核参数调优、容器化基础等进阶内容,配有自动化运维监控系统实战项目。

Linux 系统管理进阶教程

适用读者:已掌握 Linux 基本命令(ls、cd、cp、mv、chmod 等),希望深入系统管理的运维工程师、开发者和技术爱好者。

环境说明:本教程以主流发行版为主,Debian/Ubuntu 系使用 apt,RHEL/CentOS 系使用 yum/dnf,命令示例会分别标注。


目录

  1. 系统启动流程
  2. systemd 服务管理
  3. 磁盘分区与 LVM
  4. 文件系统管理
  5. 性能监控
  6. 日志分析
  7. 自动化脚本(Bash 编程)
  8. 软件包管理
  9. 内核参数调优
  10. 容器化基础
  11. 实战项目:自动化运维监控系统

1. 系统启动流程

理解 Linux 启动流程是系统管理的基础。当电源接通后,系统经历以下阶段:

1.1 启动阶段概览

固件(BIOS/UEFI) → 引导加载器(GRUB2) → 内核加载 → init/systemd → 用户空间

1.2 各阶段详解

BIOS/UEFI 阶段

  • BIOS:传统固件,执行 POST(加电自检),查找 MBR 中的引导代码
  • UEFI:现代固件,直接读取 EFI 分区中的引导文件,支持安全启动(Secure Boot)
# 查看当前启动模式
[ -d /sys/firmware/efi ] && echo "UEFI" || echo "BIOS/Legacy"

# 查看 EFI 分区
lsblk -o NAME,FSTYPE,MOUNTPOINT | grep -i efi

GRUB2 引导阶段

GRUB2 是最常用的引导加载器,负责加载内核和 initramfs。

# 查看 GRUB 配置
cat /etc/default/grub

# 修改默认启动内核(设为第 2 个菜单项)
sudo grub-set-default 1

# 更新 GRUB 配置
# Debian/Ubuntu:
sudo update-grub
# RHEL/CentOS:
sudo grub2-mkconfig -o /boot/grub2/grub.cfg

# 查看可用内核
awk -F\' '/menuentry/ {print NR-1, $2}' /boot/grub/grub.cfg

内核与 initramfs

内核加载后,展开 initramfs(初始内存文件系统),挂载真正的根文件系统。

# 查看当前内核版本
uname -r

# 查看 initramfs 内容
lsinitramfs /boot/initrd.img-$(uname -r)    # Debian/Ubuntu
lsinitrd /boot/initramfs-$(uname -r).img     # RHEL/CentOS

# 重新生成 initramfs
sudo update-initramfs -u                     # Debian/Ubuntu
sudo dracut -f /boot/initramfs-$(uname -r).img $(uname -r)  # RHEL/CentOS

systemd 初始化

现代 Linux 发行版几乎都使用 systemd 作为 PID 1 进程,负责启动所有后续服务。

# 查看启动耗时
systemd-analyze

# 查看各服务启动耗时(按耗时排序)
systemd-analyze blame

# 查看关键链路
systemd-analyze critical-chain

# 查看启动过程日志
journalctl -b

1.3 启动目标(Target)

systemd 用 target 替代了 SysVinit 的 runlevel:

Target 用途 对应旧 runlevel
poweroff.target 关机 0
rescue.target 单用户/救援模式 1
multi-user.target 多用户无图形 3
graphical.target 图形界面 5
reboot.target 重启 6
# 查看当前默认 target
systemctl get-default

# 设置默认为命令行模式
sudo systemctl set-default multi-user.target

# 临时切换到救援模式
sudo systemctl isolate rescue.target

2. systemd 服务管理

2.1 基本操作

# 启动/停止/重启服务
sudo systemctl start nginx
sudo systemctl stop nginx
sudo systemctl restart nginx

# 重载配置(不中断服务,需要服务支持)
sudo systemctl reload nginx

# 设置开机自启 / 取消自启
sudo systemctl enable nginx
sudo systemctl disable nginx

# 查看服务状态
systemctl status nginx

# 检查服务是否运行
systemctl is-active nginx
systemctl is-enabled nginx

2.2 列出与过滤服务

# 列出所有已加载的服务
systemctl list-units --type=service

# 列出所有已启用的服务
systemctl list-unit-files --type=service --state=enabled

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

# 查看服务的依赖关系
systemctl list-dependencies nginx

2.3 编写自定义 Service 单元

创建文件 /etc/systemd/system/myapp.service

[Unit]
Description=My Application Service
Documentation=https://example.com/docs
After=network.target postgresql.service
Requires=postgresql.service
# Requires 表示强依赖,如果 postgresql 停止,myapp 也会停止
# Wants 表示弱依赖,postgresql 停止不影响 myapp

[Service]
Type=simple
# Type 可选: simple(默认), forking, oneshot, notify, idle
User=appuser
Group=appgroup
WorkingDirectory=/opt/myapp
Environment=NODE_ENV=production
EnvironmentFile=/opt/myapp/.env
ExecStartPre=/opt/myapp/pre-start-check.sh
ExecStart=/opt/myapp/start.sh
ExecStartPost=/opt/myapp/post-start.sh
ExecReload=/bin/kill -HUP $MAINPID
ExecStop=/opt/myapp/stop.sh

# 自动重启策略
Restart=on-failure
RestartSec=5s
StartLimitBurst=3
StartLimitIntervalSec=60

# 资源限制
LimitNOFILE=65535
LimitNPROC=4096

# 安全加固
NoNewPrivileges=true
ProtectSystem=strict
ReadWritePaths=/opt/myapp/data /var/log/myapp

[Install]
WantedBy=multi-user.target
# 加载新配置并启动
sudo systemctl daemon-reload
sudo systemctl start myapp
sudo systemctl enable myapp

# 查看日志
journalctl -u myapp -f

2.4 Timer 定时器(替代 cron)

创建 /etc/systemd/system/backup.timer

[Unit]
Description=Daily Backup Timer

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

[Install]
WantedBy=timers.target

对应的服务 /etc/systemd/system/backup.service

[Unit]
Description=Daily Backup Job

[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
User=root
sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer

# 查看所有 timer
systemctl list-timers --all

2.5 Journal 日志管理

# 查看某服务的所有日志
journalctl -u nginx

# 查看最近 100 行
journalctl -u nginx -n 100

# 实时跟踪
journalctl -u nginx -f

# 查看今天的日志
journalctl --since today

# 查看指定时间范围
journalctl --since "2024-01-15 08:00" --until "2024-01-15 12:00"

# 只看错误和警告
journalctl -p err
journalctl -p warning..emerg

# 查看磁盘使用情况
journalctl --disk-usage

# 清理旧日志(保留最近 7 天)
sudo journalctl --vacuum-time=7d

# 限制日志大小
sudo journalctl --vacuum-size=500M

3. 磁盘分区与 LVM

3.1 磁盘分区基础

# 列出所有磁盘和分区
lsblk
sudo fdisk -l

# 查看磁盘详细信息
sudo hdparm -I /dev/sda

# 使用 fdisk 分区(MBR)
sudo fdisk /dev/sdb
# 常用命令: n(新建), d(删除), p(打印), t(改类型), w(写入)

# 使用 gdisk 分区(GPT)
sudo gdisk /dev/sdb

# 使用 parted(支持 MBR 和 GPT)
sudo parted /dev/sdb
(parted) mklabel gpt
(parted) mkpart primary ext4 0% 50%
(parted) mkpart primary xfs 50% 100%
(parted) print

# 通知内核分区表变更
sudo partprobe /dev/sdb

3.2 LVM 逻辑卷管理

LVM(Logical Volume Manager)提供了灵活的磁盘管理能力,支持在线扩容、快照等。

核心概念:物理卷(PV) → 卷组(VG) → 逻辑卷(LV)

# === 创建 LVM ===

# 1. 创建物理卷
sudo pvcreate /dev/sdb1 /dev/sdc1

# 查看物理卷
sudo pvdisplay
sudo pvs

# 2. 创建卷组
sudo vgcreate data_vg /dev/sdb1 /dev/sdc1

# 查看卷组
sudo vgdisplay
sudo vgs

# 3. 创建逻辑卷
sudo lvcreate -L 50G -n app_lv data_vg          # 指定大小
sudo lvcreate -l 100%FREE -n data_lv data_vg     # 使用全部剩余空间

# 查看逻辑卷
sudo lvdisplay
sudo lvs

# 4. 格式化并挂载
sudo mkfs.ext4 /dev/data_vg/app_lv
sudo mkdir -p /data/app
sudo mount /dev/data_vg/app_lv /data/app

# 写入 /etc/fstab 实现开机自动挂载
echo '/dev/data_vg/app_lv /data/app ext4 defaults 0 2' | sudo tee -a /etc/fstab

LVM 扩容

# 场景:app_lv 需要从 50G 扩到 100G

# 1. 扩展逻辑卷
sudo lvextend -L +50G /dev/data_vg/app_lv
# 或者扩展到卷组全部空间
sudo lvextend -l +100%FREE /dev/data_vg/app_lv

# 2. 扩展文件系统(ext4)
sudo resize2fs /dev/data_vg/app_lv

# 对于 xfs 文件系统
sudo xfs_growfs /data/app

# 一步到位:lvextend -r 自动调整文件系统
sudo lvextend -r -L +50G /dev/data_vg/app_lv

添加新磁盘到卷组

# 新磁盘加入已有卷组
sudo pvcreate /dev/sdd1
sudo vgextend data_vg /dev/sdd1

# 查看卷组空间
sudo vgs

LVM 快照

# 创建快照(COW 方式,几乎瞬间完成)
sudo lvcreate -L 10G -s -n app_snap /dev/data_vg/app_lv

# 挂载快照(只读访问某个时间点的数据)
sudo mkdir /mnt/snap
sudo mount -o ro /dev/data_vg/app_snap /mnt/snap

# 恢复快照
sudo umount /mnt/snap
sudo lvconvert --merge /dev/data_vg/app_snap

# 删除快照
sudo lvremove /dev/data_vg/app_snap

4. 文件系统管理

4.1 常见文件系统对比

文件系统 最大文件 最大卷 特点
ext4 16 TiB 1 ExB Linux 默认,稳定可靠
XFS 8 EiB 8 EiB 高性能,适合大文件
Btrfs 16 EiB 16 EiB 支持快照、压缩、校验
ZFS 16 EiB 256 ZiB 企业级,内置 RAID

4.2 文件系统操作

# 创建文件系统
sudo mkfs.ext4 /dev/sdb1
sudo mkfs.xfs /dev/sdb2
sudo mkfs.btrfs /dev/sdb3

# 查看文件系统信息
sudo dumpe2fs /dev/sdb1 | head -30     # ext4
sudo xfs_info /dev/sdb2                 # xfs
sudo btrfs filesystem show /dev/sdb3    # btrfs

# 挂载
sudo mount /dev/sdb1 /mnt/data

# 挂载选项
sudo mount -o noatime,nodiratime /dev/sdb1 /mnt/data   # 提升性能
sudo mount -o remount,rw /mnt/data                       # 重新挂载为读写

# 查看挂载信息
mount | grep sdb
findmnt /mnt/data
df -hT

# 卸载
sudo umount /mnt/data
# 如果提示 busy,查看占用进程
sudo lsof +D /mnt/data
sudo fuser -vm /mnt/data

4.3 /etc/fstab 配置

# 格式:设备  挂载点  文件系统  选项  dump  fsck顺序
# 示例:
UUID=xxxx-xxxx  /data  ext4  defaults,noatime  0  2

# 获取 UUID
sudo blkid /dev/sdb1

# 测试 fstab(不重启验证)
sudo mount -a

# 使用 systemd 自动挂载(推荐用于可移动设备)
# /etc/systemd/system/mnt-data.mount
[Unit]
Description=Data Partition

[Mount]
What=/dev/disk/by-uuid/xxxx-xxxx
Where=/mnt/data
Type=ext4
Options=noatime

[Install]
WantedBy=multi-user.target

4.4 磁盘空间管理

# 查看磁盘使用情况
df -hT

# 查看目录大小
du -sh /var/log/*
du -h --max-depth=1 / | sort -rh | head -10

# 查找大文件
sudo find / -type f -size +100M -exec ls -lh {} \; 2>/dev/null
sudo find / -type f -size +1G 2>/dev/null

# 查找已删除但仍被进程占用的文件
sudo lsof +L1

# 清理常用
sudo journalctl --vacuum-size=200M
sudo apt clean                          # Debian/Ubuntu
sudo yum clean all                      # RHEL/CentOS
sudo rm -rf /tmp/*

4.5 RAID 配置(mdadm)

# 创建 RAID 1(镜像)
sudo mdadm --create /dev/md0 --level=1 --raid-devices=2 /dev/sdb1 /dev/sdc1

# 查看 RAID 状态
cat /proc/mdstat
sudo mdadm --detail /dev/md0

# 保存 RAID 配置
sudo mdadm --detail --scan | sudo tee -a /etc/mdadm/mdadm.conf

# 模拟故障并替换磁盘
sudo mdadm --manage /dev/md0 --fail /dev/sdb1
sudo mdadm --manage /dev/md0 --remove /dev/sdb1
sudo mdadm --manage /dev/md0 --add /dev/sdd1

5. 性能监控

5.1 top / htop

# top 基本使用
top
# 常用快捷键:
#   M - 按内存排序
#   P - 按 CPU 排序
#   1 - 显示每个 CPU 核心
#   k - 终止进程
#   c - 显示完整命令
#   H - 显示线程

# htop(更友好的交互界面)
htop
# 支持鼠标操作,F5 树形视图,F6 排序,F9 杀进程

# 批处理模式(适合脚本采集)
top -bn1 | head -20
top -bn1 -o %MEM | head -20   # 按内存排序

5.2 vmstat

# 每秒采样一次,共 5 次
vmstat 1 5

# 输出字段说明:
# procs: r(运行队列) b(阻塞进程)
# memory: swpd(虚拟内存) free(空闲) buff(缓冲) cache(缓存)
# swap: si(换入) so(换出)
# io: bi(块读入) bo(块写出)
# system: in(中断数) cs(上下文切换)
# cpu: us(user) sy(system) id(idle) wa(iowait) st(steal)

# 查看活跃/非活跃内存
vmstat -a 1 3

# 查看磁盘统计
vmstat -d

# 查看 slab 信息
vmstat -m

5.3 iostat

# 安装(sysstat 包)
sudo apt install sysstat     # Debian/Ubuntu
sudo yum install sysstat     # RHEL/CentOS

# 磁盘 I/O 统计
iostat -xz 1 5

# 关键字段:
# Device: 设备名
# r/s, w/s: 每秒读/写次数
# rkB/s, wkB/s: 每秒读/写数据量
# await: 平均 I/O 等待时间(ms)
# %util: 设备利用率(>70% 需关注)

# 只看扩展统计
iostat -xz -p sda 1

# 以 MB 为单位显示
iostat -xm 1 3

5.4 综合监控工具

# 内存详细信息
free -h
cat /proc/meminfo

# CPU 信息
lscpu
cat /proc/cpuinfo

# 查看进程打开的文件
lsof -p <PID>
lsof -i :80

# 查看网络连接
ss -tulnp        # 监听端口
ss -s            # 连接统计

# 系统负载
uptime
cat /proc/loadavg

# sar(系统活动报告,需要 sysstat)
sar -u 1 3       # CPU 使用率
sar -r 1 3       # 内存使用
sar -b 1 3       # I/O 统计
sar -n DEV 1 3   # 网络接口统计

# 查看历史 sar 数据
sar -u -f /var/log/sysstat/sa$(date +%d -d yesterday)

5.5 dstat(多功能综合监控)

# 安装
sudo apt install dstat

# 综合监控(CPU、磁盘、网络、内存)
dstat

# 高级用法
dstat -cdnm --top-cpu --top-mem 5    # 每 5 秒采样,显示 top 进程
dstat -tcmdn 1                       # 带时间戳的综合视图

6. 日志分析

6.1 日志体系

Linux 系统日志主要分为:

  • systemd-journal:二进制日志,由 journald 管理
  • rsyslog:传统文本日志,写入 /var/log/ 目录
  • 应用日志:各应用自行管理
# 常见日志文件
/var/log/syslog          # 系统日志(Debian/Ubuntu)
/var/log/messages        # 系统日志(RHEL/CentOS)
/var/log/auth.log        # 认证日志(Debian/Ubuntu)
/var/log/secure          # 认证日志(RHEL/CentOS)
/var/log/kern.log        # 内核日志
/var/log/dmesg           # 启动硬件信息
/var/log/cron.log        # 定时任务日志
/var/log/nginx/          # Nginx 日志

6.2 journalctl 高级用法

# 查看本次启动日志
journalctl -b

# 查看上次启动日志
journalctl -b -1

# 查看内核消息
journalctl -k

# 按服务过滤
journalctl -u nginx -u php-fpm

# 按 PID 过滤
journalctl _PID=1234

# 按可执行文件过滤
journalctl /usr/bin/nginx

# 输出为 JSON 格式
journalctl -u nginx -o json-pretty

# 输出带精确时间戳
journalctl -u nginx -o short-precise

# 只显示新日志(类似 tail -f)
journalctl -u nginx -f

# 高亮错误
journalctl -p err --no-pager

# 指定输出行数
journalctl -n 50 --no-pager

6.3 logrotate 日志轮转

logrotate 防止日志文件无限增长。配置文件位于 /etc/logrotate.conf/etc/logrotate.d/

# 查看现有配置
cat /etc/logrotate.conf
ls /etc/logrotate.d/

创建自定义轮转配置 /etc/logrotate.d/myapp

/var/log/myapp/*.log {
    daily                # 每天轮转
    rotate 30            # 保留 30 个
    compress             # gzip 压缩
    delaycompress        # 延迟一次再压缩
    missingok            # 文件不存在不报错
    notifempty           # 空文件不轮转
    dateext              # 用日期作为后缀
    dateformat -%Y%m%d   # 日期格式
    create 0644 appuser appgroup

    postrotate
        # 轮转后通知应用重新打开日志文件
        systemctl reload myapp > /dev/null 2>&1 || true
    endscript
}
# 手动测试轮转(不实际执行)
sudo logrotate -d /etc/logrotate.d/myapp

# 强制执行轮转
sudo logrotate -f /etc/logrotate.d/myapp

# 查看轮转状态
cat /var/lib/logrotate/status

6.4 实用日志分析技巧

# 统计 Nginx 访问 IP 排名
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head 20

# 查找 4xx/5xx 错误
awk '$9 >= 400 {print $9, $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn

# 查看 SSH 登录失败
grep "Failed password" /var/log/auth.log | awk '{print $(NF-3)}' | sort | uniq -c | sort -rn | head

# 实时监控错误日志
tail -f /var/log/syslog | grep -i error

# 用 grep 过滤时间范围
grep "May 28 08:" /var/log/syslog

# 使用 awk 提取特定时间段
awk '/May 28 08:[0-2][0-9]/' /var/log/syslog

7. 自动化脚本(Bash 编程)

7.1 脚本规范模板

#!/usr/bin/env bash
#
# 脚本名称: deploy.sh
# 描述: 自动化部署脚本
# 用法: ./deploy.sh [选项] <参数>
# 版本: 1.0.0
# 作者: ops-team

set -euo pipefail    # e:出错退出 u:未定义变量报错 o pipefail:管道错误捕获
trap cleanup EXIT     # 退出时执行清理函数

# === 配置 ===
readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly LOG_FILE="/var/log/deploy.log"
readonly LOCK_FILE="/var/run/deploy.lock"

# === 函数 ===
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG_FILE"
}

error() {
    log "ERROR: $*" >&2
    exit 1
}

cleanup() {
    rm -f "$LOCK_FILE"
    log "清理完成"
}

check_lock() {
    if [[ -f "$LOCK_FILE" ]]; then
        error "另一个实例正在运行,PID: $(cat "$LOCK_FILE")"
    fi
    echo $$ > "$LOCK_FILE"
}

# === 主流程 ===
main() {
    check_lock
    log "部署开始"

    # 业务逻辑...

    log "部署完成"
}

main "$@"

7.2 条件与循环

# 条件判断
if [[ -f "/etc/nginx/nginx.conf" ]]; then
    echo "Nginx 已安装"
elif [[ -f "/etc/apache2/apache2.conf" ]]; then
    echo "Apache 已安装"
else
    echo "未检测到 Web 服务器"
fi

# 数值比较
disk_usage=$(df / | awk 'NR==2 {print $5}' | tr -d '%')
if (( disk_usage > 80 )); then
    echo "磁盘使用率 ${disk_usage}%,超过阈值!"
fi

# 字符串匹配
if [[ "$1" =~ ^[0-9]+$ ]]; then
    echo "参数是数字"
fi

# case 语句
case "$1" in
    start)   start_service ;;
    stop)    stop_service ;;
    restart) stop_service; start_service ;;
    status)  check_status ;;
    *)       echo "用法: $0 {start|stop|restart|status}" ;;
esac

# for 循环
for server in web01 web02 web03; do
    echo "部署到 $server..."
    ssh "$server" 'sudo systemctl restart nginx'
done

# while 循环读取文件
while IFS=',' read -r name ip role; do
    echo "主机: $name, IP: $ip, 角色: $role"
done < hosts.csv

# C 风格 for
for ((i=1; i<=10; i++)); do
    echo "第 $i 次重试..."
    curl -sf http://localhost/health && break
    sleep 2
done

7.3 数组与关联数组

# 索引数组
services=("nginx" "mysql" "redis" "php-fpm")
for svc in "${services[@]}"; do
    sudo systemctl status "$svc" --no-pager
done

# 关联数组(Bash 4+)
declare -A servers=(
    ["web01"]="192.168.1.10"
    ["web02"]="192.168.1.11"
    ["db01"]="192.168.1.20"
)

for name in "${!servers[@]}"; do
    echo "$name -> ${servers[$name]}"
done

7.4 文本处理

# awk:统计每个状态码数量
awk '{status[$9]++} END {for(s in status) print s, status[s]}' access.log | sort -k2 -rn

# sed:批量替换配置
sudo sed -i 's/^#\s*max_connections.*/max_connections = 500/' /etc/mysql/my.cnf

# 多行处理
awk '/BEGIN/{p=1} p; /END/{p=0}' config.txt

# 参数扩展
filename="report.tar.gz"
echo "${filename%.tar.gz}"     # report(去掉后缀)
echo "${filename##*.}"         # gz(取最后后缀)
echo "${filename^^}"           # REPORT.TAR.GZ(转大写)

# Here Document
cat <<'EOF' > /etc/nginx/conf.d/app.conf
server {
    listen 80;
    server_name example.com;
    root /var/www/app;
}
EOF

7.5 并发与进程管理

# 后台并发执行
for host in web0{1..5}; do
    ssh "$host" 'uptime' &
done
wait    # 等待所有后台任务完成
echo "全部完成"

# 使用 xargs 并发
cat hosts.txt | xargs -P 4 -I {} ssh {} 'uname -r'

# 进程替换
diff <(ssh web01 'cat /etc/nginx/nginx.conf') \
     <(ssh web02 'cat /etc/nginx/nginx.conf')

# 信号处理
trap 'echo "收到 SIGINT,正在退出..."; exit 1' INT
trap 'echo "收到 SIGTERM"; exit 0' TERM

# 超时控制
timeout 10 ssh web01 'heavy-command'
if [[ $? -eq 124 ]]; then
    echo "命令超时"
fi

7.6 调试技巧

# 开启调试模式
bash -x script.sh          # 执行时打印每行命令
set -x                     # 脚本中局部开启
set +x                     # 关闭

# 语法检查(不执行)
bash -n script.sh

# shellcheck 静态分析
shellcheck script.sh

# 自定义调试函数
debug() {
    [[ "${DEBUG:-0}" == "1" ]] && echo "[DEBUG] $*" >&2
}
# 使用: DEBUG=1 ./script.sh

8. 软件包管理

8.1 APT(Debian/Ubuntu)

# 更新包索引
sudo apt update

# 升级所有包
sudo apt upgrade
sudo apt full-upgrade     # 处理依赖变更

# 搜索包
apt search nginx
apt list --installed | grep nginx

# 查看包信息
apt show nginx

# 安装/卸载
sudo apt install nginx
sudo apt remove nginx           # 保留配置
sudo apt purge nginx            # 删除配置

# 清理
sudo apt autoremove             # 删除无用依赖
sudo apt clean                  # 清理下载缓存

# 锁定版本(防止自动升级)
sudo apt-mark hold nginx
sudo apt-mark unhold nginx
apt-mark showhold

# 安装本地 deb 包
sudo dpkg -i package.deb
sudo apt install -f             # 修复依赖

# 查看包安装的文件
dpkg -L nginx

# 查看文件属于哪个包
dpkg -S /usr/sbin/nginx

# 添加 PPA(Ubuntu)
sudo add-apt-repository ppa:ondrej/php
sudo apt update

8.2 YUM/DNF(RHEL/CentOS/Fedora)

# 搜索
yum search nginx

# 查看包信息
yum info nginx

# 安装/卸载
sudo yum install nginx
sudo yum remove nginx

# 更新
sudo yum update
sudo yum update nginx        # 只更新指定包

# 列出已安装
yum list installed

# 查看包提供的文件
rpm -ql nginx

# 查看文件属于哪个包
rpm -qf /usr/sbin/nginx

# 清理缓存
sudo yum clean all

# 管理仓库
yum repolist all
sudo yum-config-manager --add-repo https://example.com/repo.rpm

# DNF(Fedora/RHEL 8+,YUM 的替代品)
sudo dnf install nginx
sudo dnf module list               # 模块化管理
sudo dnf module enable php:8.1

8.3 Snap / Flatpak

# Snap(Ubuntu 默认)
snap find vlc
sudo snap install vlc
snap list
sudo snap refresh
sudo snap remove vlc

# Flatpak(Fedora 默认)
flatpak search gimp
flatpak install flathub org.gimp.GIMP
flatpak list
flatpak update

9. 内核参数调优

9.1 sysctl 基础

# 查看所有内核参数
sysctl -a

# 查看单个参数
sysctl net.ipv4.ip_forward
sysctl vm.swappiness

# 临时修改(重启失效)
sudo sysctl -w vm.swappiness=10
sudo sysctl -w net.core.somaxconn=65535

# 永久修改:编辑 /etc/sysctl.d/99-custom.conf
sudo tee /etc/sysctl.d/99-custom.conf <<'EOF'
# === 网络优化 ===
# TCP 连接队列大小
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
# 启用 TCP Fast Open
net.ipv4.tcp_fastopen = 3
# TIME_WAIT 快速回收
net.ipv4.tcp_tw_reuse = 1
# 增大本地端口范围
net.ipv4.ip_local_port_range = 1024 65535
# TCP 缓冲区
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 87380 16777216

# === 内存优化 ===
# 减少 swap 使用倾向
vm.swappiness = 10
# 控制内核回收脏页的阈值
vm.dirty_ratio = 15
vm.dirty_background_ratio = 5
# 允许内存过量分配(对数据库有利)
vm.overcommit_memory = 1

# === 文件系统 ===
# 增加文件描述符限制
fs.file-max = 2097152
fs.inotify.max_user_watches = 524288

# === 安全 ===
# 禁用 ICMP 重定向
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
# 启用 SYN Cookie(防 SYN Flood)
net.ipv4.tcp_syncookies = 1
EOF

# 应用配置
sudo sysctl --system

9.2 文件描述符限制

# 查看当前限制
ulimit -n

# 临时修改
ulimit -n 65535

# 永久修改 /etc/security/limits.conf
sudo tee -a /etc/security/limits.conf <<'EOF'
*         soft    nofile    65535
*         hard    nofile    65535
root      soft    nofile    65535
root      hard    nofile    65535
*         soft    nproc     65535
*         hard    nproc     65535
EOF

# systemd 服务的限制在 unit 文件中设置
# LimitNOFILE=65535

9.3 I/O 调度器

# 查看当前调度器
cat /sys/block/sda/queue/scheduler

# 临时切换
echo "mq-deadline" | sudo tee /sys/block/sda/queue/scheduler

# SSD 推荐 none/noop,HDD 推荐 mq-deadline
# 永久设置(udev 规则)
sudo tee /etc/udev/rules.d/60-ioscheduler.rules <<'EOF'
# SSD 使用 none
ACTION=="add|change", KERNEL=="sd[a-z]", ATTR{queue/rotational}=="0", ATTR{queue/scheduler}="none"
# HDD 使用 mq-deadline
ACTION=="add|change", KERNEL=="sd[a-z]", ATTR{queue/rotational}=="1", ATTR{queue/scheduler}="mq-deadline"
EOF

9.4 NUMA 与 CPU 亲和性

# 查看 NUMA 拓扑
numactl --hardware

# 在特定 NUMA 节点运行程序
numactl --cpunodebind=0 --membind=0 ./myapp

# 设置进程 CPU 亲和性
taskset -c 0,1,2,3 ./myapp              # 绑定到 CPU 0-3
taskset -cp 0-3 <PID>                   # 对运行中的进程设置

10. 容器化基础

10.1 Docker 安装与基本操作

# 安装 Docker(Ubuntu)
# 注意:实际安装请参考 Docker 官方文档的最新步骤
sudo apt update
sudo apt install docker.io
sudo systemctl enable --now docker
sudo usermod -aG docker $USER    # 将当前用户加入 docker 组(需重新登录)

# 镜像操作
docker pull nginx:latest
docker images
docker rmi nginx:latest
docker image prune -a             # 清理未使用的镜像

# 容器操作
docker run -d --name web -p 8080:80 nginx    # 后台运行,端口映射
docker ps                                      # 运行中的容器
docker ps -a                                   # 所有容器
docker logs -f web                             # 查看日志
docker exec -it web bash                       # 进入容器
docker stop web
docker start web
docker rm web

# 清理
docker system prune -a    # 清理所有未使用的资源

10.2 Dockerfile 编写

# 多阶段构建示例
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build

FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
HEALTHCHECK --interval=30s --timeout=3s \
    CMD wget -qO- http://localhost/ || exit 1
CMD ["nginx", "-g", "daemon off;"]
# 构建镜像
docker build -t myapp:v1 .

# 运行
docker run -d -p 8080:80 --name myapp myapp:v1

10.3 Docker Compose

# docker-compose.yml
version: '3.8'

services:
  web:
    build: .
    ports:
      - "8080:80"
    depends_on:
      - api
    restart: unless-stopped

  api:
    image: node:20-alpine
    working_dir: /app
    volumes:
      - ./api:/app
    command: node server.js
    environment:
      - DB_HOST=db
      - DB_PORT=5432
    depends_on:
      db:
        condition: service_healthy

  db:
    image: postgres:16-alpine
    volumes:
      - pgdata:/var/lib/postgresql/data
    environment:
      POSTGRES_DB: myapp
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 5
    secrets:
      - db_password

volumes:
  pgdata:

secrets:
  db_password:
    file: ./secrets/db_password.txt
# 常用命令
docker compose up -d          # 后台启动
docker compose down            # 停止并删除
docker compose logs -f         # 查看日志
docker compose ps              # 查看状态
docker compose exec api sh     # 进入容器
docker compose up -d --build   # 重新构建并启动

10.4 容器资源限制

# 限制 CPU 和内存
docker run -d \
    --cpus="1.5" \
    --memory="512m" \
    --memory-swap="1g" \
    --name app myapp:v1

# 查看容器资源使用
docker stats
docker stats --no-stream app

10.5 Podman(Docker 替代品)

# Podman 无需守护进程,兼容 Docker CLI
podman pull nginx:latest
podman run -d -p 8080:80 --name web nginx:latest
podman ps
podman logs web

# 生成 systemd 服务文件
podman generate systemd --new --name web > /etc/systemd/system/web.service
sudo systemctl daemon-reload
sudo systemctl enable --now web

11. 实战项目:自动化运维监控系统

本节综合运用前述知识,构建一个实用的服务器监控脚本,实现 CPU、内存、磁盘、服务状态的自动检测和告警。

11.1 监控脚本

#!/usr/bin/env bash
#
# monitor.sh - 服务器自动监控脚本
# 功能:检测系统资源和服务状态,超阈值发送告警
# 用法:./monitor.sh [--config /path/to/config]

set -euo pipefail

# === 配置 ===
readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly CONFIG_FILE="${1:-${SCRIPT_DIR}/monitor.conf}"
readonly LOG_DIR="/var/log/monitor"
readonly LOG_FILE="${LOG_DIR}/monitor-$(date +%Y%m%d).log"
readonly LOCK_FILE="/var/run/monitor.lock"
readonly ALERT_COOLDOWN_FILE="/tmp/monitor_alert_cooldown"

# 默认阈值(可被配置文件覆盖)
CPU_THRESHOLD=80
MEM_THRESHOLD=85
DISK_THRESHOLD=90
LOAD_THRESHOLD=$(nproc)
SERVICES=("nginx" "mysql" "redis")

# 告警配置
ALERT_METHOD="log"          # log | webhook | email
WEBHOOK_URL=""
ALERT_EMAIL=""
COOLDOWN_SECONDS=300        # 相同告警冷却时间(秒)

# === 初始化 ===
init() {
    mkdir -p "$LOG_DIR"
    
    # 加载配置文件
    if [[ -f "$CONFIG_FILE" ]]; then
        # shellcheck source=/dev/null
        source "$CONFIG_FILE"
        log "INFO" "已加载配置文件: $CONFIG_FILE"
    fi

    # 检查锁
    if [[ -f "$LOCK_FILE" ]]; then
        local pid
        pid=$(cat "$LOCK_FILE")
        if kill -0 "$pid" 2>/dev/null; then
            echo "另一个实例正在运行 (PID: $pid)"
            exit 0
        fi
    fi
    echo $$ > "$LOCK_FILE"
    trap 'rm -f "$LOCK_FILE"' EXIT
}

# === 日志函数 ===
log() {
    local level="$1"
    shift
    local msg="[$(date '+%Y-%m-%d %H:%M:%S')] [${level}] $*"
    echo "$msg" >> "$LOG_FILE"
    [[ "$level" == "ERROR" || "$level" == "WARN" ]] && echo "$msg" >&2
}

# === 告警冷却检查 ===
should_alert() {
    local alert_key="$1"
    local now
    now=$(date +%s)
    local cooldown_file="${ALERT_COOLDOWN_FILE}_${alert_key}"

    if [[ -f "$cooldown_file" ]]; then
        local last_alert
        last_alert=$(cat "$cooldown_file")
        if (( now - last_alert < COOLDOWN_SECONDS )); then
            return 1    # 冷却中,不发送
        fi
    fi

    echo "$now" > "$cooldown_file"
    return 0
}

# === 告警发送 ===
send_alert() {
    local subject="$1"
    local body="$2"
    local alert_key
    alert_key=$(echo "$subject" | md5sum | cut -c1-8)

    if ! should_alert "$alert_key"; then
        log "DEBUG" "告警冷却中,跳过: $subject"
        return
    fi

    log "WARN" "告警: $subject - $body"

    case "$ALERT_METHOD" in
        webhook)
            send_webhook "$subject" "$body"
            ;;
        email)
            send_email "$subject" "$body"
            ;;
        log)
            # 仅记录日志(默认)
            ;;
    esac
}

send_webhook() {
    local payload
    payload=$(cat <<EOF
{
    "msg_type": "text",
    "content": {
        "text": "[告警] $1\n$2\n主机: $(hostname)\n时间: $(date '+%Y-%m-%d %H:%M:%S')"
    }
}
EOF
)
    curl -s -X POST "$WEBHOOK_URL" \
        -H "Content-Type: application/json" \
        -d "$payload" > /dev/null 2>&1 || log "ERROR" "Webhook 发送失败"
}

send_email() {
    echo "$2" | mail -s "[监控告警] $1" "$ALERT_EMAIL" 2>/dev/null \
        || log "ERROR" "邮件发送失败"
}

# === 检测函数 ===
check_cpu() {
    local cpu_usage
    cpu_usage=$(top -bn1 | grep "Cpu(s)" | awk '{print int($2 + $4)}')

    if (( cpu_usage > CPU_THRESHOLD )); then
        send_alert "CPU 使用率过高" "当前: ${cpu_usage}%,阈值: ${CPU_THRESHOLD}%"
        # 输出 Top 5 CPU 进程
        ps aux --sort=-%cpu | head -6 >> "$LOG_FILE"
    fi
    log "INFO" "CPU: ${cpu_usage}%"
}

check_memory() {
    local mem_total mem_available mem_usage
    mem_total=$(grep MemTotal /proc/meminfo | awk '{print $2}')
    mem_available=$(grep MemAvailable /proc/meminfo | awk '{print $2}')
    mem_usage=$(( (mem_total - mem_available) * 100 / mem_total ))

    if (( mem_usage > MEM_THRESHOLD )); then
        send_alert "内存使用率过高" "当前: ${mem_usage}%,阈值: ${MEM_THRESHOLD}%"
        ps aux --sort=-%mem | head -6 >> "$LOG_FILE"
    fi
    log "INFO" "内存: ${mem_usage}%"
}

check_disk() {
    while read -r mount usage; do
        usage=${usage%\%}
        if (( usage > DISK_THRESHOLD )); then
            send_alert "磁盘空间不足" "挂载点: ${mount},使用率: ${usage}%,阈值: ${DISK_THRESHOLD}%"
        fi
        log "INFO" "磁盘 ${mount}: ${usage}%"
    done < <(df -h --output=target,pcent -x tmpfs -x devtmpfs | tail -n +2)
}

check_load() {
    local load_1m
    load_1m=$(awk '{print int($1)}' /proc/loadavg)

    if (( load_1m > LOAD_THRESHOLD )); then
        send_alert "系统负载过高" "1 分钟负载: ${load_1m},阈值: ${LOAD_THRESHOLD}"
    fi
    log "INFO" "负载: ${load_1m}"
}

check_services() {
    for svc in "${SERVICES[@]}"; do
        if ! systemctl is-active --quiet "$svc" 2>/dev/null; then
            send_alert "服务异常" "服务 ${svc} 未运行!"
            # 自动尝试重启
            log "WARN" "尝试重启 $svc..."
            if sudo systemctl restart "$svc" 2>/dev/null; then
                log "INFO" "$svc 重启成功"
            else
                log "ERROR" "$svc 重启失败"
            fi
        else
            log "INFO" "服务 ${svc}: 运行中"
        fi
    done
}

check_zombie() {
    local zombie_count
    zombie_count=$(ps aux | awk '$8 ~ /Z/ {count++} END {print count+0}')

    if (( zombie_count > 5 )); then
        send_alert "僵尸进程过多" "数量: ${zombie_count}"
    fi
}

# === 生成报告 ===
generate_report() {
    local report_file="${LOG_DIR}/report-$(date +%Y%m%d_%H%M%S).txt"

    {
        echo "=============================="
        echo "  服务器状态报告"
        echo "  主机: $(hostname)"
        echo "  时间: $(date '+%Y-%m-%d %H:%M:%S')"
        echo "  运行: $(uptime -p)"
        echo "=============================="
        echo ""
        echo "--- CPU ---"
        top -bn1 | head -5
        echo ""
        echo "--- 内存 ---"
        free -h
        echo ""
        echo "--- 磁盘 ---"
        df -hT
        echo ""
        echo "--- 网络连接 ---"
        ss -s
        echo ""
        echo "--- 最近登录 ---"
        last -5
    } > "$report_file"

    log "INFO" "报告已生成: $report_file"
}

# === 主流程 ===
main() {
    init
    log "INFO" "===== 监控检查开始 ====="

    check_cpu
    check_memory
    check_disk
    check_load
    check_services
    check_zombie

    log "INFO" "===== 监控检查完成 ====="
}

# 支持 --report 参数生成完整报告
if [[ "${1:-}" == "--report" ]]; then
    generate_report
    exit 0
fi

main "$@"

11.2 配置文件

创建 monitor.conf

# monitor.conf - 监控配置

# 阈值设置
CPU_THRESHOLD=80
MEM_THRESHOLD=85
DISK_THRESHOLD=90
LOAD_THRESHOLD=4

# 监控的服务列表
SERVICES=("nginx" "mysql" "redis")

# 告警方式: log | webhook | email
ALERT_METHOD="webhook"
WEBHOOK_URL="https://open.feishu.cn/open-apis/bot/v2/hook/your-token-here"
# ALERT_EMAIL="ops@example.com"

# 告警冷却时间(秒)
COOLDOWN_SECONDS=300

11.3 部署为 systemd 服务

创建 /etc/systemd/system/monitor.service

[Unit]
Description=Server Monitor Service
After=network.target

[Service]
Type=oneshot
ExecStart=/opt/monitor/monitor.sh --config /opt/monitor/monitor.conf
User=root

[Install]
WantedBy=multi-user.target

创建 /etc/systemd/system/monitor.timer

[Unit]
Description=Run Monitor Every 5 Minutes

[Timer]
OnBootSec=1min
OnUnitActiveSec=5min
AccuracySec=10s

[Install]
WantedBy=timers.target
# 部署
sudo mkdir -p /opt/monitor
sudo cp monitor.sh monitor.conf /opt/monitor/
sudo chmod +x /opt/monitor/monitor.sh

sudo systemctl daemon-reload
sudo systemctl enable --now monitor.timer

# 验证
systemctl list-timers monitor.timer
journalctl -u monitor -n 20

11.4 扩展:日志分析自动化

#!/usr/bin/env bash
# log_analyzer.sh - 自动分析常见日志并生成报告

readonly REPORT="/tmp/log_analysis_$(date +%Y%m%d).txt"

{
    echo "=== 日志分析报告 $(date) ==="
    echo ""

    echo "--- SSH 登录失败 Top 10 IP ---"
    grep "Failed password" /var/log/auth.log 2>/dev/null \
        | awk '{print $(NF-3)}' | sort | uniq -c | sort -rn | head -10

    echo ""
    echo "--- Nginx 状态码统计 ---"
    awk '{print $9}' /var/log/nginx/access.log 2>/dev/null \
        | sort | uniq -c | sort -rn

    echo ""
    echo "--- 磁盘空间趋势 ---"
    df -h | grep -v tmpfs

    echo ""
    echo "--- 最近内核错误 ---"
    dmesg | grep -i error | tail -10

} > "$REPORT"

echo "报告已生成: $REPORT"

总结

本教程涵盖了 Linux 系统管理的核心进阶知识:

章节 关键技能
系统启动 理解 BIOS→GRUB→内核→systemd 全流程
systemd 服务管理、自定义单元、Timer 替代 cron
磁盘与 LVM 分区、LVM 弹性管理、快照、扩容
文件系统 格式化、挂载、fstab、空间管理
性能监控 top/vmstat/iostat 综合分析
日志分析 journalctl、logrotate、日志挖掘
Bash 编程 规范脚本、并发、调试
软件包管理 apt/yum/dnf、版本锁定
内核调优 sysctl、文件描述符、I/O 调度
容器化 Docker/Compose/Podman
实战项目 完整监控系统 + systemd 集成

学习建议

  1. 动手实践:在虚拟机或测试环境中逐一操作每个命令
  2. 阅读手册man--help 是最好的老师
  3. 循序渐进:先在测试环境验证,再应用到生产环境
  4. 记录笔记:将常用命令和踩过的坑记录下来

本教程内容为原创,基于 Linux 系统管理通用知识编写,可自由使用和分享。

内容声明

本文内容为AI技术学习教程,仅供学习参考。如涉及技术问题,欢迎通过 xurj005@163.com 与我们交流。

目录