一 安装docker

1.1 欧拉2403 安装docker

1.1.1 环境准备

# 欧拉中用 dnf-utils 替代 yum-utils(功能完全一致)
sudo dnf install -y dnf-utils device-mapper-persistent-data lvm2 libseccomp-devel

1.1.2 安装Docker Engine

1.1.2.1 配置 Docker 国内源(阿里云)
# 1. 移除可能存在的旧 Docker 源
sudo rm -f /etc/yum.repos.d/docker-ce.repo

# 2. 添加阿里云 Docker 源(适配 CentOS 9/欧拉 24.03)
sudo tee /etc/yum.repos.d/docker-ce.repo <<-'EOF'
[docker-ce-stable]
name=Docker CE Stable - $basearch
baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/9/$basearch/stable
enabled=1
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/docker-ce/linux/centos/gpg
EOF

# 3. 重建缓存
sudo dnf makecache

1.1.2.2 卸载冲突组件 + 安装 Docker

# 1. 安装 Docker 核心组件
sudo dnf install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

# 2. 启动 Docker 并设置开机自启
sudo systemctl start docker
sudo systemctl enable docker

# 2. 验证 Docker 安装
docker --version
# 预期输出:Docker version 26.x.x, build XXXXX

在这里插入图片描述

二 安装docker-compose

docker-compose 是个二进制文件,各版本安装步骤相同,具体安装时要注意docker-compose 于docker 的版本兼容性

2.1 独立版(兼容旧脚本,带横杠)

二进制文件 下载地址 各位自己定,我这里用的是华为的镜像地址

# 1. 从 华为国内镜像下载二进制包
sudo curl -L https://repo.huaweicloud.com/docker-compose/v2.27.0/docker-compose-Linux-x86_64 -o /usr/local/bin/docker-compose

# 2. 添加可执行权限
sudo chmod +x /usr/local/bin/docker-compose

# 3. 创建软链接(全局可用)
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose

# 4. 验证
docker-compose --version
# 预期输出:docker-compose version v2.27.0, build XXXXX

三 挂载数据盘

3.1 通用挂载方式(2T 以上及以下均可挂载)

3.1.1 为什么以2T 为界限给出两种挂载方式

源于两种不同的硬盘分区表格式:MBR 和 GPT

对比项 MBR (主引导记录) GPT (全局唯一标识符分区表)
最大支持容量 2TB 18EB (约 1800万TB,远超当前硬件水平)
分区工具 fdisk parted
文件系统 通常配合 ext4 通常配合 XFS (大文件性能更好)
适用场景 老旧系统,小于 2T 的系统盘 现代标准,所有数据盘,大于 2T 的硬盘

核心区别解释:

  • 容量限制:MBR 是一种非常古老的分区标准,它在设计上限制了硬盘的最大容量为 2TB。如果你有一块 3TB 的硬盘,使用 MBR 分区,系统只能识别出前 2TB,剩下的 1TB 会“凭空消失”。
  • 工具不同:因为 MBR 和 GPT 的结构不同,所以管理它们的工具也不同。fdisk 是专门管理 MBR 的,它无法处理 GPT;而 parted 是一个功能强大的现代工具,它支持 GPT(同时也支持 MBR,但通常用于 GPT)。
  • 可靠性:GPT 在硬盘的开头和结尾都存储了分区表的备份,比 MBR 更加安全可靠,不易因意外断电等原因导致分区表损坏。

总结

  • 2T 分界线的由来:是因为 MBR 分区表的容量限制。
    * 为什么推荐 GPT (parted):因为它没有 2T 的容量限制,是现代 Linux 系统的标准,更加安全可靠。它是一种真正通用的方式,无论硬盘大小,都可以使用。

3.1.2 通用挂载方案(兼容所有容量磁盘,以 /dev/sda 为例)

3.1.2.1. 安装工具并分区
# 安装 parted 工具
sudo dnf install -y parted

# 进入 parted 交互模式
sudo parted /dev/sdb

在 parted 交互界面中,依次输入以下命令:

mklabel gpt          # 创建 GPT 分区表 (这一步会清除硬盘上所有数据)
mkpart primary 0% 100%  # 创建一个占据整个硬盘的主分区
print              # 查看分区是否成功,应该会显示 /dev/s
quit               # 退出

执行后会生成 /dev/sda1 分区(GPT 格式,无论 2T 以下 / 以上都适用)。
在这里插入图片描述

3.1.2.2 格式化分区(ext4 通用格式)
# 格式化 /dev/sdb1 为 ext4(通用文件系统,兼容所有Linux)
mkfs.ext4 /dev/sdb1

可选:如果需要更好的性能 / 兼容性,也可以用 xfs(mkfs.xfs /dev/sdb1),挂载方式完全一致。

3.1.2.3:创建挂载目录并临时挂载
# 1. 创建 /data 目录
mkdir -p /data

# 2. 临时挂载(立即生效,重启丢失)
mount /dev/sdb1 /data

# 3. 验证挂载结果
df -h /data

在这里插入图片描述

3.1.2.4 设置开机自动挂载(通用方式,永不丢失)

方式:用 UUID 挂载(比设备名更稳定,避免磁盘名变动)

# 2. 备份 fstab(防止改错)
cp /etc/fstab /etc/fstab.bak.orig

# 2. 获取 /dev/sdb1 的 UUID
blkid /dev/sdb1
# 输出示例:/dev/sda1: UUID="d6164931-dd99-4faa-a6ba-c33b8b2e9b5f" TYPE="ext4"

# 3. 写入 fstab(替换下面的 UUID 为你自己的)
echo 'UUID=d6164931-dd99-4faa-a6ba-c33b8b2e9b5f /data ext4 defaults 0 0' >> /etc/fstab

# 2,3 合成一句命令
UUID=$(blkid -s UUID -o value /dev/sdb1) && echo "UUID=$UUID /data ext4 defaults 0 0" >> /etc/fstab

# 4. 验证 fstab(关键!无报错才说明配置正确)
mount -a

  • 说明:defaults 包含 rw(可读写)、suid、dev、exec、auto、nouser、async 等通用参数,满足绝大多数场景;最后的 0 0 是备份 / 检查标记,通用配置。
  • blkid -s UUID -o value /dev/sdb1:只输出 UUID 值(如 d6164931-dd99-4faa-a6ba-c33b8b2e9b5f),无额外格式
  • &&:确保只有在 blkid 成功时才写入 fstab
    自动替换为实际 UUID,避免手动复制错误

在这里插入图片描述

3.1.3 自动化挂载脚本

#!/bin/bash
# ============================================================================
# 脚本名称: auto_mount_disk.sh
# 功能描述: 为指定磁盘创建 GPT 分区表、格式化文件系统、设置开机自动挂载
# 适用系统: openEuler 22.03 / 24.03 (欧拉系统)
# 优化内容: 
#   - 支持 NVMe 等磁盘 (自动识别分区设备名)
#   - 增加依赖包检查 (parted, xfsprogs/e2fsprogs)
#   - 增加 -f 强制模式 (跳过交互确认)
#   - 优化分区生成等待机制 (循环探测)
#   - 增强 fstab 重复检测 (精确匹配挂载点或 UUID)
#   - 增加挂载点非空检查并提示
#   - 添加系统日志记录
#   - 【修改】系统盘检查改为二次确认(非强制模式需输入YES确认)
# 使用方法: ./auto_mount_disk.sh -d /dev/sdb -m /data [-t xfs|ext4] [-f]
# 版本: 2.1
# ============================================================================

set -e

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
NC='\033[0m'

# 默认值
DISK=""
MOUNT_POINT=""
FS_TYPE="xfs"
FORCE_MODE=false
LOG_FILE="/var/log/auto_mount_disk.log"

# 帮助信息
usage() {
    cat << EOF
用法: $0 -d <磁盘设备> -m <挂载目录> [-t <文件系统类型>] [-f]

必需参数:
  -d    磁盘设备,例如 /dev/sdb
  -m    挂载目录,例如 /data

可选参数:
  -t    文件系统类型,支持 xfs(默认) 或 ext4
  -f    强制模式,跳过交互确认
  -h    显示此帮助

示例:
  $0 -d /dev/sdb -m /data
  $0 -d /dev/nvme0n1 -m /app -t ext4 -f

注意: 需要 root 权限执行。脚本会对指定磁盘进行全新分区并格式化,原有数据将丢失!
EOF
    exit 1
}

# 日志函数
log_info() {
    echo -e "${GREEN}[INFO]${NC} $1" | tee -a "$LOG_FILE"
}

log_warn() {
    echo -e "${YELLOW}[WARN]${NC} $1" | tee -a "$LOG_FILE"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $1" | tee -a "$LOG_FILE"
    exit 1
}

# 检查 root
check_root() {
    if [[ $EUID -ne 0 ]]; then
        log_error "此脚本需要 root 权限执行"
    fi
}

# 解析参数
parse_args() {
    while getopts "d:m:t:fh" opt; do
        case $opt in
            d) DISK="$OPTARG" ;;
            m) MOUNT_POINT="$OPTARG" ;;
            t) FS_TYPE="$OPTARG" ;;
            f) FORCE_MODE=true ;;
            h) usage ;;
            *) usage ;;
        esac
    done

    if [[ -z "$DISK" || -z "$MOUNT_POINT" ]]; then
        log_error "必须指定磁盘设备(-d)和挂载目录(-m)"
    fi

    if [[ ! -b "$DISK" ]]; then
        log_error "磁盘设备 $DISK 不存在"
    fi

    if [[ "$FS_TYPE" != "xfs" && "$FS_TYPE" != "ext4" ]]; then
        log_error "仅支持 xfs 或 ext4"
    fi

    MOUNT_POINT="${MOUNT_POINT%/}"
}

# 检查系统盘(改为二次确认)
check_system_disk() {
    if [[ "$DISK" != "/dev/sda" && "$DISK" != "/dev/vda" ]]; then
        return
    fi

    if [[ "$FORCE_MODE" == true ]]; then
        log_error "禁止在强制模式下对系统盘 $DISK 进行操作!"
    fi

    echo -e "${RED}严重警告:您尝试对系统盘 $DISK 进行操作!这可能导致系统无法启动!${NC}"
    read -p "请输入 YES 确认继续: " confirm
    if [[ "$confirm" != "YES" ]]; then
        log_error "操作已取消"
    fi
    log_warn "已确认继续操作系统盘,请确保您知道风险!"
}

# 检查并安装依赖包
check_dependencies() {
    local missing_pkgs=()
    if ! command -v parted &>/dev/null; then
        missing_pkgs+=("parted")
    fi
    if [[ "$FS_TYPE" == "xfs" ]] && ! command -v mkfs.xfs &>/dev/null; then
        missing_pkgs+=("xfsprogs")
    fi
    if [[ "$FS_TYPE" == "ext4" ]] && ! command -v mkfs.ext4 &>/dev/null; then
        missing_pkgs+=("e2fsprogs")
    fi
    if [[ ${#missing_pkgs[@]} -gt 0 ]]; then
        log_warn "缺少必要软件包: ${missing_pkgs[*]}"
        read -p "是否自动安装? [y/N]: " -n 1 -r
        echo
        if [[ $REPLY =~ ^[Yy]$ ]]; then
            if command -v dnf &>/dev/null; then
                dnf install -y "${missing_pkgs[@]}" || log_error "安装失败,请手动安装: ${missing_pkgs[*]}"
            else
                log_error "未找到包管理器,请手动安装: ${missing_pkgs[*]}"
            fi
        else
            log_error "缺少必要软件包,请安装后再运行"
        fi
    fi
}

# 危险操作确认(非强制模式下交互)
confirm_danger() {
    if [[ "$FORCE_MODE" == true ]]; then
        log_warn "强制模式已启用,跳过交互确认"
        return
    fi

    echo -e "${YELLOW}警告: 即将对 $DISK 执行以下操作:${NC}"
    echo "  1. 创建 GPT 分区表(清除所有数据)"
    echo "  2. 创建 100% 容量分区"
    echo "  3. 格式化为 $FS_TYPE"
    echo "  4. 挂载到 $MOUNT_POINT 并写入开机自动挂载"
    echo -e "${RED}数据将永久丢失!${NC}"
    read -p "请输入 YES 确认继续: " confirm
    if [[ "$confirm" != "YES" ]]; then
        log_error "操作已取消"
    fi
}

# 检查磁盘是否已被挂载或使用
check_disk_usage() {
    local mounted_parts=$(lsblk -no MOUNTPOINT "$DISK" 2>/dev/null | grep -v '^$' | head -1)
    if [[ -n "$mounted_parts" ]]; then
        log_error "磁盘 $DISK 已有分区挂载在 $mounted_parts,请先卸载"
    fi

    if command -v lvs &>/dev/null && lvs 2>/dev/null | grep -q "$(basename "$DISK")"; then
        log_error "磁盘 $DISK 被 LVM 使用,请先处理"
    fi
    if swapon --show | grep -q "$DISK"; then
        log_error "磁盘 $DISK 被用作 swap,请先 swapoff"
    fi
}

# 获取分区设备名
get_partition_dev() {
    local base=$(basename "$DISK")
    if [[ "$base" == nvme* ]]; then
        echo "${DISK}p1"
    else
        echo "${DISK}1"
    fi
}

# 创建 GPT 分区
create_partition() {
    log_info "正在为 $DISK 创建 GPT 分区表..."
    wipefs -a "$DISK" 2>/dev/null || true
    parted -s "$DISK" mklabel gpt
    parted -s "$DISK" mkpart primary 0% 100%
    partprobe "$DISK" 2>/dev/null || true
    sleep 2

    PARTITION=$(get_partition_dev)
    local retry=0
    while [[ ! -b "$PARTITION" ]] && [[ $retry -lt 10 ]]; do
        sleep 1
        ((retry++))
        partprobe "$DISK" 2>/dev/null || true
    done

    if [[ ! -b "$PARTITION" ]]; then
        log_error "分区 $PARTITION 未能生成,请检查磁盘或手动创建"
    fi
    log_info "分区创建完成: $PARTITION"
}

# 格式化分区
format_partition() {
    log_info "格式化 $PARTITION 为 $FS_TYPE..."
    if [[ "$FS_TYPE" == "xfs" ]]; then
        mkfs.xfs -f "$PARTITION"
    else
        mkfs.ext4 -F "$PARTITION"
    fi
}

# 创建挂载目录并检查是否非空
create_mountpoint() {
    if [[ -d "$MOUNT_POINT" ]]; then
        if [[ -n "$(ls -A "$MOUNT_POINT")" ]]; then
            log_warn "挂载目录 $MOUNT_POINT 非空,可能会覆盖原文件"
            if [[ "$FORCE_MODE" != true ]]; then
                read -p "是否继续挂载? [y/N]: " -n 1 -r
                echo
                if [[ ! $REPLY =~ ^[Yy]$ ]]; then
                    log_error "操作已取消"
                fi
            fi
        fi
    else
        mkdir -p "$MOUNT_POINT"
        log_info "挂载目录 $MOUNT_POINT 已创建"
    fi
}

# 写入 fstab
setup_fstab() {
    UUID=$(blkid -s UUID -o value "$PARTITION")
    if [[ -z "$UUID" ]]; then
        log_error "获取 UUID 失败"
    fi

    local fstab_bak="/etc/fstab.bak.$(date +%Y%m%d%H%M%S)"
    cp /etc/fstab "$fstab_bak"
    log_info "已备份 /etc/fstab 到 $fstab_bak"

    if grep -q "^[^#].*\<$MOUNT_POINT\>" /etc/fstab 2>/dev/null; then
        log_warn "fstab 中已存在挂载点 $MOUNT_POINT 的条目,跳过添加"
        return
    fi
    if grep -q "^UUID=$UUID" /etc/fstab 2>/dev/null; then
        log_warn "fstab 中已存在 UUID=$UUID 的条目,跳过添加"
        return
    fi

    echo "UUID=$UUID $MOUNT_POINT $FS_TYPE defaults 0 0" >> /etc/fstab
    log_info "已写入 /etc/fstab"
}

# 挂载并验证
mount_all() {
    if ! mount -a 2>&1 | tee -a "$LOG_FILE"; then
        log_error "mount -a 执行失败,请检查 /etc/fstab 语法"
    fi

    if mountpoint -q "$MOUNT_POINT"; then
        log_info "✅ 挂载成功!"
        df -h "$MOUNT_POINT"
    else
        log_error "挂载失败,请手动排查"
    fi
}

# 主流程
main() {
    check_root
    parse_args "$@"
    echo "===== $(date) =====" >> "$LOG_FILE"
    log_info "脚本开始执行,参数: DISK=$DISK, MOUNT_POINT=$MOUNT_POINT, FS_TYPE=$FS_TYPE, FORCE=$FORCE_MODE"

    check_system_disk       # 新增:系统盘二次确认
    check_dependencies
    confirm_danger
    check_disk_usage
    create_partition
    format_partition
    create_mountpoint
    setup_fstab
    mount_all

    echo -e "${GREEN}=============================================${NC}"
    echo -e "${GREEN}✅ 磁盘自动分区 + 格式化 + 开机挂载 全部完成!${NC}"
    echo -e "磁盘:$DISK"
    echo -e "分区:$PARTITION"
    echo -e "挂载点:$MOUNT_POINT"
    echo -e "文件系统:$FS_TYPE"
    echo -e "${GREEN}=============================================${NC}"
    log_info "脚本执行成功"
}

main "$@"

四 安装桌面

4.1 安装gnome 桌面

第一步:将系统更新至最新

在开始任何安装前,建议先将系统和软件源更新到最新版本,这能保证后续依赖包的顺利安装。


sudo dnf update -y

第二步:安装桌面环境 (GUI)

你可以从以下几种桌面环境中,根据自己的偏好选择一个进行安装。
方案A:安装 GNOME

GNOME 是 Linux 上最流行的桌面环境之一,界面现代,对 Wayland 协议有良好支持。如果你的虚拟机内存大于 2GB,建议选择 GNOME。
bash

1. 安装 Xorg 服务器以及 GNOME 桌面环境的核心组件
sudo dnf install -y xorg-x11-server-Xorg gdm gnome-shell gnome-terminal gnome-classic-session

bash

# 2. 将系统默认启动目标设置为图形界面
sudo systemctl set-default graphical.target

bash

# 3. 启用 GDM (GNOME Display Manager) 服务并立即启动
sudo systemctl enable gdm && sudo systemctl start gdm

执行 start gdm 后,系统会立即切换到图形界面。之后重启,系统会自动进入图形登录界面。

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐