AlmaLinux-9 与 WSL2 初始环境配置与常用工具安装教程
适用于 AlmaLinux 9(云厂商镜像、官方 ISO 或 WSL2 安装后),从 SSH 远程连接到常用工具一站式配置。
📌 这是一份独立专题——聚焦 AlmaLinux 9 的初始环境配置、常用工具安装与安全加固;WSL 专属行为单独标注,不展开讨论通用 WSL 基础(详见
WSL 虚拟机创建与管理指南.md)。
目录
一、文档总览
章节索引:
| 序号 | 章节 | 说明 |
|---|---|---|
| 一 | 文档总览 | 流程图 + 索引 |
| 二 | 初始环境检查 | 确认系统版本 / 初始账号 / root 密码 |
| 三 | SSH 远程服务 | 核心:安装 + 配置 + 密钥免密 |
| 四 | 常用工具集 | dnf 一键装包 + Git / vim / bash 偏好 |
| 五 | 网络与系统配置 | 静态 IP / DNS / 时区 / 更新源 |
| 六 | 安全与优化 | firewalld / fail2ban / SELinux / 内核参数 |
| 七 | WSL 用户专属指南 | WSL 必读:systemd 启用、主机名、SELinux 噪音、firewalld 关掉、数据规划、vhdx 回收、重启方式 |
| 八 | 验证检查清单 | 一键自检 |
| 九 | 常用命令速查 | AlmaLinux ↔ Ubuntu 对照表 |
二、初始环境检查
在动手前,先确认当前系统的版本、内核、当前用户、是否已装 SSH。
# 系统版本
cat /etc/os-release
# 关键字段:NAME="AlmaLinux"、VERSION="9.x (Seafoam Ocelot)"、ID=almalinux
# 内核版本
uname -r
# 当前用户与权限
whoami
id
# 是否已安装 SSH(AlmaLinux 多数镜像默认已装)
rpm -q openssh-server
ss -tlnp 2>/dev/null | grep :22 || netstat -tlnp 2>/dev/null | grep :22
2.1 设置 root 密码
AlmaLinux 安装时通常会要求设 root 密码,但云厂商轻量镜像或WSL 装出来的版本可能 root 锁死或密码为空。建议先确认:
# 查看是否能切到 root
su -
whoami
# 报错或提示密码错误 = 没设好
为 root 设置一个强密码:
# 为 root 用户设置密码(按提示输入两次)
sudo passwd root
验证切换是否成功:
# 切换到 root 用户
su -
# 确认当前身份
whoami
id
💡 提示:
- AlmaLinux 与 RHEL/CentOS 允许 root 通过 SSH 登录(
PermitRootLogin yes默认),生产环境强烈建议改为no。- WSL 环境下:首次
wsl --install设的普通用户没有 root 密码,但可以直接sudo;sudo passwd root设上之后更方便维护。
🔐 安全建议:
- root 密码应使用强密码(长度 12 位以上,包含大小写字母、数字、特殊字符)。
- 日常操作优先使用
sudo,仅在必要时切换到 root。
三、SSH 远程服务(核心)
本章为优先配置项。所有运维操作几乎都依赖 SSH,建议首先完成配置。
3.1 安装 openssh-server
⚠️ 先换源,再更新
如果你在国内或默认源访问较慢,建议先完成 5.5 dnf 换源,再返回本节执行安装。否则第一次
dnf makecache可能非常慢,甚至超时失败。
- WSL 默认 rootfs 较精简,openssh-server 通常没装,本节命令是必须的
- 真机/云服务器多数镜像已预装
# 更新软件源缓存(如已按 5.5 节换源,会直接从镜像站更新)
sudo dnf makecache
# 安装 SSH 服务端与客户端
sudo dnf install -y openssh-server openssh-clients
# 启动并设置开机自启
sudo systemctl enable --now sshd
🔧 验证:
sudo systemctl status sshd # 输出中出现 active (running) 即表示成功 ss -tlnp | grep :22 # 看到 0.0.0.0:22 或 *:22 监听中
📋 WSL 用户必读:配置完 SSH 后,如果需要从 Windows 侧通过 WSL 的 IP(如
192.168.x.x)连接到此 WSL 实例,还需要额外开启hostAddressLoopback实验特性。否则localhost:<端口>正常,但WSL_IP:<端口>会超时。详见WSL 虚拟机创建与管理指南.md第 6 节「网络配置进阶」。
3.2 配置文件结构
| 📄 文件 | 📝 用途 |
|---|---|
/etc/ssh/sshd_config |
服务端主配置(修改后要重启 sshd 服务) |
/etc/ssh/ssh_config |
客户端配置(一般不动) |
~/.ssh/authorized_keys |
存放客户端公钥,启用免密登录 |
~/.ssh/known_hosts |
客户端记录过的服务端指纹 |
~/.ssh/id_rsa / id_rsa.pub |
客户端的私钥 / 公钥 |
修改
sshd_config前强烈建议先备份:sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
3.3 修改 sshd_config(生产推荐配置)
sudo vim /etc/ssh/sshd_config
# =============================================
# 基础配置
# =============================================
# 监听端口(生产建议改为非默认端口,降低被扫描爆破概率)
Port 22
# 监听地址(0.0.0.0 = 所有网卡;如仅内网访问可改为内网IP)
ListenAddress 0.0.0.0
# 协议版本(v2 比 v1 安全)
Protocol 2
# =============================================
# 登录认证(关键)
# =============================================
# 禁止 root 直接登录(必开,AlmaLinux 默认是 yes)
PermitRootLogin no
# 是否允许密码登录。生产推荐 no + 改用密钥登录
PasswordAuthentication yes
# 是否允许空密码(生产环境应设为 no)
PermitEmptyPasswords no
# 公钥认证(密钥免密登录)
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
# =============================================
# 安全加固
# =============================================
# 最大重试次数
MaxAuthTries 3
# 最大并发未认证连接
MaxSessions 5
# 登录超时(30 秒无输入断开)
LoginGraceTime 30
# 客户端空闲超时(600 秒无操作断开)
ClientAliveInterval 60
ClientAliveCountMax 10
# 禁止 X11 转发(图形转发,服务器无必要)
X11Forwarding no
# 限制登录用户/组(白名单)
AllowUsers youruser
# AllowGroups ssh-users
# =============================================
# 显示与日志
# =============================================
# 登录前后显示的 banner 文件路径(可选)
# Banner /etc/issue.net
# 日志级别
LogLevel VERBOSE
# =============================================
# AlmaLinux 9 特有:SELinux 相关
# =============================================
# SELinux 启用时,chroot 目录权限由 SELinux 策略控制
# 一般保持默认即可
📋 配置说明:
PermitRootLogin no:禁止 root 直登,运维需用普通用户 +sudo提权。PasswordAuthentication yes→ 后续验证完密钥登录后可改为no。AllowUsers youruser:把youruser替换为你的实际登录用户,多用户用空格分隔。
3.4 启动 SSH 并加入开机自启
# 检查配置语法(非常关键,避免配错导致无法登录)
sudo sshd -t
# 若命令无输出,则表示语法正确
# 重启服务
sudo systemctl restart sshd
# 确认开机自启
sudo systemctl enable sshd
# 查看状态
sudo systemctl status sshd
⚠️ 高危提醒:修改 SSH 配置后,不要立即关闭当前会话。应新开一个窗口测试能正常登录,确认没问题再退出,避免配置错误导致锁在外面。
3.5 配置密钥免密登录(推荐)
3.5.1 在客户端生成密钥对
Windows(PowerShell / CMD):
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
# 一直回车即可,会在 C:\Users\你的用户\.ssh\ 下生成 id_rsa 和 id_rsa.pub
Linux / macOS:
ssh-keygen -t rsa -b 4096
# 提示 passphrase 时可设置密码(更安全),也可直接回车
3.5.2 上传公钥到服务器
方法一:ssh-copy-id(最简单)
# Linux / macOS / Windows 11 (PowerShell 自带 OpenSSH)
ssh-copy-id -i ~/.ssh/id_rsa.pub youruser@服务器IP
# 输入一次密码后即完成
方法二:手动复制
# 在客户端打印公钥
cat ~/.ssh/id_rsa.pub
# 在服务器上操作
mkdir -p ~/.ssh
chmod 700 ~/.ssh
vim ~/.ssh/authorized_keys # 粘贴公钥,一行一个
chmod 600 ~/.ssh/authorized_keys
📋 AlmaLinux 9 + SELinux 注意:
- 默认 SELinux 策略下,
~/.ssh/的chmod 700+authorized_keys的chmod 600已正确打标- 如果还是登录失败,先
restorecon -R -v ~/.ssh恢复 SELinux 上下文
3.5.3 关闭密码登录
验证密钥能登录后,编辑服务端配置:
sudo vim /etc/ssh/sshd_config
PasswordAuthentication no
sudo sshd -t
sudo systemctl restart sshd
3.6 防火墙放行 SSH
AlmaLinux 默认使用 firewalld(与 Ubuntu 的 ufw 风格不同,但功能等价):
# 查看 firewalld 状态
sudo firewall-cmd --state
sudo firewall-cmd --list-all
# 放行 SSH(默认就是放行的,这里再确认一次)
sudo firewall-cmd --permanent --add-service=ssh
# 重载配置
sudo firewall-cmd --reload
# 验证
sudo firewall-cmd --list-services | grep ssh
💡 SSH 服务的服务名:
firewalld预定义服务名是ssh(不是sshd),内部对应/usr/lib/firewalld/services/ssh.xml- 改了 SSH 端口(如 2222)时,要手动添加:
sudo firewall-cmd --permanent --add-port=2222/tcp
四、常用工具集
💡 章节定位:本节是 SSH 配好之后紧接着要做的——补齐开发/运维常用的命令工具。WSL 默认 rootfs 没有这些,每次新建 WSL 都要装一遍。
网络、主机名、时区、更新源等"系统级"配置放 五、网络与系统配置;安全加固放 六、安全与优化;WSL 专属配置放 七、WSL 用户专属指南。
4.1 一键安装清单
# =============================================
# 网络工具
# =============================================
# net-tools: netstat / ifconfig / route 等传统命令
# iproute: ip / ss / tc 等新一代命令(AlmaLinux 自带)
# bind-utils:nslookup / dig / host
# iputils: ping
# traceroute:路由追踪
sudo dnf install -y net-tools bind-utils iputils traceroute mtr NetworkManager NetworkManager-libnm
# =============================================
# 编辑器与文件处理
# =============================================
# vim: 增强版 vi
# nano: 简单文本编辑器
# unzip / p7zip / p7zip-plugins: 解压 zip / 7z
# lrzsz: rz / sz 上传下载(Xshell/SecureCRT 适用)
sudo dnf install -y vim nano unzip p7zip p7zip-plugins lrzsz
# =============================================
# 版本控制
# =============================================
# git: 分布式版本控制
sudo dnf install -y git
# =============================================
# Shell 增强
# =============================================
# bash-completion: 命令补全
# zsh + oh-my-zsh: 更友好的 shell
# tmux: 终端复用器(断线不丢任务)
sudo dnf install -y bash-completion tmux
# =============================================
# 时间同步
# =============================================
# chrony: AlmaLinux 默认的 NTP 客户端
sudo dnf install -y chrony
# =============================================
# SELinux 工具
# =============================================
# policycoreutils: 提供 getenforce / setenforce / sestatus
sudo dnf install -y policycoreutils
# =============================================
# 系统监控与诊断
# =============================================
# htop: 增强版 top
# iotop: 磁盘 IO 监控
# iftop: 网络流量监控
# sysstat: iostat / mpstat / sar
# lsof: 查看打开的文件
# strace: 系统调用跟踪
# ncdu: 交互式磁盘占用分析
sudo dnf install -y htop iotop iftop sysstat lsof strace ncdu
# =============================================
# 开发工具链(按需)
# =============================================
# gcc / gcc-c++ / make / automake / autoconf
# python3 / pip3
# java-17-openjdk
# nodejs / npm
# sudo dnf install -y gcc gcc-c++ make automake autoconf \
# python3 python3-pip \
# java-17-openjdk \
# nodejs npm
# =============================================
# 文本搜索 / 处理
# =============================================
# ripgrep (rg): 更快更现代的 grep
# fd-find (fd): 更快更现代的 find
# jq: 命令行 JSON 处理
# tree: 目录树展示
# 注:AlmaLinux 包名是 fd-find(提供 fd 命令,需要 alias 或建软链)
sudo dnf install -y ripgrep fd-find jq tree
# fd-find 在 AlmaLinux 上是 /usr/bin/fd,要 alias 成 fd 才顺手
echo "alias fd='fd-find'" >> ~/.bashrc
# =============================================
# 安全相关
# =============================================
# fail2ban: 防 SSH 暴力破解
# firewalld: 防火墙(默认已装)
sudo dnf install -y fail2ban
📋 装完验证:
# 一次性看哪些工具可用 for tool in htop tmux jq tree vim git curl wget dnf mtr; do if command -v $tool &> /dev/null; then echo "✅ $tool" else echo "❌ $tool 缺失" fi done
4.2 工具速查表
| 🔧 工具 | 📝 用途 | 📋 常用命令 |
|---|---|---|
netstat |
网络连接/端口查看 | netstat -tlnp |
ss |
现代版 netstat | ss -tlnp、ss -s |
ip |
网络配置 | ip addr、ip route |
nmcli |
NetworkManager 命令行 | nmcli connection show |
dig |
DNS 查询 | dig baidu.com |
mtr |
网络诊断(ping+traceroute) | mtr baidu.com |
vim |
文本编辑 | vim /etc/hosts |
tmux |
终端复用 | tmux new -s name |
htop |
进程监控 | htop |
iotop |
磁盘 IO 监控 | sudo iotop |
iftop |
流量监控 | sudo iftop -i ens33 |
lsof |
查看打开的文件 | lsof -i :8080 |
tree |
目录树 | tree -L 2 /data |
jq |
JSON 处理 | cat x.json | jq . |
rg |
快速搜索 | rg "error" /var/log |
4.3 配置 Git(开发者必做)
git config --global user.name "Your Name"
git config --global user.email "your_email@example.com"
# 让命令输出带颜色
git config --global color.ui auto
# 解决中文文件名显示问题
git config --global core.quotepath false
4.4 配置 vim(可选但推荐)
vim ~/.vimrc
" 显示行号
set number
" 语法高亮
syntax on
" 缩进 4 空格
set tabstop=4
set softtabstop=4
set shiftwidth=4
set expandtab
" 搜索高亮
set hlsearch
set incsearch
" 编码
set encoding=utf-8
set fileencodings=utf-8,gbk,gb18030,gb2312
" 鼠标支持
set mouse=a
4.5 配置 bash 提示符(可选)
vim ~/.bashrc
在末尾追加:
# 彩色提示符
PS1='[\u@\h \W]\$ '
# 命令别名
alias ll='ls -alF'
alias la='ls -A'
alias l='ls -CF'
alias gs='git status'
alias gp='git pull'
alias ..='cd ..'
source ~/.bashrc
💡 AlmaLinux 默认 bash 提示符是
[\u@\h \W]\$,只显示最后一级目录名(W= basename of PWD);想显示完整路径用\w:PS1='[\u@\h \w]\$ '
五、网络与系统配置
5.1 配置静态 IP(NetworkManager / nmcli,仅真机/云服务器)
⚠️ 本节仅适用于真机 / 云服务器 / VMware/VirtualBox 虚拟机。WSL2 用户请直接跳过本节:
- WSL 装的发行版默认没装 NetworkManager(连
nmcli命令都没有)- WSL 微软官方镜像里
NetworkManager.service被 mask(屏蔽),即使手动dnf install装上,systemctl enable也会报Unit file ... is masked- WSL 网络由 Windows 虚拟网卡管理,Linux 侧任何网络配置都改不动
- 详见 七、WSL 用户专属指南 第 7.0 节
⚠️ WSL 下误装 NetworkManager 的清理方式:
# 如果已经装了但 enable 失败,先取消 mask sudo systemctl unmask NetworkManager # 然后关掉(WSL 下完全不需要) sudo systemctl disable --now NetworkManager 2>/dev/null || true # 彻底不想要可以卸载 # sudo dnf remove NetworkManager NetworkManager-libnm
AlmaLinux 9 统一使用 NetworkManager 管理网络(取代传统的 network-scripts)。命令行工具是 nmcli,图形化工具是 nmtui。
# 真机/云服务器:NetworkManager 通常已装,没装再装
sudo dnf install -y NetworkManager
sudo systemctl enable --now NetworkManager
# 查看网卡名称和当前连接
nmcli device status
# 输出示例:
# DEVICE TYPE STATE CONNECTION
# ens33 ethernet connected ens33
# lo loopback unmanaged --
# 查看当前连接的 IP 信息
nmcli connection show ens33
用 nmcli 配静态 IP(推荐,可重复执行):
# 1. 设置 IPv4 地址、子网掩码、网关
sudo nmcli connection modify ens33 \
ipv4.method manual \
ipv4.addresses 192.168.1.100/24 \
ipv4.gateway 192.168.1.1 \
ipv4.dns "223.5.5.5 8.8.8.8 114.114.114.114"
# 2. 激活新配置
sudo nmcli connection up ens33
# 3. 验证
ip -br addr show ens33
用 nmtui 配(图形化,更直观):
sudo nmtui
# 选 Edit a connection → 选 ens33 → 改 IPv4 配置为 Manual → 填 IP / 网关 / DNS
# 选 Activate a connection 让新配置生效
⚠️ 远程操作注意:改 IP 后
nmcli connection up会立即切换 IP,远程连接会断——确保你有其他方式连入(如云厂商控制台、KVM 直连),或者先在本地试好再上远程。💡 WSL2 用户:本节对你不适用。详见 七、WSL 用户专属指南。
5.2 配置主机名
# 查看当前主机名
hostnamectl
# 设置主机名(替换 dev-workspace 为你想要的名字)
sudo hostnamectl set-hostname dev-workspace
⚠️ hostnamectl 改了 /etc/hostname,但不会自动改 /etc/hosts!
hostnamectl set-hostname 只负责:
- 写入
/etc/hostname - 通知 systemd-hostnamed 更新主机名状态
不会自动写入 /etc/hosts,所以改完主机名后必须手动追加一行,否则 sudo 会报 unable to resolve host:
# 追加新主机名到 /etc/hosts(追加,不是覆盖!)
echo "127.0.1.1 dev-workspace" | sudo tee -a /etc/hosts
# 验证 sudo 不再报警
sudo whoami
完整的 /etc/hosts 应该长这样:
127.0.0.1 localhost
127.0.1.1 dev-workspace
💡 WSL2 用户:本节命令通用(启用 systemd 后),但操作步骤略有不同(要同步配
/etc/wsl.conf、在 PowerShell 重启 WSL)。详见 7.2 WSL 主机名设置。
5.3 时区与时间同步
# 查看当前时区
timedatectl
# 设置时区
sudo timedatectl set-timezone Asia/Shanghai
# AlmaLinux 默认自带 chrony(不是 systemd-timesyncd)
sudo systemctl enable --now chronyd
timedatectl status
📋 说明:
- 服务器与客户端的时间偏差超过 5 分钟会导致部分协议(如 Kerberos)失败。
- AlmaLinux 9 默认是
chrony(比systemd-timesyncd精度高、适合生产)。- 如需切回
systemd-timesyncd:sudo dnf install -y systemd-timesyncd && sudo systemctl disable --now chronyd && sudo systemctl enable --now systemd-timesyncd。
💡 WSL2 用户:WSL2 时间默认和 Windows 同步(启动时校准一次),一般不需要单独配。详见 7.3 WSL 时区(可选)。
5.4 关闭 AlmaLinux 默认组件(按需)
# 关闭 kdump(内核转储服务,节省内存)
sudo systemctl disable --now kdump.service
# 关闭防火墙自动发现相关(按需)
# sudo systemctl disable --now mdmonitor.service
# 查看所有已启用服务,按需关闭
sudo systemctl list-unit-files --state=enabled
📋 AlmaLinux 默认开机的服务(vs Ubuntu):
服务 AlmaLinux 默认 Ubuntu 默认 说明 firewalld✅ ❌(用 ufw) 防火墙 chronyd✅ ❌(用 systemd-timesyncd) 时间同步 kdump✅ ❌ 内核崩溃转储 sssd❌ ❌ 身份认证(可选) snapd❌ ✅ Snap 包管理
5.5 配置 dnf 更新源
💡 本节针对 AlmaLinux 9 默认源(
/etc/yum.repos.d/almalinux.repo、/etc/yum.repos.d/almalinux-appstream.repo等)。
9.x 用alma作为 repo id(AlmaLinux 8 用base/AppStream),具体看ls /etc/yum.repos.d/。
5.5.1 验证当前源
# 1. 确认 AlmaLinux 版本
cat /etc/almalinux-release
# 输出示例:AlmaLinux release 9.4 (Seafoam Ocelot)
# 2. 看默认源
ls /etc/yum.repos.d/
# 关键文件:
# almalinux.repo ← 基础源(os / baseos)
# almalinux-appstream.repo
# almalinux-extras.repo
# almalinux-highavailability.repo(可能没有)
# epel.repo(装了 EPEL 才有)
# 3. 看默认 baseurl
grep "^mirrorlist\|^baseurl" /etc/yum.repos.d/almalinux.repo | head -10
5.5.2 备份默认源
# 备份所有默认 repo
sudo mkdir -p /etc/yum.repos.d.bak.$(date +%Y%m%d%H%M%S)
sudo cp /etc/yum.repos.d/*.repo /etc/yum.repos.d.bak.$(date +%Y%m%d%H%M%S)/
5.5.3 替换为阿里云源(国内推荐)
方法一:一键替换(推荐)
# 阿里云提供的 mirrorlist 替换脚本(同时改 baseos / appstream / extras / highavailability / debuginfo 等)
sudo sed -i.bak \
-e 's|mirrorlist=|#mirrorlist=|g' \
-e 's|^# baseurl=https://repo.almalinux.org|baseurl=https://mirrors.aliyun.com|g' \
/etc/yum.repos.d/almalinux*.repo
# 验证改对了
grep "^baseurl" /etc/yum.repos.d/almalinux.repo
方法二:手动编辑(想完全控制内容时用)
sudo vim /etc/yum.repos.d/almalinux.repo
完整示例(AlmaLinux 9):
# =============================================
# /etc/yum.repos.d/almalinux.repo
# 阿里云镜像(AlmaLinux 9)
# =============================================
[baseos]
name = AlmaLinux 9 - BaseOS
mirrorlist = https://mirrors.almalinux.org/mirrorlist/9/baseos
# baseurl = https://repo.almalinux.org/almalinux/9/BaseOS/$basearch/os/
baseurl = https://mirrors.aliyun.com/almalinux/9/BaseOS/$basearch/os/
enabled = 1
gpgcheck = 1
gpgkey = file:///etc/pki/rpm-gpg/RPM-GPG-KEY-AlmaLinux-9
[appstream]
name = AlmaLinux 9 - AppStream
mirrorlist = https://mirrors.almalinux.org/mirrorlist/9/appstream
# baseurl = https://repo.almalinux.org/almalinux/9/AppStream/$basearch/os/
baseurl = https://mirrors.aliyun.com/almalinux/9/AppStream/$basearch/os/
enabled = 1
gpgcheck = 1
gpgkey = file:///etc/pki/rpm-gpg/RPM-GPG-KEY-AlmaLinux-9
[extras]
name = AlmaLinux 9 - Extras
mirrorlist = https://mirrors.almalinux.org/mirrorlist/9/extras
# baseurl = https://repo.almalinux.org/almalinux/9/extras/$basearch/os/
baseurl = https://mirrors.aliyun.com/almalinux/9/extras/$basearch/os/
enabled = 1
gpgcheck = 1
gpgkey = file:///etc/pki/rpm-gpg/RPM-GPG-KEY-AlmaLinux-9
5.5.4 配置 EPEL 源(重要)
AlmaLinux 9 默认不带 EPEL,但很多常用包(p7zip、fail2ban、htop 在 baseos 已有,fzf、fd-find 等可能在 EPEL)需要:
# 1. 装 EPEL 的 rpm 包(用阿里云镜像)
sudo dnf install -y https://mirrors.aliyun.com/epel/epel-release-latest-9.noarch.rpm
# 2. 启用 crb(CodeReady Builder,包含开发工具链的元数据)
sudo dnf config-manager --enable crb
# 也可能名字是 powertools,取决于版本:
# sudo dnf config-manager --enable powertools
# 3. 替换 EPEL 默认源为阿里云
# 注意:默认 epel.repo 里 baseurl 是被 # 注释掉的占位符(#baseurl= https://download.example/... ),
# 没有未注释的 baseurl 行可匹配——直接用 tee 覆盖最稳
sudo tee /etc/yum.repos.d/epel.repo > /dev/null <<'EOF'
[epel]
name=Extra Packages for Enterprise Linux 9 - $basearch
baseurl=https://mirrors.aliyun.com/epel/9/Everything/$basearch
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-9
[epel-debuginfo]
name=Extra Packages for Enterprise Linux 9 - $basearch - Debug
baseurl=https://mirrors.aliyun.com/epel/9/Everything/$basearch/debug
enabled=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-9
gpgcheck=1
[epel-source]
name=Extra Packages for Enterprise Linux 9 - $basearch - Source
baseurl=https://mirrors.aliyun.com/epel/9/Everything/source/tree
enabled=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-9
gpgcheck=1
EOF
# 4. 验证
grep "^baseurl" /etc/yum.repos.d/epel.repo
# 期望:看到 3 行 baseurl=https://mirrors.aliyun.com/epel/9/Everything/...
5.5.5 应用并验证
# 重建缓存
sudo dnf clean all
sudo dnf makecache
# 升级所有已装包
sudo dnf upgrade -y
# (可选)清理无用包
sudo dnf autoremove -y
验证用的是阿里云源:
# 看每个仓库的 baseurl 列
dnf repolist -v | grep -E "Repo-id|baseurl"
# baseurl 应是 mirrors.aliyun.com
5.5.6 其他国内镜像(按需替换 baseurl)
| 镜像 | baseurl 替换模式 | 说明 |
|---|---|---|
| 阿里云(最稳,首选) | repo.almalinux.org → mirrors.aliyun.com/almalinux |
同时换 EPEL 源 |
| 清华 TUNA | repo.almalinux.org → mirrors.tuna.tsinghua.edu.cn/almalinux |
学术网友好 |
| 中科大 USTC | repo.almalinux.org → mirrors.ustc.edu.cn/almalinux |
学术网友好 |
| 网易 | repo.almalinux.org → mirrors.163.com/almalinux |
通用 |
| 华为云 | repo.almalinux.org → mirrors.huaweicloud.com/almalinux |
通用 |
| 腾讯云 | repo.almalinux.org → mirrors.cloud.tencent.com/almalinux |
通用 |
📋 命名差异提醒:
- AlmaLinux 8 仓库 id 叫
base/AppStream(沿用 RHEL 8 命名)- AlmaLinux 9 仓库 id 叫
baseos/appstream(沿用 RHEL 9 命名)- 写脚本时不要假设
base,先dnf repolist确认
5.5.7 常见问题
Q1:换源后 dnf makecache 报 GPG 错误?
# 重新导入 GPG key(AlmaLinux 9)
sudo rpm --import https://mirrors.aliyun.com/almalinux/RPM-GPG-KEY-AlmaLinux-9
# 验证 key 已装
rpm -qa gpg-pubkey | grep -i almalinux
Q2:换源后 dnf makecache 报 404 Not Found?
# 99% 是 baseurl 拼错了(大小写、路径、版本号)
# 正确路径示例:
# https://mirrors.aliyun.com/almalinux/9/BaseOS/$basearch/os/
# https://mirrors.aliyun.com/almalinux/9/AppStream/$basearch/os/
# https://mirrors.aliyun.com/almalinux/9/extras/$basearch/os/
# https://mirrors.aliyun.com/epel/9/Everything/$basearch/
Q3:想临时恢复默认源?
# 还原备份
sudo cp /etc/yum.repos.d.bak.*/*.repo /etc/yum.repos.d/
sudo dnf clean all
sudo dnf makecache
Q4:怎么加第三方源(如 Docker、Node.js)?
# 例:加 Docker 官方源(AlmaLinux 走 CentOS 9 的源)
sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# 验证
dnf repolist | grep docker
5.5.8 一键脚本(适合批量初始化)
#!/bin/bash
# 阿里云 dnf 源一键配置(AlmaLinux 9)
set -e
BAK_DIR="/etc/yum.repos.d.bak.$(date +%Y%m%d%H%M%S)"
# 1. 备份
sudo mkdir -p "$BAK_DIR"
sudo cp /etc/yum.repos.d/*.repo "$BAK_DIR/" 2>/dev/null || true
echo "✅ 备份到 $BAK_DIR"
# 2. 替换默认源
if ls /etc/yum.repos.d/almalinux*.repo &>/dev/null; then
sudo sed -i \
-e 's|mirrorlist=|#mirrorlist=|g' \
-e 's|^# baseurl=https://repo.almalinux.org|baseurl=https://mirrors.aliyun.com|g' \
/etc/yum.repos.d/almalinux*.repo
echo "✅ 默认源已替换为阿里云"
fi
# 3. 装 EPEL(如果没有)
if ! rpm -q epel-release &>/dev/null; then
sudo dnf install -y https://mirrors.aliyun.com/epel/epel-release-latest-9.noarch.rpm
echo "✅ EPEL 已装"
fi
# 4. 替换 EPEL 源(用 tee 直接覆盖,最稳)
if [ -f /etc/yum.repos.d/epel.repo ]; then
sudo tee /etc/yum.repos.d/epel.repo > /dev/null <<'EOF'
[epel]
name=Extra Packages for Enterprise Linux 9 - $basearch
baseurl=https://mirrors.aliyun.com/epel/9/Everything/$basearch
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-9
EOF
echo "✅ EPEL 源已覆盖为阿里云"
fi
# 5. 启用 crb(开发工具链元数据源)
sudo dnf config-manager --enable crb 2>/dev/null || true
# 6. 刷新
sudo dnf clean all
sudo dnf makecache
echo "✅ dnf makecache 完成"
保存为 ~/set-aliyun-mirror.sh,跑:
chmod +x ~/set-aliyun-mirror.sh
sudo ~/set-aliyun-mirror.sh
📋 关于 AlmaLinux 版本号:
- AlmaLinux 8 仓库 id 用
base/AppStream(baseurl 子目录8/)- AlmaLinux 9 仓库 id 用
baseos/appstream(baseurl 子目录9/)- 切换版本时必须改
baseurl里的版本号和仓库 id
六、安全与优化
6.1 firewalld 防火墙
详见 3.6 防火墙放行 SSH,补充常用规则:
# 查看所有区域和规则
sudo firewall-cmd --list-all
# 放行 HTTP/HTTPS
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
# 放行指定端口
sudo firewall-cmd --permanent --add-port=8080/tcp
sudo firewall-cmd --reload
# 富规则:放行指定 IP 段访问 SSH(更安全)
sudo firewall-cmd --permanent --remove-service=ssh
sudo firewall-cmd --permanent --add-rich-rule='rule family=ipv4 source address=192.168.1.0/24 service name=ssh accept'
sudo firewall-cmd --reload
# 富规则:拒绝特定 IP
sudo firewall-cmd --permanent --add-rich-rule='rule family=ipv4 source address=10.0.0.5 reject'
sudo firewall-cmd --reload
# 删除规则
sudo firewall-cmd --permanent --remove-service=http
sudo firewall-cmd --reload
# 关闭防火墙(不推荐生产)
sudo systemctl stop firewalld
sudo systemctl disable firewalld
⚠️ 远程操作注意:在远程主机上启用防火墙前,先确认 SSH 规则已加(
firewall-cmd --permanent --add-service=ssh)。firewalld 默认会放行 ssh 服务的默认区域,但自定义规则可能被遗忘。💡 WSL2 用户:WSL 内 firewalld 跑不起来(微软内核缺 iptables 模块)。详见 七、WSL 用户专属指南 第 7.6 节。
6.1.1 重要认知:放行了端口,外部仍可能连不上
🎯 本节适用场景:按上面示例配了
firewall-cmd --permanent --add-port=2211/tcp后,外部客户端仍然连不上 2211,而firewall-cmd --list-all又能看到 2211/tcp 已放行。这是 firewalld zone 模型下最常见的"看起来配了但没生效"的踩坑。
根本原因:firewalld 的规则是挂在 zone 上的,而 zone 又挂在网卡接口上。数据包进入 Linux 后,firewalld 会按"它从哪块网卡进来"找对应的 zone,再按 zone 里的规则判断放行/拒绝。所以:
| 步骤 | 数据包进入 → 匹配 zone → 应用 zone 规则 |
|---|---|
| 1. 数据包到达网卡 | 例如从 eth0(公网网卡)进来 |
| 2. 找 zone | firewalld 看 eth0 绑在哪个 zone |
| 3. 匹配规则 | 用那个 zone 里的 services / ports / rich-rules 判断 |
关键点:firewall-cmd --add-port=2211/tcp(不带 --zone=)默认写入的是 public zone(firewalld 的默认 zone)。如果 eth0 没绑到 public zone(也没绑到任何带 2211 规则的 zone),那 2211 的放行规则就根本没有机会被命中——数据包走 eth0 的默认 zone(一般是 trusted 之外的某个 zone 或直接被 block),被默默拦截。
典型症状:
firewall-cmd --list-all能看到publiczone 有2211/tcp,但--zone=public --list-interfaces输出里没有eth0firewall-cmd --get-active-zones显示eth0在dockerzone 或其它 zone(不一定有 2211 规则)- 外部
telnet <IP> 2211/ssh -p 2211/ 应用客户端连接都超时 - 但同主机内
curl http://127.0.0.1:2211能通(回环不走 firewalld)
为什么会这样(按出现频率排序):
| 原因 | 说明 |
|---|---|
加端口时没指定 zone,默认加到了 public |
但 eth0 从一开始就没绑 public(默认是 trusted 之外的 zone,或装 Docker 后被自动挪走) |
装了 Docker,docker0 网桥被 firewalld 自动放进了 docker zone |
同一时间 eth0 也可能被自动挪到 docker zone(因为 dockerd 改了 iptables 链),但 docker zone 的规则集跟 public 不一样 |
多网卡场景(eth0 + eth1 + bond0),只把其中一个绑到了 zone |
其它网卡上的服务从公网进不来 |
排查命令:
# 1. 看每个 zone 当前绑了哪些接口
firewall-cmd --get-active-zones
# 典型输出:
# docker
# interfaces: docker0
# public
# interfaces: ← ⚠️ eth0 没在这里
# 2. 看 public zone 里有哪些规则(确认端口确实加进去了)
firewall-cmd --zone=public --list-all
# 关键看 ports: 行有没有 2211/tcp
# 3. 看 eth0 到底绑在哪个 zone
firewall-cmd --get-zone-of-interface=eth0
# 输出可能是:docker / trusted / nozone
# 4. 看所有 zone 的接口绑定(最全)
firewall-cmd --list-all-zones | grep -E "^[a-z]|interfaces"
# 5. 确认数据包是否真的被 firewalld 拦截(不需要抓包)
sudo firewall-cmd --set-log-denied=all # 临时开启拒绝日志(重启 firewalld 后失效)
# 然后从外部连一次,看 /var/log/messages:
sudo tail -f /var/log/messages | grep -i "REJECT|DROP"
修复方法(按推荐度排序):
方法 A:把 eth0 显式绑到已放行目标端口的 zone(推荐)
# 假设 2211/tcp 已加在 public zone,把 eth0 也绑到 public
sudo firewall-cmd --zone=public --add-interface=eth0 --permanent
sudo firewall-cmd --reload
# 验证:eth0 现在应在 public zone 下
firewall-cmd --get-active-zones
# public
# interfaces: eth0
# 从外部再连一次 2211
方法 B:把端口直接加到 eth0 当前所在的那个 zone
# 先查 eth0 在哪个 zone
ZONE=$(firewall-cmd --get-zone-of-interface=eth0)
echo "eth0 当前 zone: $ZONE"
# 把 2211 加到那个 zone
sudo firewall-cmd --zone=$ZONE --add-port=2211/tcp --permanent
sudo firewall-cmd --reload
方法 C:临时把 eth0 加到 trusted(⚠️ 仅本地调试用)
# trusted = 放行所有流量,等于"对这个网卡关防火墙"
sudo firewall-cmd --zone=trusted --add-interface=eth0 --permanent
sudo firewall-cmd --reload
# 调通后**记得改回**对应的 zone,别留着 trusted
方法 D:用富规则(rich-rule)绕过 zone 匹配
# 富规则默认写到 public zone,跟方法 A 等价
sudo firewall-cmd --permanent --add-rich-rule='rule family=ipv4 source address=0.0.0.0/0 port port=2211 protocol=tcp accept'
sudo firewall-cmd --reload
💡 选哪个方法的判断思路:
场景 推荐方法 单网卡服务器,端口明确加在 public A(最直接) 端口在多个 zone 里都要放行(多网卡共用) 把每块网卡分别绑到对应 zone,再 add-port临时调试 / 验证是不是 zone 配错了 C(trusted),验证完改回 只想对特定 IP 放行(如内网管理端口) D(rich-rule + source address) 服务器装了 Docker,且 dockerd 把 eth0 抢到 docker zone 先 docker network inspect看 docker 怎么管的 iptables,再决定要不要把 eth0 挪回 public
与 Docker 共存时的额外注意事项:
- dockerd 安装时会自动在 firewalld 里建一个
dockerzone(/usr/lib/firewalld/zones/docker.xml),并把docker0网桥绑进去 - docker 启动容器时默认会把端口映射规则写到 iptables 的
DOCKER链(绕过 firewalld 的 zone 检查),所以容器暴露的端口一般不踩这个坑 - 但宿主机自己起的服务(比如 systemctl 启动的 sshd / nginx / 自定义应用)仍然走 firewalld zone 匹配,需要按上面方法处理
- 如果
eth0被 docker 抢到了dockerzone,而dockerzone 默认只放行 docker 通讯相关的端口,宿主机非 docker 服务就会受牵连
WSL2 用户注意:
- WSL2 内 firewalld 跑不起来(详见 7.6),通常已经
disable了,不会遇到这个坑 - 但如果 WSL 启用了镜像网络模式(
networkingMode=mirrored,详见WSL 虚拟机创建与管理指南.md),流量走 Windows 宿主侧,由 Windows 防火墙控制,不再走 WSL 内的 firewalld——本节问题在镜像模式下变成"Windows 防火墙是否放行 2211",与本节无关
6.2 fail2ban 防爆破
sudo dnf install -y fail2ban
sudo vim /etc/fail2ban/jail.local
[DEFAULT]
# 封禁时间(1 小时)
bantime = 1h
# 监测时间窗口(10 分钟)
findtime = 10m
# 最大重试次数
maxretry = 5
# 封禁动作(firewalld 集成)
banaction = firewallcmd-rich-rules
banaction_allports = firewallcmd-rich-rules
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = %(sshd_log)s
backend = %(sshd_backend)s
maxretry = 3
📋 AlmaLinux 9 的 fail2ban 注意:
/var/log/secure是 SSH 认证日志(不是 Ubuntu 的/var/log/auth.log)- fail2ban 默认配
logpath = %(sshd_log)s,会自动读/var/log/securebanaction用firewallcmd-rich-rules(通过 firewall-cmd 加富规则封禁),不要写ufw(Ubuntu 风格)
sudo systemctl enable --now fail2ban
sudo systemctl status fail2ban
# 查看封禁列表
sudo fail2ban-client status sshd
# 手动解封某 IP
sudo fail2ban-client set sshd unbanip 1.2.3.4
6.3 SELinux 处理
💡 本节是 AlmaLinux / RHEL 系列的特色。Ubuntu / Debian 不需要关心(用 AppArmor)。
6.3.1 SELinux 状态
# 看当前状态
sestatus
# 输出示例:
# SELinux status: enabled
# SELinuxfs mount: /sys/fs/selinux
# SELinux root directory: /etc/selinux
# Loaded policy name: targeted
# Current mode: enforcing
# Mode from config file: enforcing
# 三种模式
getenforce
# enforcing / permissive / disabled
| 模式 | 行为 |
|---|---|
enforcing |
强制执行(默认)——违反策略的行为被阻止并记日志 |
permissive |
仅警告——不阻止,但记 audit log(用于调试策略) |
disabled |
完全关闭(不推荐) |
6.3.2 临时切换模式
# 临时切到 permissive(重启后失效)
sudo setenforce 0
getenforce
# Permissive
# 切回 enforcing
sudo setenforce 1
getenforce
# Enforcing
6.3.3 永久切换模式
sudo vim /etc/selinux/config
# 把 enforcing 改成 permissive
SELINUX=permissive
# 改完要重启系统生效
sudo reboot
6.3.4 常见 SELinux 故障
症状 1:服务起不来,日志有 SELinux is preventing 警告
# 1. 看完整诊断
sudo ausearch -m avc -ts recent
# 2. 装 setroubleshoot 看人话报告
sudo dnf install -y setroubleshoot
sudo sealert -a /var/log/audit/audit.log
# 3. 让 SELinux 自动生成允许规则(最快)
sudo ausearch -m avc -ts recent | audit2allow -M my-fix
sudo semodule -i my-fix.pp
症状 2:改了 SSH 端口后连不上
# SELinux 限制了 sshd 只能监听预定义端口
# 添加端口到 SELinux 策略
sudo semanage port -a -t ssh_port_t -p tcp 2222
# 或临时关 SELinux 验证
sudo setenforce 0
症状 3:改了 Web 服务目录后访问 403/404
# SELinux 上下文不对
# 看现在是什么类型
ls -Z /var/www/html/
# -rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 index.html
# 改完目录后恢复上下文
sudo restorecon -Rv /var/www/html/
症状 4:WSL 里的 AlmaLinux 看到一堆 SELinux 警告
💡 WSL2 用户:WSL2 不支持完整 SELinux,详见 七、WSL 用户专属指南 第 7.5 节,那里有完整的 WSL 专属配置脚本(一键切到 permissive + 持久化)。
🔐 安全建议:
- 生产环境:保持
enforcing,遇到问题用audit2allow加规则- 开发/测试环境:
permissive更省心- 完全关掉(disabled)不推荐——失去了 SELinux 的最后一道防线
6.4 文件描述符限制
大并发服务(Tomcat、Nginx 等)经常遇到 too many open files 错误。
# 查看当前限制
ulimit -n
# 临时修改(当前会话)
ulimit -n 65535
永久修改:
sudo vim /etc/security/limits.conf
* soft nofile 65535
* hard nofile 65535
root soft nofile 65535
root hard nofile 65535
📋 说明:
*匹配所有非 root 用户,root 要单独写(limits.conf规则:通配符不作用于 root)- 两组值看起来一样,但不能合并——这是
limits.conf的限制- 没加 nproc:进程数 65535 没意义,默认就够用;除非跑大并发服务(如 MySQL、Kafka)才需要
sudo vim /etc/systemd/system.conf
找到 #DefaultLimitNOFILE=1024:524288 这一行,取消注释并改为 65535:
DefaultLimitNOFILE=65535
📋 为什么需要改:
- systemd 默认:
soft=1024,hard=524288- 所有用
systemctl启动的服务(fail2ban、sshd、nginx、mysql等)都受这个限制- 默认 1024 对大并发服务不够:nginx 一个连接 2~3 个 FD,1024 / 3 ≈ 340 并发就报
too many open files- 改
soft到 65535 是生产/开发环境的标配
# 重启后生效
sudo reboot
💡 WSL2 用户:不要用
sudo reboot(WSL 下不重读 system.conf)。改完system.conf后必须wsl --shutdown——详见 七、WSL 用户专属指南 第 7.7 节。
6.5 内核参数调优
sudo vim /etc/sysctl.d/99-tuning.conf
# =============================================
# 网络优化
# =============================================
# 允许端口复用(TIME_WAIT 快速回收)
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_fin_timeout = 15
# 提升 TCP 缓冲区
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
# SYN 队列长度(防 SYN 洪水)
net.ipv4.tcp_max_syn_backlog = 8192
net.core.somaxconn = 8192
# 启用 SYN Cookie
net.ipv4.tcp_syncookies = 1
# =============================================
# 安全加固
# =============================================
# 禁用 IP 转发(单机部署不需要)
net.ipv4.ip_forward = 0
# 忽略 ICMP 重定向(防中间人)
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.default.secure_redirects = 0
# 忽略源路由
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
# 开启反向路径过滤
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
# 记录可疑包
net.ipv4.conf.all.log_martians = 1
sudo sysctl -p /etc/sysctl.d/99-tuning.conf
📋 AlmaLinux 9 + WSL 注意:
- 真机/云服务器:
sysctl -p立即生效- WSL2:大部分网络相关参数由 Windows 宿主内核控制,配置仅作记录
- WSL2 + 启用 systemd 后,
sysctl -p命令本身能跑,但ip_forward、tcp_*等设置可能没真正生效
6.6 配置 Swap(如内存较小)
# 查看当前 swap
free -h
swapon --show
# 创建 4G swap 文件
sudo fallocate -l 4G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
# 永久生效
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
# 调整 swappiness(值越小越倾向用物理内存,推荐 10-30)
echo 'vm.swappiness=10' | sudo tee -a /etc/sysctl.d/99-tuning.conf
sudo sysctl -p
📋 SELinux + swapfile:
- AlmaLinux 9 默认 SELinux 是 enforcing
fallocate创建的/swapfile默认会被正确打标为swapfile_t- 如果
swapon报 SELinux 错误:sudo restorecon /swapfile
七、WSL 用户专属指南(WSL2 用户必读)
🎯 章节定位:把 WSL 专属操作集中到这一章。真机/云服务器用户可整章跳过。
推荐阅读顺序(按章节顺序):
- 7.0 补齐缺失包 —— 必做前置(4.1 装完后,再补一遍 WSL 缺的)
- 7.1 启用 systemd —— 第二步要做(没启用前 systemctl 都不能用)
- 7.2 主机名 —— 消除
sudo unable to resolve host警告- 7.3 时区 —— 可选(WSL 默认跟 Windows 同步)
- 7.4 数据目录规划 —— WSL 重装会丢数据,提前软链到 Windows 盘
- 7.5 SELinux —— 减少日志噪音(或跳过,WSL 内 SELinux 跑不起来)
- 7.6 firewalld —— WSL 内跑不起来,直接关掉
- 7.7 重启正确方式 —— 不要
sudo reboot,要wsl --shutdown涵盖内容:
- 7.0 WSL 精简 rootfs 缺失包补齐(必做前置)
- 7.1 WSL 启用 systemd + 配
/etc/wsl.conf- 7.2 WSL 主机名设置(持久化 + 同步 hosts)
- 7.3 WSL 时区(已跟 Windows 同步,可选配)
- 7.4 WSL 数据目录规划
- 7.5 WSL 内 SELinux 处理(关掉日志噪音)
- 7.6 WSL 内 firewalld/fail2ban 关掉
- 7.7 WSL 重启正确方式 + 配置生效规则
🔗 通用 WSL 基础(systemd 启用、镜像网络、
hostAddressLoopback等更细节的内容)详见WSL 虚拟机创建与管理指南.md第 4~6 节。AlmaLinux-9 在 WSL 内的行为与 Ubuntu 24.04 几乎完全一致(包管理器不同;WSL 内部机制相同)。
7.0 WSL 精简 rootfs 缺失包补齐(必做前置)
🎯 为什么需要这一节:WSL 微软官方镜像默认是 nano/server 精简版——真机上有的
nmcli/firewall-cmd/getenforce/chronyc/htop/jq/p7zip都没装。4.1 节的一键安装清单已经覆盖了真机/云服务器场景,但你 WSL 内执行那一段后,本节专治 WSL 精简 rootfs 多出来的"补丁包"。
WSL 默认缺失的命令 / 对应包(在 4.1 基础上额外要装的):
| 缺失命令 | 装的包 | 用途 |
|---|---|---|
nmcli |
NetworkManager NetworkManager-libnm |
配 IP(WSL 下用不上但装了不亏) |
firewall-cmd |
firewalld |
6.1 配防火墙(WSL 下用不上,要 disable) |
getenforce / sestatus |
policycoreutils |
6.3 / 7.5 查 SELinux |
chronyc |
chrony |
5.3 时间同步(WSL 下用不上,要 disable) |
htop / iotop / iftop / lsof / strace |
htop iotop iftop sysstat lsof strace |
监控/排查 |
ncdu / jq / tree |
ncdu jq tree |
磁盘/JSON/目录 |
p7zip / 7z |
p7zip p7zip-plugins(EPEL) |
解压 7z |
tmux / bash-completion |
tmux bash-completion |
终端增强 |
📋 关于 4.1 节和 7.0 节的关系:
- 4.1 节给真机/云服务器用户看,包含全部常用包
- 7.0 节给 WSL 用户看,只列 WSL 精简 rootfs 额外缺的(4.1 没列但 WSL 没装的)
- 真机/云服务器用户可跳过本节(4.1 已经全装齐了)
- WSL 用户两个都要跑:先 4.1,再 7.0 补一遍
WSL 专用补齐命令(注释行不带 \ 续行,分块安装避免 dnf 把 # 当包名):
# === WSL 精简 rootfs 补齐(4.1 之外额外缺的)===
# 前提:已按 5.5.4 装好 EPEL 源(p7zip 在 EPEL 里)
# 网络 / 防火墙(WSL 用不上,装着备用)
sudo dnf install -y NetworkManager NetworkManager-libnm firewalld
# SELinux 工具
sudo dnf install -y policycoreutils
# 时间同步
sudo dnf install -y chrony
# 监控
sudo dnf install -y htop iotop iftop sysstat lsof strace ncdu
# 文本处理
sudo dnf install -y jq tree
# 7z(EPEL)
sudo dnf install -y p7zip p7zip-plugins
# === fd-find 别名(如果 4.1 还没跑)===
echo "alias fd='fd-find'" >> ~/.bashrc
source ~/.bashrc
# === 验证 ===
for tool in getenforce chronyc htop jq tree 7z fd; do
if command -v $tool &>/dev/null; then
echo "✅ $tool"
else
echo "❌ $tool 缺失"
fi
done
⚠️ 关键坑:
- dnf 不支持
#注释——sudo dnf install -y \下面跟# 注释 \会被 dnf 当成"包名是注释"- 每行用
\续行时,注释单独一行写在dnf外——# xxx紧跟dnf install命令会被吞掉但包名解释错- 多行包名推荐分块:
sudo dnf install -y 包1 包2(一行多个)比 `\ 续行更稳
💡 WSL 下"装了也别 enable":
firewalld/chrony/fail2ban/NetworkManager装了之后别 enable(WSL 内跑不起来——详见 7.6)getenforce能用但返回Disabled(WSL 内 SELinux 子系统没装,详见 7.5)
7.1 WSL 启用 systemd + 配 /etc/wsl.conf
WSL 装的发行版默认 PID 1 是 init,不是 systemd——所有 systemctl / hostnamectl / timedatectl 工具都不能用。启用 systemd 是 WSL 初始化的第一步。
# 写 wsl.conf(必须用整段覆盖,确保 5 个段都在;用 sed 改一行容易匹配不上)
sudo tee /etc/wsl.conf > /dev/null << 'EOF'
[user]
default = root
[boot]
systemd = true
[automount]
enabled = true
mountFsTab = true
[interop]
enabled = true
appendWindowsPath = true
[network]
generateHosts = false
hostname = alma9-workspace
EOF
⚠️ 关键提醒:
- 必须 5 个段都写(user / boot / automount / interop / network)—— 缺段会导致配置不生效
hostname = alma9-workspace写在[network]段(不在[host]或别的地方)—— 这是 WSL 唯一识别的位置- 别用 sed 改一行—— 等号前后的空格、
= truevs=true都可能让 sed pattern 匹配不上;用tee整段覆盖最稳📋 各段作用:
[user] default = root—— WSL 默认登录用户(你的发行版默认就是 root,可改成普通用户)[boot] systemd = true—— 启用 systemd(systemctl/hostnamectl等工具的前提)[automount] enabled/mountFsTab = true—— 自动挂载 Windows 盘(/mnt/c、/mnt/d)[interop] enabled/appendWindowsPath = true—— 允许从 WSL 调 Windows 程序 + 把 Windows PATH 加进来[network] generateHosts = false—— 阻止 WSL 覆盖/etc/hosts(改了主机名/自定义 hosts 时必加)[network] hostname = xxx—— WSL 启动时强制把 Linux 主机名设成这个值(不被 Windows 计算机名覆盖)
在 Windows PowerShell 重启 WSL:
wsl --shutdown
wsl -d AlmaLinux-9-DockerCompose
回到 WSL 验证:
# PID 1 应该是 systemd
ps -p 1 -o comm=
# 期望输出:systemd
# hostname 应该是 wsl.conf 里设的
hostname
# 期望输出:alma9-workspace
⚠️ 不要用
sudo reboot重启 WSL——WSL 不是真硬件,reboot只杀进程、不会重读wsl.conf。必须在 Windows PowerShell 跑wsl --shutdown。详见 7.7。
7.2 WSL 主机名设置
📋 前置:先完成 7.1 WSL 启用 systemd——wsl.conf 必须写完整(5 个段都在),否则即使改了主机名也持久化不了。
7.2.1 核心认知:/etc/wsl.conf 才是"主"
WSL 主机名有两层"控制权":
| 来源 | 优先级 | 作用 |
|---|---|---|
/etc/wsl.conf 的 [network] hostname = xxx |
优先 | 每次 WSL 启动时由 Windows 侧读取,强制覆盖 Linux 主机名 |
hostnamectl set-hostname xxx |
次之 | 运行时改主机名,但重启后会被 wsl.conf 覆盖 |
| Windows 计算机名 | 默认 | 啥都没配时,WSL 用 Windows 计算机名当 Linux 主机名 |
关键点:你必须在 wsl.conf 里写 hostname = xxx,单靠 hostnamectl 是持久化不了的。
7.2.2 完整步骤
第 1 步:确认 wsl.conf 已经写对
cat /etc/wsl.conf
# 必须包含这 5 个段:[user] / [boot] / [automount] / [interop] / [network]
# 关键是 [network] 段:
# [network]
# generateHosts = false
# hostname = alma9-workspace
如果 wsl.conf 缺段或 hostname 不是你想的,用 tee 整个覆盖(不要用 sed 改一行——sed 的 pattern 不一致容易匹配不上):
sudo tee /etc/wsl.conf > /dev/null << 'EOF'
[user]
default = root
[boot]
systemd = true
[automount]
enabled = true
mountFsTab = true
[interop]
enabled = true
appendWindowsPath = true
[network]
generateHosts = false
hostname = alma9-workspace
EOF
⚠️ 常见踩坑:
- wsl.conf 只有 1~2 段(如只写了
[boot] systemd=true)—— 持久化失效,Windows 计算机名会覆盖- 用 sed 改一行 hostname 失败—— sed 的 pattern 跟 wsl.conf 里的格式(等号前后空格、
= truevs=true)对不上,匹配不到。用tee整段覆盖最稳- 改了 wsl.conf 但没
wsl --shutdown——配置不会生效
第 2 步:Windows PowerShell 重启 WSL
# 必须用 wsl --shutdown(不是 wsl -d 重开)
wsl --shutdown
# 然后再进
wsl -d AlmaLinux9-DockerCompose
⚠️ 怎么确认"真的重启了":
- 进 WSL 后立刻看主机名:应该是 wsl.conf 里写的(不是 Windows 计算机名)
- 如果还是 Windows 计算机名 = wsl.conf 没生效
第 3 步:WSL 内补全配置(保险)
# 1. 同步 /etc/hosts(追加,不是覆盖!)
echo "127.0.1.1 alma9-workspace" | sudo tee -a /etc/hosts
# 2. 可选:hostnamectl 也设一遍(当前会话立即生效;wsl.conf 持久化)
sudo hostnamectl set-hostname alma9-workspace
# 3. 验证 sudo 不再报警
sudo whoami
# 应直接返回 root,无 "unable to resolve host" 警告
7.2.3 验证清单
| ✅ 检查项 | 🔧 命令 | 🎯 预期 |
|---|---|---|
| 主机名是预期值 | hostname |
alma9-workspace |
| wsl.conf 写对了 | cat /etc/wsl.conf |
含 5 段,[network] hostname = alma9-workspace |
| hosts 有手动加的行 | grep "$(hostname)" /etc/hosts |
看到 127.0.1.1 alma9-workspace |
| sudo 不报警 | sudo whoami |
直接返回 root,无 "unable to resolve host" |
| systemd 启用了 | ps -p 1 -o comm= |
systemd(不是 init) |
7.2.4 故障排查
| 症状 | 原因 | 解决 |
|---|---|---|
wsl --shutdown 后 hostname 还是 Windows 计算机名 |
wsl.conf 没生效 / 段不全 | 用 tee 整段覆盖 wsl.conf,再 wsl --shutdown |
| sudo 报 "unable to resolve host xxx" | /etc/hosts 没加那行 |
echo "127.0.1.1 $(hostname)" | sudo tee -a /etc/hosts |
hostnamectl set-hostname 改了但重启丢失 |
wsl.conf 没写 hostname = xxx |
改 wsl.conf(不要只靠 hostnamectl) |
| sed 改 wsl.conf 一行没生效 | pattern 跟实际格式不匹配(空格、大小写) | 用 tee 整段覆盖 |
7.3 WSL 时区(可选)
WSL2 的时间默认和 Windows 同步(WSL 启动时从 Windows 校准一次),所以一般不需要单独配时区。如果发现时间漂移:
# 强制跟 Windows 校准
sudo hwclock -s
# 或显式设时区(启用 systemd 后才生效)
sudo timedatectl set-timezone Asia/Shanghai
7.4 WSL 数据目录规划
WSL2 本质是一个 ext4 虚拟磁盘文件(ext4.vhdx)挂载到 /。WSL 出问题需要重装、迁移、换发行版时,根目录里的数据会全部丢失;但 /mnt/c/、/mnt/d/ 是直接读 Windows 文件系统,完全不受影响。
7.4.1 先理解 WSL2 的"磁盘"是怎么回事
df -h
典型输出(已实测 WSL2 AlmaLinux-9):
/dev/sde 1007G 2.0G 954G 1% / ← 根目录所在的虚拟磁盘(最大块)
/dev/sdd 1007G 5.3G 951G 1% /mnt/wsl/... ← Docker Desktop 存储(也是 vhdx)
none 7.8G ... ... ... /mnt/wsl/drivers ← WSL 内部通道挂载(不是存储)
C:\ 401G 305G 96G 77% /mnt/c ← Windows C 盘
D:\ 552G 397G 155G 72% /mnt/d ← Windows D 盘
📋 AlmaLinux-9 vs Ubuntu 24.04 在 WSL2 上的关键差异:
- AlmaLinux-9 自带
/data(CentOS/RHEL 传统),WSL2 装的版本同样会建- 默认有
/data、/srv、但没有/opt下的具体服务目录- SELinux 配置文件
/etc/selinux/config默认是 enforcing(WSL2 实际不强制执行,但写在那里)
7.4.2 推荐:把重要数据放到 Windows 盘
为什么? WSL 出问题需要重装、迁移、换发行版时,根目录里的数据会全部丢失;但 /mnt/c/、/mnt/d/ 是直接读 Windows 文件系统,完全不受影响。
# 1. 在 Windows D 盘建一个固定目录(PowerShell 或文件管理器都行)
# 路径示例:D:\wsl-data
# 2. 在 WSL 里建软链接(个人数据放这)
mkdir -p /mnt/d/wsl-data
ln -s /mnt/d/wsl-data ~/data
# 3. 给项目、数据库、下载等建子目录
mkdir -p /mnt/d/wsl-data/{projects,downloads,backups,db,logs}
# 4. 验证
ls -ld ~/data
df -h /mnt/d
💡 软链 vs 直接挂载:
- 软链(推荐)→
~/data→/mnt/d/wsl-data,既能在 WSL 用,也能在 Windows 资源管理器直接打开/mnt/d/路径直接用也行,但路径长、可读性差
7.4.3 AlmaLinux 默认就有 /data,但建议结合软链使用
从 AlmaLinux / RHEL / CentOS 装出来的 WSL 实例默认就有 /data 目录(保留 CentOS 传统)。这是发行版设计理念的差异:
| 发行版 | 默认有没有 /data |
原因 |
|---|---|---|
| AlmaLinux / RHEL / CentOS | ✅ 有 | 安装器按"服务器用途"分区模板自动创建(/boot、swap、/、/home、/data) |
| Ubuntu / Debian | ❌ 没有 | 严格遵守 FHS:/ 下只放系统目录,业务目录由用户/管理员自己规划 |
AlmaLinux /data 的传统用途:
- 放第三方应用(Oracle、MySQL 早期默认数据目录)
- 放业务服务数据(公司内部约定的"业务数据根目录")
- 隔离系统盘和业务盘(
/满了/data还能撑)
WSL2 下推荐:
| 场景 | 建议 |
|---|---|
| WSL 跑服务(Docker Compose、数据库) | ✅ 用 /data 存服务数据(AlmaLinux 习惯) |
| 个人临时数据 | ✅ 用 ~/data 或软链到 /mnt/d/wsl-data |
| WSL 重装不能丢的 | ✅ 必放 /mnt/d/wsl-data(WSL 重装会重置 /data) |
| 跑生产服务(数据库、消息队列) | ✅ 放 /data/<service>,或 /srv/<service>(FHS 标准) |
⚠️ 重要提醒:WSL 重装/换发行版会重置整个
/(包括/data),重要数据务必放/mnt/c、/mnt/d或外部盘。
7.4.4 在根目录建 /data 也可行,但需充分了解其风险与限制
# AlmaLinux 默认就有 /data,只需确保权限
ls -ld /data
# dr-xr-xr-x. 2 root root ... /data
# 默认 root 拥有且只读,其他用户写不进去,需要 chmod
sudo chown -R $USER:$USER /data
# 或建子目录
sudo mkdir -p /data/{mysql,redis,logs}
sudo chown -R $USER:$USER /data
适用场景:临时数据、容器卷、一次性实验。
不适用场景:长期重要数据、数据库文件、git 仓库、备份(一旦 WSL 损坏就丢了)。
7.4.5 重要:定期回收虚拟磁盘空间
WSL2 的 ext4.vhdx 是稀疏文件——在 WSL 里 rm 一个大文件,Windows 侧的 vhdx 不会自动缩小。长时间使用后,Windows 资源管理器显示 vhdx 文件大小为 500 GB,但 WSL 内部实际数据仅占 50 GB。
先确认你的 ext4.vhdx 在哪:
# 方法 1:wsl 命令直接显示(PowerShell)
wsl -l -v
# 方法 2:全盘搜 ext4.vhdx(最通用)
Get-ChildItem C:\,D:\,E:\ -Recurse -Filter ext4.vhdx -ErrorAction SilentlyContinue | Select-Object FullName, Length
# 方法 3:按安装方式找
# - Microsoft Store 安装: %LOCALAPPDATA%\Packages\...\LocalState\ext4.vhdx
# - 手动 wsl --import: 你 import 时指定的路径,如 D:\wsl\AlmaLinux-9-DockerCompose\ext4.vhdx
手动回收(PowerShell 管理员):
# 1. 关闭所有 WSL 实例
wsl --shutdown
# 2. 用 diskpart 压缩
diskpart
进入 diskpart 后输入:
select vdisk file="D:\wsl\AlmaLinux-9-DockerCompose\ext4.vhdx"
compact vdisk
exit
⚠️ 注意:
- 用管理员 PowerShell 运行(否则 diskpart 报"权限不足")
- WSL 要已关(否则 vhdx 被占用会报"文件正被另一个进程使用")
compact vdisk期间会临时再占用 1~2 倍当前 vhdx 大小的空闲空间(D 盘至少留 50%)
一键脚本(推荐每月跑一次)——把脚本放在 D:\wsl\compact-almalinux9.ps1:
# =============================================
# D:\wsl\compact-almalinux9.ps1
# 用途:回收 AlmaLinux-9 WSL2 虚拟磁盘空间
# 用法:右键 → 使用 PowerShell 管理员运行
# =============================================
# 1. 关闭所有 WSL 实例
wsl --shutdown
Start-Sleep -Seconds 3
# 2. 配置 vhdx 路径(手动 import 时的路径)
$vhdxPath = "D:\wsl\AlmaLinux-9-DockerCompose\ext4.vhdx"
# 如果用 Microsoft Store 版,把上面换成:
# $vhdxPath = "$env:LOCALAPPDATA\Packages\*AlmaLinux*AlmaLinux-9*\LocalState\ext4.vhdx" | Get-ChildItem | Select-Object -First 1 -ExpandProperty FullName
# 3. 校验
if (-not (Test-Path $vhdxPath)) {
Write-Error "❌ 找不到 vhdx:$vhdxPath"
Write-Host "请用 Get-ChildItem 搜索 vhdx 位置后修改脚本"
exit 1
}
$beforeGB = [math]::Round((Get-Item $vhdxPath).Length / 1GB, 2)
Write-Host "📦 压缩前:$beforeGB GB" -ForegroundColor Cyan
# 4. 写临时 diskpart 脚本
$tmp = Join-Path $env:TEMP "compact-wsl-$PID.txt"
"select vdisk file=`"$vhdxPath`"" | Out-File -Encoding ascii $tmp
"compact vdisk" | Out-File -Append -Encoding ascii $tmp
# 5. 执行(会跑几十秒到几分钟)
diskpart /s $tmp
Remove-Item $tmp
# 6. 报告
$afterGB = [math]::Round((Get-Item $vhdxPath).Length / 1GB, 2)
$saved = [math]::Round($beforeGB - $afterGB, 2)
Write-Host "📦 压缩后:$afterGB GB(回收 $saved GB)" -ForegroundColor Green
定时自动回收(每月 1 号凌晨 2 点):
# 在管理员 PowerShell 里执行一次
$action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NoProfile -ExecutionPolicy Bypass -File D:\wsl\compact-almalinux9.ps1"
$trigger = New-ScheduledTaskTrigger -Monthly -DaysOfMonth 1 -At "02:00"
Register-ScheduledTask -TaskName "WSL Compact AlmaLinux9 vhdx" -Action $action -Trigger $trigger -RunLevel Highest -Description "每月压缩 AlmaLinux-9 WSL 虚拟磁盘"
7.4.6 常见误区
| 误区 | 正确做法 |
|---|---|
"在 / 建文件夹要分配空间" |
mkdir 只创建目录项,不预分配磁盘空间;写入文件时才实际占用 |
"none 7.8G 满了怎么办" |
none 是 WSL 内部 9P 通道(内存映射),不是磁盘存储;占用高时重启 WSL(wsl --shutdown)即可释放 |
| "WSL 里删了大文件,Windows 磁盘空间没释放" | WSL2 的 ext4.vhdx 是稀疏文件,删除文件后不会自动缩小;需要用 diskpart compact vdisk 手动压缩回收 |
| "根目录可以无限写" | 受 ext4.vhdx 配置上限限制(默认 256 GB,可手动扩展) |
| "重装 WSL 还能找到根目录数据" | 不能!WSL 重装会重置根目录;重要数据务必放 /mnt/c、/mnt/d 或外部盘 |
7.4.7 WSL 常用运维命令
# 查看 WSL 版本和状态(Windows PowerShell)
wsl -l -v
# 关闭所有 WSL 实例
wsl --shutdown
# 导出当前发行版做备份(PowerShell)
wsl --export AlmaLinux-9-DockerCompose D:\wsl-backup\almalinux9-$(Get-Date -Format yyyyMMdd).tar
# 从备份恢复(PowerShell)
wsl --import AlmaLinux-9-DockerCompose D:\wsl\AlmaLinux-9-DockerCompose D:\wsl-backup\almalinux9-xxx.tar
# 设置默认登录用户(在 /etc/wsl.conf 加):
# [user]
# default = youruser
💡 AlmaLinux-9 WSL 默认用户提示:
wsl --install -d AlmaLinux-9装出来默认是 root- 第一次进入会强制让你建一个普通用户(输完用户名密码后默认登录该用户)
- 但
wsl.conf里[user] default = xxx不会自动写——要手动配
7.4.8 WSL 网络配置与 Windows 互通
💡 谁需要看本节:WSL2 用户(Microsoft Store 安装 /
wsl --import/ LxRunOffline 任一方式)。
❌ 谁可以跳过:物理机、云服务器、VMware/VirtualBox 虚拟机用户(按 5.1 节 nmcli 配置即可)。
WSL 启用 systemd、配置主机名、镜像网络、hostAddressLoopback 等通用 WSL 知识,详见 WSL 虚拟机创建与管理指南.md 第 4~6 节。AlmaLinux-9 在 WSL 内的行为与 Ubuntu 24.04 几乎完全一致(包管理器、systemd 工具链不同;WSL 内部机制相同)。
AlmaLinux-9 在 WSL 内的常见调整:
# 1. 启用 systemd(参考 7.1)
sudo tee /etc/wsl.conf > /dev/null << 'EOF'
[user]
default = youruser
[boot]
systemd=true
[network]
generateHosts = false
hostname = alma9-workspace
EOF
# 2. 切到 nftables 后端(WSL 内 firewalld 跑不起来,要 disable)
sudo systemctl disable --now firewalld
# 3. 启用时间同步(如果用了 chronyd,可能要配)
sudo systemctl enable --now chronyd
⚠️ AlmaLinux-9 + WSL 的 SELinux:
- AlmaLinux-9 安装时默认开启 SELinux,配置文件
/etc/selinux/config里SELINUX=enforcing- WSL2 的微软内核不支持完整 SELinux 强制执行(缺 LSM 模块)——在 WSL 里 SELinux 不会真正生效
- 行为上没问题,但日志会有些噪音(一些 service 报 SELinux 警告),可以接受
- 想关掉:编辑
/etc/selinux/config,把SELINUX=enforcing改成SELINUX=permissive(或 disabled),但对 WSL 来说意义不大
7.5 WSL 内 SELinux 处理
📋 详细说明见 6.3 SELinux 处理(命令通用)。本节只讲 WSL 下的特殊处理。
AlmaLinux-9 安装时默认开启 SELinux,配置文件 /etc/selinux/config 里 SELINUX=enforcing。WSL2 的微软内核不支持完整 SELinux 强制执行(缺 LSM 模块)——在 WSL 里 SELinux 不会真正生效,但服务会刷一些 SELinux 警告日志。
WSL 下推荐处理:
# 临时切到 permissive(重启后失效)
sudo setenforce 0
# 永久切到 permissive(编辑配置文件)
sudo sed -i 's/^SELINUX=enforcing/SELINUX=permissive/' /etc/selinux/config
# 验证
getenforce
# 期望输出:Permissive
💡 WSL 下切到 permissive 是安全的:
- WSL 不是生产环境,缺 LSM 模块本来就不能强制 SELinux
- permissive 模式下 SELinux 仍然记录违反策略的事件(audit log),但不阻止
- 完全关掉(
disabled)反而可能让某些依赖 SELinux 的服务启动失败
7.6 WSL 内 firewalld / fail2ban 关掉
📋 详细说明见 6.1 firewalld 防火墙 和 6.2 fail2ban 防爆破(命令通用)。本节只讲 WSL 下的特殊处理。
WSL2 的微软内核没编译老 iptables 模块——firewalld 会报 iptables 错误;fail2ban 依赖 iptables 做封禁动作,也跑不动。WSL 内直接关掉这两个:
# 关 firewalld
sudo systemctl disable --now firewalld
# 关 fail2ban
sudo systemctl disable --now fail2ban
💡 WSL 下不需要 Linux 防火墙:
- Windows 防火墙是 WSL 流量的真正边界
- WSL 服务要被 Windows 访问,开
hostAddressLoopback(参考 WSL 文档第 6 节)- 容器间网络(Docker bridge)由 Docker 自己管 iptables,跟 NM/firewalld 无关
7.7 WSL 重启正确方式 + 配置生效规则
💡 基本运维命令(
wsl -l -v、wsl --shutdown、wsl --export/--import)见 7.4.7 WSL 常用运维命令。本节只讲"重启"和"哪些配置改了必须重启"。
WSL 重启的正确方式(在 Windows PowerShell):
# 正确:完全关闭 + 重新打开(重读 wsl.conf / .wslconfig / system.conf)
wsl --shutdown
wsl -d AlmaLinux-9-DockerCompose
| 行为 | sudo reboot(WSL 内部) |
wsl --shutdown(PowerShell) |
|---|---|---|
| 杀进程 | ✅ | ✅ |
| 重启 WSL 服务 | ❌ 不会 | ✅ 会 |
重新读 wsl.conf |
❌ | ✅ |
重新读 system.conf |
❌ | ✅ |
重新读 .wslconfig |
❌ | ✅ |
| 重新分配内存/CPU 限制 | ❌ | ✅ |
❌ 不要用
sudo reboot:
- WSL 不是真硬件,
reboot找不到 BIOS/固件去调用- 微软的 WSL 进程管理由 Windows 侧的
LxssManager服务控制- 必须在 Windows 侧让
LxssManager重新加载所有发行版,wsl --shutdown就是干这个的- 改了
wsl.conf/system.conf后,没有wsl --shutdown就不会重新读
哪些配置改了必须重启 WSL:
| 配置文件 / 操作 | 是否需要 wsl --shutdown |
|---|---|
/etc/wsl.conf(所有段) |
✅ 必须 |
~/.wslconfig(Windows 侧) |
✅ 必须 |
/etc/systemd/system.conf |
✅ 必须(systemd 启动时读) |
/etc/security/limits.conf |
⚠️ 仅 PAM 登录的进程生效(重开终端就够) |
| 普通 systemd 服务配置 | ❌ 用 systemctl restart xxx 即可 |
| 软件包安装 / 升级 | ❌ 直接生效 |
🔗 通用 WSL 基础(systemd 启用细节、镜像网络、
hostAddressLoopback实验特性等)详见WSL 虚拟机创建与管理指南.md第 4~6 节。
八、验证检查清单
完成所有配置后,建议逐项验证。
8.1 通用检查(真机 / 云服务器 / WSL 通用)
| ✅ 检查项 | 🔧 命令 | 🎯 预期 |
|---|---|---|
| 系统版本 | cat /etc/almalinux-release |
AlmaLinux release 9.x ... |
| SSH 远程可连 | ssh youruser@IP |
成功登录(最好密钥免密) |
| 密码登录已关闭 | ssh -o PasswordAuthentication=no youruser@IP |
仍可登录 = OK |
| SSH 服务自启 | sudo systemctl is-enabled sshd |
enabled |
| 防火墙已启用 | sudo firewall-cmd --state |
running |
| 防火墙放行 SSH | sudo firewall-cmd --list-services |
含 ssh |
| 网络连通 | ping -c 3 baidu.com 或 curl -v http://baidu.com |
有响应(注意:WSL 默认禁 ICMP,ping 可能不通) |
| DNS 解析 | dig baidu.com |
返回 IP |
| 时区正确 | timedatectl |
Asia/Shanghai |
| 时间同步 | timedatectl show |
NTPSynchronized=yes |
| 系统已更新 | dnf check-update |
无输出 = 已最新 |
| FD 限制 | ulimit -n |
65535(已配置时) |
| 工具齐全 | which htop tmux jq tree vim |
全部有路径 |
| fail2ban 运行 | sudo systemctl status fail2ban |
active (running) |
| SELinux 状态 | getenforce |
Enforcing / Permissive(看需求) |
8.2 真机 / 云服务器额外检查(WSL 跳过)
| ✅ 检查项 | 🔧 命令 | 🎯 预期 |
|---|---|---|
| 静态 IP 生效 | ip addr show <网卡名> |
IP 与配置一致(网卡名因硬件/虚拟化平台而异:常见如 ens33、ens160、enp0s3、eth0 等,需按实际填写) |
| 默认路由 | ip route show default |
显示网关 IP |
| 远程可 ping 通 | ping <服务器IP>(从另一台机器) |
有响应(服务器防火墙可能挡 ICMP) |
📋 怎么知道自己的网卡名:
# 列所有网卡(找带 inet IP 的那个) ip -br addr # 输出示例: # lo UNKNOWN 127.0.0.1/8 # ens33 UP 192.168.1.100/24 ← 这就是 # docker0 DOWN 172.17.0.1/16
8.3 WSL2 用户额外检查
💡 配套阅读:七、WSL 用户专属指南——所有 WSL 专属配置(systemd 启用、主机名、firewalld 关掉、SELinux 切 permissive 等)都集中在那里。本表只是验证"配置生效了没"。
| ✅ 检查项 | 🔧 命令 | 🎯 预期 |
|---|---|---|
| WSL 发行版 | wsl -l -v(PowerShell 跑) |
看到自己的发行版,版本是 2 |
| systemd 已启用 | ps -p 1 -o comm= |
systemd(不是 init) |
| WSL 主机名 | hostname |
你设的名字(如 alma9-workspace) |
| 主机名持久化 | cat /etc/wsl.conf |
含 [network] hostname = xxx |
| hosts 同步 | cat /etc/hosts | grep $(hostname) |
含 127.0.1.1 <主机名> |
| sudo 无警告 | sudo whoami |
直接返回 root,无 "unable to resolve host" |
| 根目录所在虚拟磁盘 | df -h / |
容量正常(默认 256G,可手动扩) |
| 根目录使用率 | df -h / | tail -1 | awk '{print $5}' |
< 80% |
| Windows 盘已挂载 | ls /mnt/c /mnt/d |
能列出文件 |
| 数据软链就绪 | ls -ld ~/data |
指向 /mnt/d/wsl-data(如已建) |
| 默认 /data 在 | ls -ld /data |
存在 |
| WSL 发行版 | cat /etc/os-release |
AlmaLinux 9 |
| WSL 重启生效 | wsl --shutdown 后 wsl(PowerShell 跑) |
配置变更生效 |
| WSL 镜像模式(按需) | ip addr show eth0 |
inet 是 192.168.x 或 10.x(不是 172.x) |
8.4 一键自检脚本(通用 + WSL)
保存为 ~/check-env.sh,chmod +x ~/check-env.sh 后跑:
#!/bin/bash
# =============================================
# AlmaLinux-9 初始环境一键自检脚本
# =============================================
echo "================================"
echo "AlmaLinux-9 初始环境自检"
echo "================================"
echo -e "\n[1] 系统信息"
echo "版本:$(grep PRETTY_NAME /etc/os-release | cut -d= -f2- | tr -d '"')"
echo "内核:$(uname -r)"
echo "当前用户:$(whoami)"
echo -e "\n[2] SSH 服务"
systemctl is-enabled sshd &>/dev/null && echo "✅ sshd 自启" || echo "❌ sshd 未自启"
systemctl is-active sshd &>/dev/null && echo "✅ sshd 运行中" || echo "❌ sshd 未运行"
echo -e "\n[3] 防火墙"
if command -v firewall-cmd &> /dev/null; then
if systemctl is-active firewalld &>/dev/null; then
firewall-cmd --list-services | head -3
else
echo "⚠️ firewalld 已装但未运行(WSL 下可能需关掉)"
fi
else
echo "⚠️ firewalld 未装"
fi
echo -e "\n[4] SELinux"
echo "当前模式:$(getenforce 2>/dev/null || echo 'N/A')"
echo -e "\n[5] 时区与时间"
timedatectl | grep -E "Time zone|System clock"
echo -e "\n[6] 网络"
ip -br addr | grep -v "DOWN" | head -5
echo -e "\n[7] DNS"
cat /etc/resolv.conf 2>/dev/null | grep nameserver | head -2
echo -e "\n[8] 资源限制"
echo "ulimit -n: $(ulimit -n)"
echo "ulimit -u: $(ulimit -u)"
echo -e "\n[9] 工具检查"
for tool in htop tmux jq tree vim git curl wget dnf; do
if command -v $tool &> /dev/null; then
echo "✅ $tool"
else
echo "❌ $tool 缺失"
fi
done
echo -e "\n[10] systemd 状态(WSL 关注)"
ps -p 1 -o comm= | grep -q systemd && echo "✅ systemd 已启用" || echo "❌ PID 1 不是 systemd(WSL 需配置 wsl.conf)"
echo -e "\n[11] 主机名"
echo "当前:$(hostname)"
grep -q "^127.0.1.1 $(hostname)" /etc/hosts && echo "✅ /etc/hosts 同步" || echo "⚠️ /etc/hosts 未同步(sudo 可能报 unable to resolve host)"
echo -e "\n[12] WSL 特定(如适用)"
if grep -qi "microsoft" /proc/version 2>/dev/null; then
echo "✅ WSL 环境"
grep -q "^\[network\]" /etc/wsl.conf && echo "✅ wsl.conf 有 [network] 段" || echo "⚠️ wsl.conf 缺 [network] 段(主机名可能不持久)"
else
echo "非 WSL 环境(真机/云服务器)"
fi
echo -e "\n================================"
echo "自检完成"
echo "================================"
九、常用命令速查
9.1 服务管理
| 🔧 操作 | 🔧 AlmaLinux-9 / RHEL | 🔧 Ubuntu 24.04 |
|---|---|---|
| 启动 | sudo systemctl start sshd |
sudo systemctl start ssh |
| 停止 | sudo systemctl stop sshd |
sudo systemctl stop ssh |
| 状态 | sudo systemctl status sshd |
sudo systemctl status ssh |
| 开机自启 | sudo systemctl enable sshd |
sudo systemctl enable ssh |
| 重载配置 | sudo systemctl reload sshd |
sudo systemctl reload ssh |
| 服务名 | sshd |
ssh |
| 配置文件 | /etc/ssh/sshd_config |
/etc/ssh/sshd_config(路径相同) |
📋 关键差异:Ubuntu 把 SSH 服务名从 RHEL 的
sshd改成了ssh,其他都一致。
9.2 包管理对照
| 🔧 操作 | 🔧 AlmaLinux-9 (dnf) | 🔧 Ubuntu 24.04 (apt) |
|---|---|---|
| 更新源索引 | sudo dnf makecache |
sudo apt update |
| 安装包 | sudo dnf install -y pkg |
sudo apt install -y pkg |
| 删除包 | sudo dnf remove pkg |
sudo apt remove pkg |
| 搜索包 | dnf search keyword |
apt search keyword |
| 包信息 | dnf info pkg |
apt show pkg |
| 列出已装 | dnf list installed |
apt list --installed |
| 升级所有 | sudo dnf upgrade -y |
sudo apt upgrade -y |
| 升级发行版 | sudo dnf upgrade --releasever=10 |
sudo do-release-upgrade |
| 清理缓存 | sudo dnf clean all |
sudo apt clean |
| 自动清理无用包 | sudo dnf autoremove |
sudo apt autoremove |
| 包组 | dnf groupinstall "Development Tools" |
apt install build-essential |
9.3 网络命令对照
| 🔧 用途 | 🔧 AlmaLinux-9 | 🔧 Ubuntu 24.04 |
|---|---|---|
| 查看 IP | ip addr / ifconfig |
ip addr(ifconfig 需装 net-tools) |
| 查看端口 | netstat -tlnp |
netstat -tlnp(需装 net-tools) / ss -tlnp |
| 测试连通 | ping / traceroute |
ping / traceroute(需装) |
| DNS 查询 | nslookup / dig |
dig(需装 dnsutils) |
| 防火墙 | firewalld / firewall-cmd |
ufw |
| 网络配置 | nmcli / nmtui(NetworkManager) |
netplan(/etc/netplan/*.yaml) |
| 主机名 | hostnamectl set-hostname x |
hostnamectl set-hostname x(相同) |
| 安全模块 | setenforce 0 / getenforce |
无(Ubuntu 用 AppArmor) |
9.4 时间与日志对照
| 🔧 用途 | 🔧 AlmaLinux-9 | 🔧 Ubuntu 24.04 |
|---|---|---|
| 时区设置 | timedatectl set-timezone ... |
相同 |
| 时间同步 | chrony(默认) |
systemd-timesyncd(默认) / chrony |
| 系统日志 | /var/log/messages |
/var/log/syslog |
| 认证日志 | /var/log/secure |
/var/log/auth.log |
| 查看日志 | journalctl -u sshd |
journalctl -u ssh |
| SELinux 审计 | /var/log/audit/audit.log |
无 |
9.5 防火墙命令对照
| 🔧 操作 | 🟢 firewalld(AlmaLinux 默认) | 🟡 iptables(底层通用) | 🔵 nftables(现代替代) | 🔴 ufw(Ubuntu 默认) |
|---|---|---|---|---|
| 查看状态 | sudo firewall-cmd --state |
sudo iptables -L -n -v |
sudo nft list ruleset |
sudo ufw status verbose |
| 查看规则 | sudo firewall-cmd --list-all |
sudo iptables -L -n -v --line-numbers |
sudo nft list ruleset |
sudo ufw status numbered |
| 启动/启用 | sudo systemctl enable --now firewalld |
开机自启需 iptables-persistent |
开机自启需 nftables.service |
sudo ufw enable |
| 放行 22 端口 | sudo firewall-cmd --permanent --add-service=ssh |
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT |
sudo nft add rule inet filter input tcp dport 22 accept |
sudo ufw allow 22/tcp |
| 放行服务名 | sudo firewall-cmd --permanent --add-service=http |
— | — | sudo ufw allow http |
| 放行 IP 段 | sudo firewall-cmd --permanent --add-rich-rule='rule family=ipv4 source address=192.168.1.0/24 accept' |
sudo iptables -A INPUT -s 192.168.1.0/24 -j ACCEPT |
sudo nft add rule inet filter input ip saddr 192.168.1.0/24 accept |
sudo ufw allow from 192.168.1.0/24 |
| 拒绝某 IP | sudo firewall-cmd --permanent --add-rich-rule='rule family=ipv4 source address=10.0.0.5 reject' |
sudo iptables -A INPUT -s 10.0.0.5 -j DROP |
sudo nft add rule inet filter input ip saddr 10.0.0.5 drop |
sudo ufw deny from 10.0.0.5 |
| 重新加载 | sudo firewall-cmd --reload |
sudo iptables-restore < /etc/iptables/rules.v4 |
sudo nft -f /etc/nftables.conf |
自动 |
| 关闭防火墙 | sudo systemctl stop firewalld |
sudo iptables -F(清空规则,慎用) |
sudo nft flush ruleset |
sudo ufw disable |
| 命令缺失 | sudo dnf install -y firewalld |
AlmaLinux 自带 | sudo dnf install -y nftables |
sudo apt install -y ufw |
📋 选择建议:
- 标准 AlmaLinux 优先用 firewalld(本教程主推),zone 概念比 ufw 略复杂但集成度高。
- 需要复杂规则(端口转发、NAT、限速)用 iptables / nftables。
- 跨平台脚本或 Ubuntu 兼容场景用 ufw(AlmaLinux EPEL 里有)。
9.6 一键脚本(新建服务器跑一次)
📋 脚本定位:
- 本脚本对应本文档 第二章(初始环境检查)、3.1-3.3(SSH 服务)、第四章(常用工具)、5.5(dnf 换源)、6.1-6.4(安全与优化)的最小可用集。
- 不包含的内容:5.1(静态 IP,按网络环境差异较大)、5.2(主机名,个性化)、3.5(密钥免密,建议手动执行以免覆盖既有密钥)、6.3(SELinux 高级配置,生产环境按需)、第七章 WSL 用户专属指南(WSL 用户单独走那一章)。
- 默认按"真机 / 云服务器"编写,脚本会自动识别 WSL2 环境并跳过不适用项(
firewalld、reboot、sysctl等)。
#!/bin/bash
# =============================================
# AlmaLinux-9 初始环境一键配置脚本
# 对应文档:AlmaLinux-9与WSL2初始环境配置与常用工具安装教程.md 第 9.6 节
# 用法:sudo bash init-almalinux9.sh
# 前置:建议先按 5.5 节换 dnf 源,再跑本脚本
# 幂等:重复运行不会破坏既有配置(已存在配置会跳过)
# =============================================
set -euo pipefail
# ---------- 颜色输出 ----------
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m'
log() { echo -e "${GREEN}[✓]${NC} $*"; }
warn() { echo -e "${YELLOW}[!]${NC} $*"; }
err() { echo -e "${RED}[✗]${NC} $*"; }
# ---------- 0. 权限与环境探测 ----------
if [[ $EUID -ne 0 ]]; then
err "请使用 root 或 sudo 运行本脚本"
exit 1
fi
# WSL2 探测:/proc/version 含 "microsoft" 或 "WSL"
IS_WSL=0
grep -qiE 'microsoft|wsl' /proc/version 2>/dev/null && IS_WSL=1
# 当前登录用户(sudo 场景下 SUDO_USER 非空;root 直登时退到默认 youruser)
REAL_USER="${SUDO_USER:-${USER:-youruser}}"
[[ "$REAL_USER" == "root" ]] && REAL_USER="youruser"
log "运行环境:$( [[ $IS_WSL -eq 1 ]] && echo 'WSL2' || echo '真机/云服务器' )"
log "操作用户:$REAL_USER"
# ---------- 1. 更新源(对应 5.5) ----------
log "[1/9] 更新 dnf 源与软件包"
if [[ $IS_WSL -eq 1 ]]; then
warn "WSL2 环境:换源脚本见 5.5.8 节,建议先手动跑(rootfs 通常默认源已够用)"
else
dnf makecache
fi
# upgrade 升级所有包;如不希望升级可注释掉下一行
dnf upgrade -y
# ---------- 2. 常用工具(对应第四章) ----------
log "[2/9] 安装常用工具集"
dnf install -y \
openssh-server openssh-clients \
vim nano curl wget git \
net-tools bind-utils iputils traceroute mtr \
unzip p7zip p7zip-plugins lrzsz \
bash-completion tmux \
htop iotop iftop sysstat lsof strace ncdu \
ripgrep fd-find jq tree \
fail2ban firewalld
# 装 EPEL(如已装会跳过)
if ! rpm -q epel-release &>/dev/null; then
dnf install -y epel-release
log "EPEL 已装"
fi
# fd-find 在 AlmaLinux 上是 /usr/bin/fd-find,alias 一下
if ! grep -q "alias fd=" /home/$REAL_USER/.bashrc 2>/dev/null; then
echo "alias fd='fd-find'" >> /home/$REAL_USER/.bashrc
fi
# ---------- 3. SSH 服务(对应 3.1 / 3.3) ----------
log "[3/9] 配置 SSH 服务"
# 备份原配置(仅首次备份)
[[ -f /etc/ssh/sshd_config ]] && [[ ! -f /etc/ssh/sshd_config.bak ]] && \
cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
# 用 sed 调整关键项(保留其它已有配置)
SSHD_CFG=/etc/ssh/sshd_config
sed -i 's/^#\?PermitRootLogin.*/PermitRootLogin no/' "$SSHD_CFG"
sed -i 's/^#\?PasswordAuthentication.*/PasswordAuthentication yes/' "$SSHD_CFG"
sed -i 's/^#\?PubkeyAuthentication.*/PubkeyAuthentication yes/' "$SSHD_CFG"
sed -i 's/^#\?X11Forwarding.*/X11Forwarding no/' "$SSHD_CFG"
sed -i 's/^#\?MaxAuthTries.*/MaxAuthTries 3/' "$SSHD_CFG"
# 启用并启动 SSH(WSL2 启用 systemd 后 systemctl 才会生效;未启用时为 no-op)
if [[ $IS_WSL -eq 0 ]]; then
systemctl enable --now sshd >/dev/null 2>&1 || warn "sshd 服务启动失败,请检查 systemd"
else
warn "WSL2 环境:未启用 systemd 时 systemctl 不可用,请按 WSL 文档启用后再重启"
fi
# 校验配置(错误则不重启,避免失联)
if command -v sshd >/dev/null 2>&1; then
sshd -t && log "sshd_config 语法校验通过" || err "sshd_config 语法错误,请检查 $SSHD_CFG"
fi
# ---------- 4. 防火墙(对应 6.1 / 七章 7.6) ----------
log "[4/9] 配置 firewalld 防火墙"
if [[ $IS_WSL -eq 0 ]]; then
systemctl enable --now firewalld >/dev/null 2>&1 || warn "firewalld 启动失败"
firewall-cmd --permanent --add-service=ssh >/dev/null 2>&1 || true
firewall-cmd --reload >/dev/null 2>&1 || true
log "firewalld 已启用(默认放行 ssh)"
else
warn "WSL2 环境:firewalld 微软内核不支持,建议 disable,由 Windows 防火墙控端口"
systemctl disable --now firewalld >/dev/null 2>&1 || true
fi
# ---------- 5. fail2ban(对应 6.2 / 七章 7.6) ----------
log "[5/9] 配置 fail2ban"
JAIL_LOCAL=/etc/fail2ban/jail.local
if [[ ! -f $JAIL_LOCAL ]]; then
cat > "$JAIL_LOCAL" <<'EOF'
[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 5
banaction = firewallcmd-rich-rules
banaction_allports = firewallcmd-rich-rules
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = %(sshd_log)s
backend = %(sshd_backend)s
maxretry = 3
EOF
log "已生成 $JAIL_LOCAL"
else
warn "$JAIL_LOCAL 已存在,跳过覆盖(手动调整请编辑该文件)"
fi
if [[ $IS_WSL -eq 0 ]]; then
systemctl enable --now fail2ban >/dev/null 2>&1 || warn "fail2ban 启动失败"
else
warn "WSL2 环境:未启用 systemd 时 fail2ban 无法后台常驻"
fi
# ---------- 6. 时区与时间同步(对应 5.3) ----------
log "[6/9] 配置时区与时间同步"
timedatectl set-timezone Asia/Shanghai
if [[ $IS_WSL -eq 0 ]]; then
systemctl enable --now chronyd >/dev/null 2>&1 || true
fi
log "当前时区:$(timedatectl | grep 'Time zone' | awk '{print $3}')"
# ---------- 7. 文件描述符限制(对应 6.4) ----------
log "[7/9] 配置文件描述符限制"
LIMITS_CONF=/etc/security/limits.conf
# 幂等:仅当 nofile 65535 不存在时追加
if ! grep -qE '^\*\s+soft\s+nofile\s+65535' "$LIMITS_CONF" 2>/dev/null; then
cat >> "$LIMITS_CONF" <<'EOF'
# === Added by init-almalinux9.sh ===
* soft nofile 65535
* hard nofile 65535
root soft nofile 65535
root hard nofile 65535
EOF
log "已追加 nofile 限制到 $LIMITS_CONF"
else
warn "$LIMITS_CONF 已包含 nofile 65535,跳过"
fi
# systemd 服务级 FD 限制
SYSTEMD_CONF=/etc/systemd/system.conf
if ! grep -qE '^DefaultLimitNOFILE=65535' "$SYSTEMD_CONF" 2>/dev/null; then
sed -i 's/^#\?DefaultLimitNOFILE=.*/DefaultLimitNOFILE=65535/' "$SYSTEMD_CONF" || \
echo "DefaultLimitNOFILE=65535" >> "$SYSTEMD_CONF"
log "已设置 DefaultLimitNOFILE=65535"
else
warn "$SYSTEMD_CONF 已包含 DefaultLimitNOFILE=65535,跳过"
fi
# ---------- 8. 内核参数调优(对应 6.5) ----------
log "[8/9] 配置内核参数调优"
SYSCTL_FILE=/etc/sysctl.d/99-tuning.conf
if [[ ! -f $SYSCTL_FILE ]]; then
cat > "$SYSCTL_FILE" <<'EOF'
# === Added by init-almalinux9.sh ===
# 网络优化
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_fin_timeout = 15
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
net.ipv4.tcp_max_syn_backlog = 8192
net.core.somaxconn = 8192
net.ipv4.tcp_syncookies = 1
# 安全加固
net.ipv4.ip_forward = 0
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.default.secure_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.all.log_martians = 1
# Swap 使用倾向(值越小越倾向用物理内存)
vm.swappiness = 10
EOF
log "已生成 $SYSCTL_FILE"
else
warn "$SYSCTL_FILE 已存在,跳过覆盖(如需重置请手动删除)"
fi
# 应用 sysctl(非 WSL 立即生效;WSL 大部分参数会被宿主内核忽略)
if [[ $IS_WSL -eq 0 ]]; then
sysctl -p "$SYSCTL_FILE" >/dev/null 2>&1 || warn "sysctl 部分参数应用失败(多因模块未加载,可忽略)"
else
warn "WSL2 环境:sysctl 大部分参数由 Windows 宿主内核控制,配置仅作记录"
fi
# ---------- 9. 完成提示 ----------
echo
log "初始化完成"
echo "------------------------------------------------"
echo " 下一步:"
echo " 1) 在本机执行:ssh-copy-id ${REAL_USER}@\$(hostname -I | awk '{print \$1}')"
echo " 2) 验证密钥登录成功后,再把 PasswordAuthentication 设为 no 永久生效"
echo " 3) 真机/云服务器需 reboot;WSL2 在 Windows PowerShell 执行 wsl --shutdown"
echo " 4) SELinux 状态:$(getenforce 2>/dev/null || echo 'N/A')(生产建议保持 enforcing)"
if [[ $IS_WSL -eq 1 ]]; then
echo " 5) WSL 用户专属配置:见第七章 WSL 用户专属指南(systemd 启用、主机名、vhdx 回收等)"
fi
echo "------------------------------------------------"
💡 文档维护提示:
- 上述所有配置均在 AlmaLinux 9.x 实测通过。
- AlmaLinux 8 大部分兼容,仅仓库 id 命名(
base/AppStreamvsbaseos/appstream)、防火墙命令(firewall-cmd基本一致)、部分 SELinux 策略有差异。- SELinux 行为取决于具体启用模式,调试时优先用
ausearch+audit2allow生成策略,而非全局 permissive。- WSL 行为(systemd 启用、虚拟磁盘回收、
/etc/wsl.conf配置等)详见WSL 虚拟机创建与管理指南.md。

浙公网安备 33010602011771号