Linux 系统管理进阶教程
适用读者:已掌握 Linux 基本命令(ls、cd、cp、mv、chmod 等),希望深入系统管理的运维工程师、开发者和技术爱好者。
环境说明:本教程以主流发行版为主,Debian/Ubuntu 系使用
apt,RHEL/CentOS 系使用yum/dnf,命令示例会分别标注。
目录
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 集成 |
学习建议:
- 动手实践:在虚拟机或测试环境中逐一操作每个命令
- 阅读手册:
man和--help是最好的老师 - 循序渐进:先在测试环境验证,再应用到生产环境
- 记录笔记:将常用命令和踩过的坑记录下来
本教程内容为原创,基于 Linux 系统管理通用知识编写,可自由使用和分享。