CentOS 7 - 10 常规运维指令手册

运维指令手册 43.3 KB 原文

CentOS 7 - 10 常规运维指令手册

适用版本:CentOS 7 / CentOS 8(含 Stream 8)/ CentOS Stream 9 / CentOS Stream 10 约定:$ 普通用户,# root 或 sudo,<xxx> 为占位符。 差异标注:正文中用 > **版本差异** 引用块标注跨版本不一致之处,无标注表示各版本通用。


目录

  1. 版本概览与差异总览
  2. 系统信息与状态
  3. 用户与权限管理
  4. 文件与目录操作
  5. 磁盘与文件系统
  6. 软件包管理:yum / dnf / dnf5
  7. 服务与 systemd
  8. 进程与资源管理
  9. 网络配置
  10. firewalld 防火墙
  11. SELinux
  12. 日志与排障
  13. 定时任务
  14. 压缩、备份与传输
  15. 性能监控与调优
  16. SSH 与远程运维
  17. 高频故障速查表
  18. 版本生命周期与迁移路径
  19. 危险命令与避坑清单

1. 版本概览与差异总览

1.1 版本对照

项目 CentOS 7 CentOS 8 Stream 9 Stream 10
发布/状态 2014,2024-06-30 EOL 2019,2021-12-31 EOL 2021-12 起,滚动更新 2024-12 起
对应 RHEL 7 8 9 10
内核 3.10 4.18 5.14 6.12
包管理器 yum(Python 2) dnf(Python 3) dnf dnf5(C++)
默认文件系统 XFS XFS XFS XFS
默认 Python 2.7 3.6(平台)+ 可选 3.11 3.9 3.12
防火墙后端 iptables nftables nftables nftables(iptables 兼容层弱化)
网络配置 network-scripts(ifcfg) NetworkManager(ifcfg 插件,弃用) NetworkManager(keyfile) NetworkManager(keyfile)
默认容器 docker(第三方) podman / buildah podman podman
systemd 219 239 252 257
模块流 module 不支持 支持 支持 支持(dnf5 语法)
dbus / 会话 传统 传统 默认 cgroup v2 默认 cgroup v2

1.2 运维必须知道的五个断点

  1. 包管理命令层:yum 在 8+ 是 dnf 的软链,命令基本通用;但 Stream 10 是 dnf5,部分子命令输出和参数不同(见 6.6)。
  2. 网络配置文件换了位置:7 的 /etc/sysconfig/network-scripts/ifcfg-* 在 8 弃用、9 起完全移除。必须改用 nmcli 或 keyfile。
  3. firewalld 后端换了:规则写法不变,但底层的 iptables -L 在 8+ 看不到完整规则,要用 nft list ruleset。
  4. netstat / ifconfig / lsof 默认不装:7 起就已经精简,用 ss / ip / lsof(需装 net-tools、lsof)。
  5. SELinux 全程开启:CentOS 与 Ubuntu 最大的运维差异。禁用 SELinux 不是解决方案,是埋雷(见第 11 章)。

1.3 版本识别

cat /etc/centos-release          # CentOS Linux release 7.9.2009 (Core) / CentOS Stream release 9
cat /etc/redhat-release          # 同上(RHEL 系通用)
cat /etc/os-release              # 最可靠,含 VERSION_ID="9"
rpm -E %{rhel}                   # 输出 7 / 8 / 9 / 10,写脚本判断版本的首选
uname -r                         # 内核:3.10 / 4.18 / 5.14 / 6.12

脚本中判断版本:

RHEL_VER=$(rpm -E %{rhel})
if [ "$RHEL_VER" -ge 8 ]; then echo "dnf 时代"; else echo "yum 时代"; fi

2. 系统信息与状态

2.1 版本与主机

hostnamectl                                    # 主机名、OS、内核、虚拟化
hostnamectl set-hostname web01                 # 永久改主机名(立即生效)
hostname                                       # 当前主机名
uname -a
uname -r
getconf LONG_BIT                               # 64

2.2 硬件资源

lscpu                              # CPU 型号、核心、NUMA
free -h                            # 内存(-m 兆、-g 吉)
lsblk -f                           # 块设备 + 文件系统 + UUID
lspci | grep -i -E 'eth|vga'       # 网卡 / 显卡
lsusb
dmidecode -t system | grep -E 'Manufacturer|Product'    # 需 root
nproc                              # 逻辑核数

2.3 负载与运行状态

uptime                             # 负载:1/5/15 分钟
who -b                             # 上次启动时间
last reboot | head -5
w                                  # 在线用户 + 正在执行的命令
vmstat 1 5                         # 见 15.2

负载判读:CentOS 7 的负载包含不可中断进程(IO 等待),负载高但 CPU 空闲通常意味着磁盘卡住,查 vmstat 的 b 列和 iostat 的 %util。

2.4 时间同步(chrony)

timedatectl                        # 时区、NTP 同步状态
chronyc tracking                   # 当前同步精度、偏差
chronyc sources -v                 # 时间源列表与状态
chronyc sourcestats -v
sudo chronyc makestep              # 立即强制校时(跳变,慎用于数据库主机)

sudo timedatectl set-timezone Asia/Shanghai
sudo systemctl enable --now chronyd

/etc/chrony.conf 关键项:

pool ntp.aliyun.com iburst
makestep 1.0 3
rtcsync

版本差异:CentOS 7 时代同时支持 ntpd 与 chronyd,默认 chronyd;8+ 只保留 chrony,不要再试图装 ntpd。


3. 用户与权限管理

3.1 用户操作

id <user>
getent passwd <user>
who; w; last -n 20

# 创建
sudo useradd -m -s /bin/bash <user>
sudo useradd -r -s /sbin/nologin -M <svcuser>    # 服务账号:无家目录、不可登录
sudo passwd <user>
echo '<user>:<password>' | sudo chpasswd         # 批量设置(脚本用,注意安全)

# 修改
sudo usermod -aG wheel <user>        # 加入 wheel 组获得 sudo 权限(CentOS 默认组)
sudo usermod -aG docker <user>       # ⚠️ 必须带 -a
sudo usermod -L <user>               # 锁定
sudo usermod -U <user>
sudo usermod -s /sbin/nologin <user>
sudo usermod -d /new/home -m <user>

# 删除
sudo userdel -r <user>

CentOS 与 Ubuntu 的组差异:CentOS 提权组是 wheel,Ubuntu 是 sudo。把用户加进 sudo 组在 CentOS 上无效。

3.2 密码策略

sudo chage -l <user>
sudo chage -M 90 -W 7 <user>          # 90 天有效期,提前 7 天警告
sudo chage -d 0 <user>                # 强制下次登录改密
sudo passwd -e <user>                 # 同上

全局默认在 /etc/login.defs;复杂度策略用 authconfig(7)或 authselect(8+):

# 7
sudo authconfig --passminlen=10 --passminclass=3 --update

# 8+
sudo authselect select sssd with-pwquality --force

版本差异:authconfig 在 8 起被 authselect 取代。在 9/10 上装 authconfig 只是为了兼容,不应继续使用。

3.3 提权(sudo)

sudo visudo                        # 安全编辑 /etc/sudoers
sudo visudo -f /etc/sudoers.d/ops  # 推荐:分文件
sudo -l                            # 查看当前权限
sudo -u <user> <cmd>
sudo -i                            # 切 root 环境

/etc/sudoers.d/ops:

ops ALL=(root) NOPASSWD: /usr/bin/systemctl restart nginx, /usr/bin/firewall-cmd --reload
%wheel ALL=(ALL) ALL

版本差异:Stream 10 引入 sudo-rs(Rust 重实现)作为 sudo 的替代路径,命令行用法保持一致,但极少数边缘语法行为可能不同;自研脚本依赖 sudo -E、sudoedit 等特性时建议在 Stream 10 上实测。

3.4 权限与特殊位

chmod 755 /opt/app
chmod 644 /etc/myapp/conf.ini
chown -R app:app /opt/app
umask                              # 默认 0022

# SUID / SGID / Sticky
chmod u+s <file>                   # SUID:以文件所有者身份运行
chmod g+s <dir>                    # SGID:目录下新文件继承目录属组
chmod +t /shared                   # Sticky:只能删自己的文件

# ACL
sudo dnf install acl -y
setfacl -m u:alice:rw /data/report.csv
getfacl /data/report.csv
setfacl -b /data/report.csv

# 不可变属性(防误删/防篡改)
sudo chattr +i /etc/passwd
lsattr /etc/passwd

# 检查异常 SUID(安全巡检)
sudo find / -perm -4000 -type f 2>/dev/null

4. 文件与目录操作

4.1 浏览与查找

ls -alh; ls -lhS; ls -lht
tree -L 2 -d
stat <file>
realpath <path>
findmnt

find /var/log -name "*.log" -size +100M
find / -type f -mtime -7 -name "*.conf"
find /tmp -type f -mmin +60 -delete
find /data -type d -empty
find . -type f -exec ls -lh {} \;
find . -name "*.log" -print0 | xargs -0 gzip

grep -rn "listen 8080" /etc/nginx/

locate 在 CentOS 上需装 mlocate,并 sudo updatedb 建库。生产环境常禁用(IO 抖动),优先用 find 或 grep -r。

4.2 复制、移动、删除

cp -a /src/. /dst/                 # 复制内容(含隐藏文件),保留属性
cp -a /src /dst/                   # 会在 dst 下建 src 目录(易错)
mv <src> <dst>
rm -i <file>
ln -s /opt/app/releases/v1.2 /opt/app/current

mkdir -p /data/app/{logs,conf,tmp}

4.3 文本处理

less +F /var/log/messages
tail -F /var/log/secure            # 轮转后仍跟踪
tail -n 200 /var/log/messages

grep -vE '^\s*#|^\s*$' /etc/ssh/sshd_config   # 去注释与空行
grep -A3 -B3 "error" app.log
awk '{print $1}' access.log | sort | uniq -c | sort -rn | head
awk '$9==502' access.log | wc -l
sed -n '100,200p' <file>
sed -i.bak 's/old/new/g' <file>    # 带备份的原地替换(生产推荐)
cut -d: -f1 /etc/passwd
sort -u <file> | wc -l

CentOS 与 Ubuntu 的 sed 差异:GNU sed 行为一致,无需像 macOS 那样加 ''。但 sed -i 不带后缀会直接改原文件,生产上坚持 -i.bak。


5. 磁盘与文件系统

5.1 容量与占用

df -h
df -i                              # inode 用尽:小文件多的场景很常见
du -sh /var/* | sort -rh | head
du -h --max-depth=1 / | sort -rh | head -20
ncdu /var                          # 交互式(需 EPEL)

sudo lsof +L1                      # 已删除仍被占用的文件(磁盘"假满"元凶)

5.2 分区与挂载

lsblk
sudo fdisk -l
sudo parted -l
blkid
findmnt

# 新盘(MBR)
sudo fdisk /dev/sdb                # n → p → 1 → 回车 → w
sudo mkfs.xfs -L data /dev/sdb1    # CentOS 默认 XFS

# 新盘(GPT,>2T)
sudo parted /dev/sdb --script mklabel gpt
sudo parted /dev/sdb --script mkpart primary xfs 0% 100%
sudo mkfs.xfs /dev/sdb1

sudo mkdir -p /data
sudo mount /dev/sdb1 /data

永久挂载 /etc/fstab:

UUID=xxxx-xxxx  /data  xfs  defaults,nofail  0 0
sudo cp /etc/fstab /etc/fstab.bak.$(date +%F)
sudo mount -a                      # 必须验证,否则重启进 emergency

XFS 的 fstab dump/pass 列应为 0 0(fsck 不用于 XFS,用 xfs_repair)。

5.3 扩容

# 分区扩容(云盘在线扩容后)
sudo dnf install -y cloud-utils-growpart
sudo growpart /dev/sda 1
sudo xfs_growfs /                 # XFS 只能扩不能缩
# ext4 用:sudo resize2fs /dev/sda1

# LVM(CentOS 默认安装即为 LVM,重点掌握)
sudo pvs; sudo vgs; sudo lvs
sudo lvextend -l +100%FREE /dev/mapper/centos-root
sudo xfs_growfs /

5.4 LVM 完整操作

# 建:PV → VG → LV
sudo pvcreate /dev/sdc
sudo vgcreate vg_data /dev/sdc
sudo lvcreate -L 200G -n lv_app vg_data
sudo mkfs.xfs /dev/vg_data/lv_app
sudo mount /dev/vg_data/lv_app /opt/app

# 扩
sudo pvcreate /dev/sdd
sudo vgextend vg_data /dev/sdd
sudo lvextend -L +100G /dev/vg_data/lv_app
sudo xfs_growfs /opt/app

# 缩(XFS 不支持缩!只能备份-重建-恢复;ext4 用 lvreduce + resize2fs)
sudo lvreduce -L -50G /dev/vg_data/lv_ext4    # ⚠️ ext4 需先 umount 并 e2fsck

# 快照(备份用)
sudo lvcreate -L 10G -s -n snap_app /dev/vg_data/lv_app
sudo lvremove /dev/vg_data/snap_app

XFS 不能缩容是 CentOS 运维最常见的误判。规划 LV 时宁可留余量,需要缩的场景应改设计或重建。

5.5 swap

swapon --show
free -h
sudo dd if=/dev/zero of=/swapfile bs=1M count=4096
sudo chmod 600 /swapfile
sudo mkswap /swapfile && sudo swapon /swapfile
echo '/swapfile swap swap defaults 0 0' | sudo tee -a /etc/fstab
sudo swapoff /swapfile

版本差异:CentOS 7 的 LVM 布局通常有独立 swap LV;8+ 默认多为 zram 或 swapfile,lsblk 看到的形态不同,不要照搬 7 的文档。

5.6 磁盘健康

sudo dnf install -y smartmontools
sudo smartctl -a /dev/sda
sudo smartctl -t short /dev/sda     # 短自检,结果看 -l selftest
dmesg -T | grep -iE "i/o error|medium error"

6. 软件包管理:yum / dnf / dnf5

6.1 通用命令(7 用 yum,8+ 用 dnf,语法一致)

sudo yum makecache fast      # 7
sudo dnf makecache           # 8+ 刷新元数据

sudo yum install -y <pkg>
sudo dnf install -y <pkg>
sudo dnf install -y <pkg>-<version>          # 指定版本
sudo dnf install -y ./local.rpm              # 本地 rpm(取代 localinstall)

sudo dnf remove <pkg>
sudo dnf autoremove                          # 清理孤立依赖
sudo dnf clean all

dnf list installed | grep <pkg>
dnf list available <pkg>
dnf info <pkg>
dnf search <keyword>
dnf provides */<command>                     # 反查命令属于哪个包(最高频)
dnf repoquery -l <pkg>                       # 包内含哪些文件(未安装也能看)

sudo dnf update                              # 升级全部(7 用 yum update)
sudo dnf update <pkg>
sudo dnf check-update                        # 只检查不升级
sudo dnf distro-sync                         # 同步到仓库当前版本(修复版本错乱)

6.2 仓库管理

dnf repolist
dnf repolist --all
cat /etc/yum.repos.d/*.repo

# 启用/禁用仓库
sudo dnf config-manager --set-enabled <repo>      # 8+
sudo dnf config-manager --set-disabled <repo>
sudo yum-config-manager --enable <repo>           # 7(需 yum-utils)
sudo dnf --disablerepo='*' --enablerepo=epel install <pkg>

# EPEL
sudo dnf install -y epel-release

本地源(离线环境):

# /etc/yum.repos.d/local.repo
[local]
name=Local Repo
baseurl=file:///mnt/cdrom
enabled=1
gpgcheck=0
sudo mount -o loop /dev/sr0 /mnt/cdrom
sudo dnf clean all && sudo dnf makecache

版本差异:7 的仓库地址在 2024-06-30 后失效,需切到 vault.centos.org(见 18.2)。仓库 ID 也从 base/updates 变为 baseos/appstream(8+)。

6.3 模块流 module(8+ 专属)

dnf module list                       # 全部模块流
dnf module list nginx                 # 某软件的可用流
dnf module info nginx:1.22
sudo dnf module enable nginx:1.22
sudo dnf module install nginx:1.22/common
sudo dnf module reset nginx           # 重置回默认
sudo dnf module switch-to nginx:1.24

模块流是 8+ 解决"同一软件多版本并存"的机制。7 完全没有,迁移脚本里遇到 dnf module 要考虑兼容分支。Stream 10 的 dnf5 中模块概念进一步弱化,部分软件改用独立的 repo 提供版本。

6.4 rpm 底层操作

rpm -qa | grep <pkg>              # 已装列表
rpm -qi <pkg>                     # 详情
rpm -ql <pkg>                     # 装了哪些文件
rpm -qf /usr/bin/nginx            # 文件属于哪个包
rpm -qc <pkg>                     # 配置文件列表
rpm -qd <pkg>                     # 文档列表
rpm -V <pkg>                      # 校验文件是否被改动(安全巡检常用)
rpm -Vf /etc/passwd

rpm -ivh <pkg>.rpm                # 安装
rpm -Uvh <pkg>.rpm                # 升级
rpm -e <pkg>                      # 卸载
rpm -e --nodeps <pkg>             # ⚠️ 忽略依赖强删,极易破坏系统
rpm -qp --scripts <pkg>.rpm       # 看安装脚本(安装前审计)

6.5 依赖与事务修复

sudo dnf check                    # 检查依赖问题
sudo dnf --fix-broken install     # 8+ 修复
sudo yum-complete-transaction --cleanup-only   # 7 修复中断的事务
sudo rpm --rebuilddb              # 重建 rpm 数据库(最后手段)
sudo dnf history                  # 事务历史
sudo dnf history undo <id>        # 回滚某次操作(7 同样支持 yum history undo)

6.6 dnf5 变化(Stream 10)

dnf5 --version
dnf5 install <pkg>
dnf5 repo list
dnf5 history list

主要变化:

  • dnf5 为独立二进制,dnf 指向它;不再依赖 Python
  • 输出格式改为更结构化的表格/机器可读格式
  • 部分旧参数被移除或改名(如 --skip-broken 语义变化、module 子命令精简)
  • --allowerasing 等冲突解决行为更严格,脚本跨版本时务必先 --assumeno 试跑

迁移脚本中判断:dnf5 --version &>/dev/null && PM=dnf5 || PM=dnf。

6.7 源码与二进制安装

sudo dnf group install -y "Development Tools"
sudo dnf install -y gcc gcc-c++ make cmake kernel-devel kernel-headers

./configure --prefix=/usr/local/<app>
make -j$(nproc) && sudo make install

# 第三方二进制放 /usr/local/bin 并确认在 PATH 中
echo $PATH | tr ':' '\n' | grep /usr/local/bin

7. 服务与 systemd

7.1 基础操作

systemctl status <svc>
sudo systemctl start|stop|restart <svc>
sudo systemctl reload <svc>          # 重载配置,优先于 restart
sudo systemctl enable --now <svc>
sudo systemctl disable <svc>
sudo systemctl is-active <svc>; systemctl is-enabled <svc>
sudo systemctl mask <svc>            # 禁止任何方式启动
sudo systemctl unmask <svc>
systemctl cat <svc>                  # 查看 unit 全文与 override

7.2 全局排查

systemctl list-units --type=service --state=running
systemctl list-units --failed                # 排障第一步
systemctl list-unit-files --state=enabled
systemctl list-timers --all
systemd-analyze blame
systemd-analyze critical-chain
sudo systemctl daemon-reload                 # 改 unit 后必执行
sudo systemctl reset-failed <svc>            # 清失败计数(触发过 StartLimit 时)

7.3 自定义服务

/etc/systemd/system/myapp.service:

[Unit]
Description=My Application
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=app
Group=app
WorkingDirectory=/opt/myapp
Environment="JAVA_HOME=/usr/lib/jvm/java-17-openjdk"
EnvironmentFile=-/etc/sysconfig/myapp
ExecStart=/opt/myapp/bin/server
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
RestartSec=5
LimitNOFILE=65535
# SELinux 严格模式下需显式声明可写目录
ReadWritePaths=/var/log/myapp /var/lib/myapp

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload && sudo systemctl enable --now myapp

CentOS 的环境变量文件习惯放 /etc/sysconfig/(Debian 系是 /etc/default/),沿用可减少团队认知成本。

7.4 覆盖而不改包自带 unit

sudo systemctl edit nginx           # 生成 /etc/systemd/system/nginx.service.d/override.conf
sudo systemctl edit --full nginx    # 整份复制(包升级后可能冲突)

7.5 SysV 兼容(仅 7 有)

# CentOS 7 仍保留 service / chkconfig 兼容层
sudo service network restart
sudo chkconfig --list
sudo chkconfig httpd on

# 8+ 已移除,只能用 systemctl

版本差异:网上大量 7 时代的教程用 service xxx restart、chkconfig,在 8+ 上直接报 command not found。本文档统一用 systemctl。


8. 进程与资源管理

8.1 查看

ps aux
ps -ef --forest
ps -eo pid,ppid,user,%cpu,%mem,etime,cmd --sort=-%cpu | head -15
pgrep -a nginx
pidof nginx
pstree -p

net-tools 默认未装,netstat 不可用;用 ss 替代。需要时 sudo dnf install -y net-tools,但生产建议直接用 ss。

8.2 终止与信号

kill <pid>                # SIGTERM,优雅退出
kill -9 <pid>             # SIGKILL,强杀
kill -HUP <pid>           # 重载配置
pkill -f "python app.py"
pkill -u <user>
killall nginx
kill -l                   # 信号列表

8.3 前后台与持久会话

<cmd> &
jobs -l
fg %1; bg %1
nohup <cmd> > /var/log/x.log 2>&1 &
disown -h %1

# 长期任务用 tmux(7 需 EPEL 或 base 源)
sudo dnf install -y tmux
tmux new -s ops
tmux attach -t ops
# Ctrl+b d 分离

8.4 端口与句柄

sudo ss -tulnp                      # 监听端口与进程
sudo ss -tanp state established     # 已建立连接
sudo lsof -i :8080                  # 需装 lsof
sudo fuser -v 8080/tcp

8.5 资源限制

ulimit -n
ulimit -a
cat /proc/<pid>/limits

# 全局永久:/etc/security/limits.conf
*  soft  nofile  65535
*  hard  nofile  65535

sysctl fs.file-max
sysctl net.core.somaxconn
sudo sysctl -p                      # 应用 /etc/sysctl.conf

注意:limits.conf 对 systemd 服务无效,必须在 unit 里写 LimitNOFILE=65535。这是 CentOS 7/8 上"明明改了 limits 但进程还是 1024"的根因。


9. 网络配置

这一章是 CentOS 跨版本变化最大的部分,务必按版本选择。

9.1 查看(全版本通用)

ip a
ip -4 a show dev eth0
ip r
ip route get 8.8.8.8
ip link set eth0 up
ip neigh
cat /etc/resolv.conf                # 常被 NetworkManager 接管

9.2 CentOS 7:network-scripts(ifcfg)

/etc/sysconfig/network-scripts/ifcfg-eth0:

TYPE=Ethernet
BOOTPROTO=none
DEFROUTE=yes
NAME=eth0
DEVICE=eth0
IPADDR=192.168.1.10
PREFIX=24
GATEWAY=192.168.1.1
DNS1=223.5.5.5
DNS2=8.8.8.8
sudo systemctl restart network      # 应用(或 ifdown/ifup eth0)
sudo ifdown eth0 && sudo ifup eth0  # 单网卡操作
ping -c3 192.168.1.1

7 上若同时启用 NetworkManager 与 network 服务,两者会互抢配置,只能保留一个:systemctl disable --now NetworkManager。

9.3 CentOS 8:ifcfg 弃用,NetworkManager 主导

# 8 仍能读 ifcfg(兼容插件),但官方推荐 nmcli
nmcli device status
nmcli connection show
sudo nmcli connection reload

9.4 CentOS 9 / 10:keyfile(network-scripts 已移除)

nmcli device status
nmcli connection show

# 新建静态 IP 连接
sudo nmcli connection add type ethernet con-name eth0 ifname eth0 \
  ipv4.method manual \
  ipv4.addresses 192.168.1.10/24 \
  ipv4.gateway 192.168.1.1 \
  ipv4.dns "223.5.5.5 8.8.8.8"

# 修改已有连接
sudo nmcli connection modify eth0 ipv4.addresses 192.168.1.11/24
sudo nmcli connection modify eth0 ipv4.method manual
sudo nmcli connection modify eth0 ipv4.gateway 192.168.1.1
sudo nmcli connection modify eth0 ipv4.dns "223.5.5.5"
sudo nmcli connection modify eth0 connection.autoconnect yes

sudo nmcli connection up eth0
sudo nmcli connection down eth0

# 删除与回退 DHCP
sudo nmcli connection delete eth0
sudo nmcli connection modify eth0 ipv4.method auto

配置文件位置:/etc/NetworkManager/system-connections/eth0.nmconnection,权限必须 600。

等价的 keyfile 手写形式:

[connection]
id=eth0
type=ethernet
interface-name=eth0
autoconnect=true

[ipv4]
method=manual
address1=192.168.1.10/24,192.168.1.1
dns=223.5.5.5;8.8.8.8;
sudo chmod 600 /etc/NetworkManager/system-connections/eth0.nmconnection
sudo nmcli connection reload && sudo nmcli connection up eth0

交互式工具(全版本):nmtui。

远程操作警告:改 IP 前先在控制台/带外管理准备好回滚手段。nmcli connection up 会立即断连,SSH 会话随之中断。

9.5 连通性诊断(由近到远)

ping -c4 8.8.8.8                # 三层
ping -c4 www.aliyun.com         # 三层 + DNS
tracepath <host>                # 无需 root
mtr -rwc 20 <host>              # 持续探测 + 丢包(排抖动首选,需 EPEL)
curl -I https://<host>          # 应用层
curl -o /dev/null -s -w "%{http_code} %{time_total}\n" https://<host>
nc -zv <host> 3306              # 端口探测(需 nmap-ncat)
telnet <host> 80                # 需 telnet 包,很多环境没有

9.6 DNS

cat /etc/resolv.conf
dig <domain> +short
dig @8.8.8.8 <domain> A
nslookup <domain>
getent hosts <domain>           # 走完整 NSS 解析链(排查 /etc/hosts 干扰)

# 持久化 DNS(9/10,NetworkManager)
sudo nmcli connection modify eth0 ipv4.dns "223.5.5.5 8.8.8.8"
sudo nmcli connection modify eth0 ipv4.ignore-auto-dns yes
sudo nmcli connection up eth0

9.7 抓包与网卡

sudo tcpdump -i any -nn port 80 -c 50
sudo tcpdump -i eth0 -nn host 1.2.3.4 and tcp port 443 -w /tmp/cap.pcap
sudo tcpdump -i any -nn 'tcp[tcpflags] & tcp-syn != 0'

ethtool eth0
ethtool -S eth0 | grep -i err
ip -s link

9.8 网卡命名与绑定

# CentOS 7 的网卡命名规则(一致性网络设备命名)
ls /etc/sysconfig/network-scripts/ifcfg-*
grep -E 'net.ifnames|biosdevname' /etc/default/grub

# 回退为 eth0(7 常见需求)
# grub 加 net.ifnames=0 biosdevname=0,然后 grub2-mkconfig -o /boot/grub2/grub.cfg

# bond(9/10 用 nmcli)
sudo nmcli connection add type bond con-name bond0 ifname bond0 bond.options "mode=active-backup,miimon=100"
sudo nmcli connection add type ethernet slave-type bond con-name bond0-eth1 ifname eth1 master bond0

10. firewalld 防火墙

10.1 基本状态

systemctl status firewalld
sudo systemctl enable --now firewalld
sudo firewall-cmd --state                    # running / not running
sudo firewall-cmd --get-default-zone         # 通常 public
sudo firewall-cmd --get-active-zones
sudo firewall-cmd --list-all                 # 当前 zone 全部规则
sudo firewall-cmd --list-all-zones
sudo firewall-cmd --get-services             # 预定义服务列表

10.2 放行与回收(核心用法)

# 服务名方式(推荐,自带端口定义)
sudo firewall-cmd --add-service=http
sudo firewall-cmd --add-service=https
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --reload                   # 永久规则需 reload 才生效

# 端口方式
sudo firewall-cmd --permanent --add-port=8080/tcp
sudo firewall-cmd --permanent --add-port=3306/tcp
sudo firewall-cmd --permanent --remove-port=8080/tcp
sudo firewall-cmd --reload

# 查询某个规则
sudo firewall-cmd --query-service=http
sudo firewall-cmd --query-port=8080/tcp

# 把运行时规则整体转永久(易忘记 --permanent 的救星)
sudo firewall-cmd --runtime-to-permanent

# 端口区间
sudo firewall-cmd --permanent --add-port=8000-8100/tcp

规则生效模型:加 --permanent 只写配置文件,加 --reload 才载入内存;不加 --permanent 只临时生效,重启即丢。习惯是先临时测试 → 确认通 → --runtime-to-permanent。

10.3 源地址、区域与富规则

# 只允许某网段访问数据库
sudo firewall-cmd --permanent --zone=public \
  --add-rich-rule='rule family="ipv4" source address="10.0.0.0/8" port port="3306" protocol="tcp" accept'
sudo firewall-cmd --reload

# 封禁某 IP
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="1.2.3.4" reject'
sudo firewall-cmd --permanent --remove-rich-rule='rule family="ipv4" source address="1.2.3.4" reject'

# 把某网卡划入不同区域
sudo firewall-cmd --permanent --zone=internal --change-interface=eth1
sudo firewall-cmd --permanent --zone=trusted --add-source=10.0.0.0/8

# 端口转发(本机 80 → 8080)
sudo firewall-cmd --permanent --add-forward-port=port=80:proto=tcp:toport=8080

# NAT 出口(需开启伪装)
sudo firewall-cmd --permanent --add-masquerade
sudo firewall-cmd --permanent --zone=public --add-forward-port=port=80:proto=tcp:toaddr=192.168.1.20:toport=80

10.4 紧急操作

sudo firewall-cmd --panic-on       # 切断一切流量(含 SSH!)
sudo firewall-cmd --panic-off
sudo firewall-cmd --complete-reload
sudo systemctl restart firewalld

10.5 底层查看

# CentOS 7:iptables 后端
sudo iptables -L -n -v --line-numbers

# CentOS 8+:nftables 后端,iptables -L 只能看到兼容层
sudo nft list ruleset
sudo nft list table inet firewalld

版本差异:8 起 firewalld 后端为 nftables。网上"用 iptables 命令直接加规则"的 7 时代做法在 8+ 上会被 firewalld 覆盖或失效,一律走 firewall-cmd。

10.6 三个经典坑

  1. 改 SSH 端口后连不上:firewalld 要放行新端口 且 SELinux 要加端口标签(见 11.6),两处缺一个都失败。
  2. docker 绕过 firewalld:docker 直接操作 netfilter,发布的端口不受 firewalld 管;要么改 iptables=false 配合自管规则,要么用 --iptables + 自定义 DOCKER-USER 链。
  3. --reload 会短暂中断:生产上大改前先 --list-all 存档,避免改错后无从恢复。
sudo firewall-cmd --list-all > /root/firewall-backup-$(date +%F).txt

11. SELinux

CentOS 默认 enforcing。这不是可选组件,是强制访问控制层,绝大多数"权限没问题但就是访问不了"都是它。

11.1 状态查看与切换

getenforce                      # Enforcing / Permissive / Disabled
sestatus                        # 详细:策略版本、模式、加载的策略名
sestatus -b                     # 所有布尔值

# 临时切换(重启失效)
sudo setenforce 0               # → Permissive(只记录不拦截,排障用)
sudo setenforce 1               # → Enforcing

# 永久配置:/etc/selinux/config
# SELINUX=enforcing | permissive | disabled

Disable 需要重启且代价高:从 disabled 切回 enforcing 会触发全盘重新打标签(/.autorelabel + 重启)。生产环境排障一律用 setenforce 0 临时验证,不要改成 disabled。

11.2 上下文(context)

ls -Z /var/www/html             # 文件上下文
ls -Zd /var/www/html            # 目录本身
ps -eZ | grep httpd             # 进程上下文
id -Z                           # 当前用户上下文
ss -Z -tulnp                    # 端口上下文

格式:system_u:object_r:httpd_sys_content_t:s0

11.3 修复上下文(最常用)

# 恢复为策略定义的默认值(改过文件位置后必做)
sudo restorecon -Rv /var/www/html
sudo restorecon -Rv /opt/app

# 临时修改(重启/relabel 后丢失,不推荐长期用)
sudo chcon -t httpd_sys_content_t /var/www/html/index.html
sudo chcon -R -t httpd_sys_content_t /data/web

# 永久修改(写入策略,推荐)
sudo semanage fcontext -a -t httpd_sys_content_t "/data/web(/.*)?"
sudo restorecon -Rv /data/web

# 查看策略中的路径规则
sudo semanage fcontext -l | grep httpd_sys_content
# 删除自定义规则
sudo semanage fcontext -d "/data/web(/.*)?"

semanage 属于哪个包:7 是 policycoreutils-python,8+ 是 policycoreutils-python-utils。装错版本会 command not found。

11.4 端口标签(非标准端口必做)

sudo semanage port -l | grep http_port_t
sudo semanage port -a -t http_port_t -p tcp 8080
sudo semanage port -m -t http_port_t -p tcp 8080
sudo semanage port -d -t http_port_t -p tcp 8080

经典场景:nginx 监听 8080,firewalld 放行了、配置也对,但 curl 一直 403/连接被拒 —— 缺 SELinux 端口标签。这是 CentOS 独有的高频故障。

11.5 布尔开关

sudo semanage boolean -l | grep httpd
getsebool -a | grep httpd
sudo setsebool httpd_can_network_connect on          # 临时
sudo setsebool -P httpd_can_network_connect on       # 永久(-P 必须加)

常用布尔值:

布尔值 用途
httpd_can_network_connect 允许 httpd/nginx 主动外连(反代后端必备)
httpd_can_network_connect_db 允许连数据库
httpd_read_user_content 读取用户家目录内容
httpd_use_nfs / httpd_use_cifs 访问 NFS / SMB 挂载
ftpd_full_access FTP 完整访问

11.6 审计日志与策略生成

sudo ausearch -m avc -ts recent                 # 最近的 AVC 拒绝记录
sudo ausearch -m avc -ts today | aureport -f -i
sudo sealert -a /var/log/audit/audit.log        # 需 setroubleshoot-server

# 由拒绝记录生成策略模块
sudo ausearch -m avc -ts recent | audit2allow -M myapp
sudo semodule -i myapp.pp
sudo semodule -l | grep myapp
sudo semodule -r myapp                          # 卸载

使用顺序:先 setenforce 0 确认问题确由 SELinux 引起 → 看 avc 日志 → 优先用 restorecon / semanage fcontext / setsebool 解决 → 确实没有现成策略时,最后才用 audit2allow 生成自定义模块。直接关 SELinux 是错误答案。

11.7 全盘重打标签

sudo touch /.autorelabel
sudo reboot
# 或手动
sudo restorecon -Rv /

11.8 常见问题对照

现象 原因 处理
nginx 启动失败,日志无明确错误 端口无标签 semanage port -a -t http_port_t -p tcp <port>
网页 403,文件权限已 755 上下文不是 httpd_sys_content_t restorecon -Rv 或 semanage fcontext
反代 502,后端 curl 正常 布尔值未开 setsebool -P httpd_can_network_connect on
应用写 /opt/app/data 失败 目录上下文不允许写 semanage fcontext -a -t <app>_var_lib_t 或加 ReadWritePaths
挂载 NFS 后无法访问 缺少 use_nfs 布尔 setsebool -P httpd_use_nfs on

12. 日志与排障

12.1 传统日志文件

ls -lh /var/log/

tail -F /var/log/messages            # 系统总日志(最重要)
tail -F /var/log/secure              # 认证、登录、sudo、SSH
tail -F /var/log/cron                # 定时任务执行记录
tail -F /var/log/audit/audit.log     # SELinux AVC
tail -F /var/log/boot.log            # 开机过程
tail -F /var/log/dnf.log             # 包管理(7 为 yum.log)
grep -i error /var/log/messages
zgrep -i error /var/log/messages-20261101.gz    # 已轮转的压缩日志

CentOS 用 /var/log/messages 与 /var/log/secure;Debian/Ubuntu 是 syslog 与 auth.log。抄 Ubuntu 文档会找不到文件。

12.2 journalctl

journalctl -xe                            # 最近的错误与提示(排障第一站)
journalctl -u nginx -f
journalctl -u nginx --since "1 hour ago"
journalctl --since "2026-11-05 08:00" --until "2026-11-05 09:00"
journalctl -p err -b                      # 本次启动的错误
journalctl -k                             # 内核
journalctl -b -1                          # 上次启动(排查崩溃重启)
journalctl --disk-usage
sudo journalctl --vacuum-time=7d
sudo journalctl --vacuum-size=500M

持久化:

sudo mkdir -p /var/log/journal
sudo systemctl restart systemd-journald
# /etc/systemd/journald.conf: Storage=persistent, SystemMaxUse=2G

版本差异:7/8 的 journald 默认存 /run/log/journal(重启丢失),9+ 默认持久化到 /var/log/journal。7 上排"昨天的故障"必须靠 rsyslog 的 /var/log/messages。

12.3 rsyslog

systemctl status rsyslog
cat /etc/rsyslog.conf
ls /etc/rsyslog.d/
sudo rsyslogd -N1                # 配置语法检查
sudo systemctl restart rsyslog

# 单独拆一个应用的日志
# /etc/rsyslog.d/myapp.conf
# if $programname == 'myapp' then /var/log/myapp.log
# & stop

12.4 内核与启动

dmesg -T
dmesg -T | grep -iE "error|fail|oom|i/o error"
dmesg -w                        # 实时
journalctl -k -b

# 内核参数
sysctl -a | grep net.ipv4
cat /etc/sysctl.conf
ls /etc/sysctl.d/
sudo sysctl -p

12.5 日志轮转

cat /etc/logrotate.conf
ls /etc/logrotate.d/
sudo logrotate -d /etc/logrotate.d/myapp      # 干跑
sudo logrotate -f /etc/logrotate.d/myapp
/var/log/myapp/*.log {
    daily
    rotate 14
    compress
    delaycompress
    missingok
    notifempty
    copytruncate
    create 0640 app app
}

13. 定时任务

13.1 cron

crontab -e
crontab -l
crontab -r                    # ⚠️ 清空当前用户全部任务
sudo crontab -u <user> -l
systemctl status crond        # ⚠️ CentOS 服务名是 crond,不是 cron
30 3 * * * /opt/scripts/backup.sh >> /var/log/backup.log 2>&1
*/5 * * * * /opt/scripts/check.sh
0 9-18 * * 1-5 /opt/scripts/sync.sh
0 0 1 * * /opt/scripts/monthly.sh

/etc/cron.d/myjob(带用户字段):

SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
30 3 * * * root /opt/scripts/backup.sh

CentOS 上 cron 的四个坑

  1. 服务名是 crond,systemctl status cron 查不到。
  2. PATH 极简,命令写绝对路径。
  3. SELinux 会拦:脚本放在自家目录且无执行上下文时,cron 静默失败。查 /var/log/cron 与 audit.log。
  4. 不加载 profile,环境变量要在脚本内显式声明。
grep CRON /var/log/cron | tail -20
sudo ausearch -m avc -ts recent | grep crond

13.2 systemd timer

/etc/systemd/system/backup.service:

[Unit]
Description=Daily backup

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

/etc/systemd/system/backup.timer:

[Unit]
Description=Run backup daily

[Timer] 03:30:00
Persistent=true
RandomizedDelaySec=300

[Install]
WantedBy=timers.target
sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer
systemctl list-timers --all
journalctl -u backup.service

timer 的优势:Persistent=true 补跑错过的任务、日志自动进 journal、可用 systemctl status 统一查看、受 systemd 的资源限制管控。生产优先于 cron。

13.3 anacron / at

cat /etc/anacrontab             # 非 24 小时运行机器用
echo "/opt/scripts/restart.sh" | at 02:00
at -l; atrm <job>

14. 压缩、备份与传输

14.1 tar

tar -czf backup-$(date +%F).tar.gz /data/app
tar -xzf backup.tar.gz -C /restore
tar -tzf backup.tar.gz | head
tar -czf x.tar.gz --exclude='*.log' --exclude='node_modules' /app
tar --zstd -cf x.tar.zst /app      # zstd,8+ 可用

14.2 rsync

rsync -avzP /data/app/ /backup/app/
rsync -avzP -e "ssh -p 2222" user@host:/data/app/ /backup/app/
rsync -avz --delete --dry-run /src/ /dst/      # 先干跑
rsync -avz --delete /src/ /dst/                # ⚠️ 镜像同步
rsync -avz --exclude='.git' --bwlimit=5000 /data/ /backup/data/

尾斜杠语义:/src/ 是"src 的内容",/src 是"src 目录本身"。备份脚本写错会多一层嵌套或同步错对象。

14.3 scp / sftp

scp file.tar.gz user@host:/tmp/
scp -r user@host:/var/log/app ./logs/
scp -P 2222 file user@host:/tmp/     # 大写 P
sftp user@host

14.4 数据库备份

CentOS 7 默认 MariaDB 5.5,8+ 为 MariaDB 10.3 / MySQL 8:

# MySQL / MariaDB
mysqldump -u root -p --single-transaction --routines --triggers db > db-$(date +%F).sql
mysqldump -u root -p --all-databases | gzip > all-$(date +%F).sql.gz
mysql -u root -p db < db.sql

# PostgreSQL
pg_dump -U postgres -Fc db > db.dump
pg_restore -U postgres -d db db.dump

# 注意备份目录的 SELinux 上下文
sudo semanage fcontext -a -t mysqld_db_t "/backup/mysql(/.*)?"
sudo restorecon -Rv /backup/mysql

14.5 备份脚本模板

#!/usr/bin/env bash
set -euo pipefail

BACKUP_DIR=/backup
SRC=/data/app
STAMP=$(date +%F_%H%M)
KEEP_DAYS=14

mkdir -p "$BACKUP_DIR"
tar -czf "$BACKUP_DIR/app-$STAMP.tar.gz" -C "$(dirname "$SRC")" "$(basename "$SRC")"
find "$BACKUP_DIR" -name 'app-*.tar.gz' -mtime +$KEEP_DAYS -delete

echo "[$(date '+%F %T')] backup ok: app-$STAMP.tar.gz"

14.6 系统级备份与快照

# LVM 快照(需预留空间)
sudo lvcreate -L 20G -s -n snap_root /dev/mapper/centos-root

# XFS 在线转储(慎用,需足够空间)
sudo xfsdump -l 0 -L full -M media -f /backup/root.xfsdump /
sudo xfsrestore -f /backup/root.xfsdump /restore

# 整机镜像(块级,需停机或快照)
sudo dd if=/dev/sda of=/backup/sda.img bs=4M status=progress

15. 性能监控与调优

15.1 快速三连

uptime; free -h; df -h; df -i
top -b -n1 | head -20

15.2 vmstat

vmstat 1 5
列 含义 告警
r 运行队列 持续 > 核数
b 阻塞进程 高说明 IO 卡
si/so swap 换入换出 非 0 即内存不足
us/sy 用户态/内核态 sy 高查系统调用
wa IO 等待 > 20% 查磁盘
id 空闲 长期 0 需扩容

15.3 iostat / pidstat / mpstat

iostat -xz 1 5
pidstat -u -d -p <pid> 1 5
mpstat -P ALL 1            # 各核负载(排查单核打满)

%util 接近 100% 表示磁盘饱和;await 远大于 svctm 说明排队;aqu-sz 持续 > 2 需关注。

15.4 历史趋势

CentOS 默认装 sysstat 并开启采集(与 Ubuntu 需手动开不同):

sar -u 1 5
sar -r 1 5
sar -d 1 5
sar -n DEV 1 5
sar -u -f /var/log/sa/sa05      # 回看某天(CentOS 路径,Ubuntu 是 sysstat/sa05)
ls /var/log/sa/

15.5 内存

free -h
ps -eo pid,user,rss,cmd --sort=-rss | head -10
cat /proc/meminfo
sudo slabtop
dmesg -T | grep -i "out of memory"
journalctl -k | grep -i "killed process"

关注 available,不是 free。buff/cache 可回收。

15.6 tuned(CentOS 特色)

sudo dnf install -y tuned
systemctl enable --now tuned
tuned-adm list
tuned-adm active
sudo tuned-adm profile throughput-performance    # 数据库/高吞吐
sudo tuned-adm profile virtual-guest             # 虚拟机
sudo tuned-adm profile latency-performance       # 低延迟
sudo tuned-adm recommend

tuned 会改内核参数、IO 调度器、CPU 调频策略,比手写 sysctl 更系统化。RHEL/CentOS 生产标配,Ubuntu 默认没有。

15.7 内核参数(/etc/sysctl.d/99-tuning.conf)

net.core.somaxconn = 32768
net.ipv4.tcp_max_syn_backlog = 16384
net.ipv4.ip_local_port_range = 10000 65000
net.ipv4.tcp_tw_reuse = 1
fs.file-max = 1000000
vm.swappiness = 10
sudo sysctl --system          # 8+ 推荐
sudo sysctl -p                # 7

15.8 IO 调度器

cat /sys/block/sda/queue/scheduler
echo mq-deadline | sudo tee /sys/block/sda/queue/scheduler
# 持久化:内核参数 elevator=mq-deadline,或 udev 规则

版本差异:7 内核 3.10 默认 deadline/cfq;8+ 为多队列 mq-deadline/none,cfq 已移除。照抄 7 的调优文档设 cfq 会失败。

15.9 压测与定位

stress-ng --cpu 4 --timeout 60s        # EPEL
sysbench cpu --threads=4 run
sudo perf top                          # 函数级热点
sudo perf record -g -p <pid> -- sleep 10 && sudo perf report

16. SSH 与远程运维

16.1 密钥登录

ssh-keygen -t ed25519 -C "ops@company"
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@host

~/.ssh/config:

Host prod-web
    HostName 10.0.1.10
    User ops
    Port 2222
    IdentityFile ~/.ssh/id_ed25519
    ServerAliveInterval 60

16.2 服务端加固

# 配置目录差异
ls /etc/ssh/sshd_config.d/          # 8+ 支持 Include,7 没有该目录

# 7:直接改 /etc/ssh/sshd_config
# 8+:建议在 /etc/ssh/sshd_config.d/99-hardening.conf 新增
Port 2222
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
ClientAliveInterval 300
ClientAliveCountMax 2
AllowUsers ops deploy
sudo sshd -t                    # 语法检查,必须先跑
sudo systemctl reload sshd      # ⚠️ CentOS 服务名是 sshd,不是 ssh

改 SSH 端口三步缺一不可:

  1. sshd_config 改 Port
  2. firewalld 放行:firewall-cmd --permanent --add-port=2222/tcp && firewall-cmd --reload
  3. SELinux 打标签:semanage port -a -t ssh_port_t -p tcp 2222

只做第 1 步会导致 sshd 起不来,是最常见的"把自己锁在门外"。

16.3 隧道

ssh -L 8080:localhost:80 user@host        # 本地转发
ssh -R 9000:localhost:3000 user@host      # 远程转发
ssh -D 1080 user@host                     # SOCKS5 代理
ssh -J jump@bastion user@internal         # 跳板

16.4 批量执行

for h in web1 web2 web3; do
  echo "== $h =="
  ssh -o ConnectTimeout=5 "$h" 'systemctl is-active nginx'
done

sudo dnf install -y pdsh
pdsh -w web[1-3] 'uptime'

16.5 SSH 排障速查

sudo tail -50 /var/log/secure
sudo sshd -t
sudo ss -tulnp | grep sshd
getenforce; sudo semanage port -l | grep ssh
sudo firewall-cmd --list-all
现象 排查
Connection refused sshd 未启动 / 端口未监听 / SELinux 端口标签缺失
Connection timed out firewalld、云安全组、网络
Permission denied (publickey) authorized_keys 权限须 600、~/.ssh 700、家目录不可组可写
登录后立即断开 磁盘满、shell 不存在、/etc/nologin、PAM 限制
连接被重置 fail2ban/denyhosts 封禁、/etc/hosts.deny

17. 高频故障速查表

17.1 CPU 高

top -b -n1 | head -15
ps -p <pid> -o pid,user,%cpu,etime,cmd
top -H -p <pid>                # 线程级
pidstat -u 1 -p <pid>
sudo perf top

17.2 磁盘满

df -h; df -i
du -h --max-depth=1 / 2>/dev/null | sort -rh | head
sudo lsof +L1                  # 已删除仍被占用
journalctl --vacuum-size=200M
sudo dnf clean all
find /var/log -name "*.gz" -mtime +30 -delete

# Docker 环境
docker system df
docker system prune -a

常见元凶:/var/log 未轮转、/var/lib/docker 堆积、journal 无上限、被删除的大文件仍被进程持有、inode 耗尽(/var/spool/postfix 堆积)。

17.3 内存不足 / OOM

free -h
dmesg -T | grep -i "out of memory"
journalctl -k | grep -i "killed process"
ps -eo pid,user,rss,cmd --sort=-rss | head
cat /proc/<pid>/oom_score

17.4 服务起不来(CentOS 四步法)

# 1. systemd 层
systemctl status <svc> -l
journalctl -u <svc> -n 100 --no-pager
# 2. SELinux 层(最常见的隐蔽原因)
sudo ausearch -m avc -ts recent
getenforce
# 3. 端口与进程层
sudo ss -tulnp | grep <port>
# 4. 手动复现
sudo -u <svcuser> <实际命令>
ls -l <工作目录> <日志目录>

17.5 权限正常但访问被拒(SELinux)

getenforce
sudo ausearch -m avc -ts recent | tail -20
sudo sealert -a /var/log/audit/audit.log
ls -Z <路径>
sudo restorecon -Rv <路径>
sudo setenforce 0        # 临时验证是否 SELinux 引起

17.6 网络通但服务连不上

ss -tulnp | grep <port>              # 本机是否监听
firewall-cmd --list-all              # 防火墙
sudo semanage port -l | grep <port>  # SELinux 端口
curl -v http://127.0.0.1:<port>      # 本机自连
ip r; ip a                           # 路由与地址
sudo tcpdump -i any -nn port <port>  # 是否有包到达

17.7 yum/dnf 报错

报错 处理
Cannot find a valid baseurl 网络/DNS 不通,或 7 的源已下线需换 vault
repomd.xml ... GPG 错误 dnf clean all && dnf makecache;检查系统时间
Error: rpmdb open failed rm -f /var/lib/rpm/__db*; rpm --rebuilddb
Transaction check error 依赖冲突,dnf distro-sync 或逐一降级
No space left on device 清 /var/cache/dnf、/var/cache/yum
dnf: command not found(在 7 上) 7 只有 yum,不要照抄 8+ 文档

17.8 系统启动失败

# emergency/rescue 下
mount -o remount,rw /
cat /etc/fstab                # 错误条目,加 nofail
systemctl --failed
journalctl -xb -p err
# SELinux 导致无法启动:grub 加 selinux=0 一次性进入,之后修上下文

17.9 时间错乱导致证书/认证失败

timedatectl
chronyc tracking
sudo systemctl restart chronyd
sudo chronyc makestep

18. 版本生命周期与迁移路径

18.1 生命周期现状

版本 EOL 现状与建议
CentOS 7 2024-06-30 已停更,仓库迁 vault。必须迁移
CentOS 8 2021-12-31 已停更,转 Stream 8 亦已 EOL
Stream 8 2024-05-31 已 EOL
Stream 9 约 2027-05 当前主力,可用
Stream 10 约 2030 新版本,逐步铺开

CentOS Linux 已于 2021 年底转向 CentOS Stream(滚动预览版,位于 RHEL 之前)。追求"稳定下游"的场景应选 Rocky Linux 或 AlmaLinux(RHEL 1:1 重建)。

18.2 CentOS 7 停更后的源切换

sudo sed -i 's|^mirrorlist=|#mirrorlist=|g' /etc/yum.repos.d/CentOS-*.repo
sudo sed -i 's|^#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*.repo
sudo yum clean all && sudo yum makecache

这只解决"还能装包",不解决安全更新。vault 是只读归档,不会有新补丁。

18.3 迁移路径

起点 目标 工具/方式
CentOS 7 Rocky/Alma 8 或 9 elevate(AlmaLinux ELevate 项目)或重装
CentOS 8 Stream 8 / Rocky 8 dnf swap centos-linux-repos centos-stream-repos 或 migrate2rocky
Stream 8 Stream 9 不支持原地升级,重装
Stream 9 Stream 10 不支持原地升级,重装
任意 Ubuntu 重装(包管理与 SELinux 体系完全不同)
# CentOS 8 → Stream 8
sudo dnf install -y centos-release-stream
sudo dnf swap centos-{linux,stream}-repos
sudo dnf distro-sync -y

# 8 → Rocky Linux(migrate2rocky)
curl -O https://raw.githubusercontent.com/rocky-linux/rocky-tools/main/migrate2rocky/migrate2rocky.sh
sudo bash migrate2rocky.sh -r

跨大版本迁移的现实建议:7→9 原地升级成功率低、回滚困难。生产环境优先"新建 + 数据迁移 + 灰度切流"。必须原地升级时,先全量快照,并在测试环境完整演练一遍。

18.4 迁移前检查清单

# 1. 记录当前状态
rpm -qa > /root/pkgs-before.txt
systemctl list-unit-files --state=enabled > /root/services-before.txt
cat /etc/fstab > /root/fstab-before.txt
ip a > /root/ip-before.txt
firewall-cmd --list-all > /root/fw-before.txt

# 2. 找出第三方源与非官方包(升级最大障碍)
ls /etc/yum.repos.d/
dnf repolist
rpm -qa --qf '%{NAME} %{VENDOR}\n' | grep -viE 'centos|red hat|rhel'

# 3. 确认关键软件在新版本的可用性(尤其依赖 Python 2 的自研脚本)
python2 -V 2>/dev/null; python3 -V

Python 2 是 7→8+ 迁移最大暗坑:7 的系统工具大量依赖 Python 2.7,8+ 全为 Python 3,9/10 完全无 Python 2。自研运维脚本必须提前改造。


19. 危险命令与避坑清单

19.1 高危命令

命令 风险
rm -rf / rm -rf /* 系统毁灭
rm -rf $VAR/(VAR 为空) 等价 rm -rf /,脚本必加 ${VAR:?}
chmod -R 777 / 全系统权限崩坏,SSH 拒登
chown -R user:user / 同上
dd if=/dev/zero of=/dev/sda 覆写磁盘
mkfs.xfs /dev/sda 误格式化系统盘
rpm -e --nodeps <核心包> 破坏依赖树,可能无法开机
setenforce 0 后忘记恢复 安全边界长期失效
/etc/selinux/config 改 disabled 重启后需全盘 relabel 才能恢复
firewall-cmd --panic-on(远程) 立即切断 SSH
> /etc/passwd > /etc/shadow 清空账户库
lvreduce 缩 XFS 不支持,直接损坏文件系统
rsync --delete 方向写反 空目录覆盖源数据

19.2 CentOS 专属避坑

  1. 不要禁用 SELinux:用 setenforce 0 验证,用 semanage/restorecon/setsebool 解决问题。
  2. 改 SSH 端口必须同步 firewalld + SELinux,两处缺一即失联。
  3. XFS 不能缩容,LV 规划留余量。
  4. fstab 加 nofail,避免磁盘缺失导致无法开机。
  5. limits.conf 不影响 systemd 服务,用 LimitNOFILE。
  6. 7 的教程不要照搬到 8+:service/chkconfig/ifcfg/iptables/netstat 大多已移除或失效。
  7. Stream 与 CentOS Linux 不是一回事:Stream 是滚动预览,补丁先于 RHEL,稳定性预期不同。

19.3 变量保护写法

# 错误
rm -rf "$VAR"/

# 正确
: "${VAR:?VAR is not set}"
rm -rf "${VAR:?}"/

19.4 变更前自保

cp -a /etc/firewalld /root/backup-firewalld-$(date +%F)
cp -a /etc/ssh/sshd_config /root/backup-sshd-$(date +%F)
cp /etc/fstab /root/backup-fstab-$(date +%F)
firewall-cmd --list-all > /root/fw-$(date +%F).txt

附录 A:常用命令速查

场景 命令
版本判断 rpm -E %{rhel} / cat /etc/centos-release
系统概况 hostnamectl / lscpu / free -h
磁盘使用 df -h df -i du -sh *
找大文件 du -h --max-depth=1 / | sort -rh | head
假性磁盘满 lsof +L1
端口占用 ss -tulnp | grep :80
进程详情 ps -eo pid,user,%cpu,%mem,cmd --sort=-%cpu | head
服务状态 systemctl status x / journalctl -u x -f
失败服务 systemctl --failed
防火墙 firewall-cmd --list-all
SELinux 状态 getenforce / sestatus
SELinux 拒绝 ausearch -m avc -ts recent
端口标签 semanage port -l | grep http_port_t
上下文修复 restorecon -Rv <path>
布尔开关 setsebool -P <bool> on
网络配置 nmcli con mod + nmcli con up
包管理 dnf install / dnf provides */cmd
反查命令来源包 rpm -qf $(which cmd)
定时任务 crontab -l / systemctl list-timers
增量备份 rsync -avzP --dry-run src/ dst/
实时日志 tail -F /var/log/messages
开机耗时 systemd-analyze blame
登录审计 last / lastb / grep Failed /var/log/secure

附录 B:接手 CentOS 服务器检查清单

# 1. 版本与硬件
rpm -E %{rhel}; hostnamectl; lscpu; free -h; df -h; df -i

# 2. 谁在用、跑什么
who; w; systemctl list-units --type=service --state=running

# 3. 暴露面
ss -tulnp
firewall-cmd --list-all
getenforce

# 4. 健康度
systemctl --failed
journalctl -p err -b --no-pager | tail -30
dmesg -T | grep -iE "error|fail|i/o error" | tail -20

# 5. 定时任务与自启
crontab -l; ls /etc/cron.d/; systemctl list-timers --all

# 6. 安全基线
grep -E "^(PermitRootLogin|PasswordAuthentication|Port)" /etc/ssh/sshd_config
ausearch -m avc -ts today | tail -20
lastb | head -20
find / -perm -4000 -type f 2>/dev/null

# 7. 更新与仓库状态(7 尤其重要)
dnf check-update || yum check-update
dnf repolist || yum repolist

# 8. 备份是否真的在跑
ls -lht /backup | head; ls -lht /var/backups | head

文档维护建议:本手册的「版本差异」标注点是跨版本最容易出事故的地方,建议在团队内单独整理成一页《CentOS 版本差异对照卡》贴在内网文档首页,新人上手先看这页。