CentOS 7 源码编译安装 Python 3.11 完整教程
脚本二测试通过:

资源部下载链接:
https://1816440419.share.123pan.cn/123pan/9QRqVv-XHvG


适用环境
- 系统:CentOS 7(初始系统,未更新 yum)
- 网络:可连接外网
- 目标:编译安装 Python 3.11.9,解决 SQLite 3.8.3+ 的版本要求,不影响系统自带的 Python 2.7
一、更换国内 Yum 源
CentOS 7 官方源已停止维护且速度慢,先切换到阿里云镜像。
bash
# 1. 备份系统默认源
sudo mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
# 2. 下载阿里云 CentOS 7 源(初始系统无 wget,用 curl)
sudo curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
# 3. 清理并重建缓存
sudo yum clean all
sudo yum makecache
二、安装 EPEL 源并切换国内镜像
Python 3.11 需要 OpenSSL 1.1+,这在 EPEL 源里。
bash
# 1. 安装 EPEL 源
sudo yum install -y epel-release
# 2. 备份并替换为阿里云 EPEL 镜像
sudo mv /etc/yum.repos.d/epel.repo /etc/yum.repos.d/epel.repo.backup 2>/dev/null
sudo mv /etc/yum.repos.d/epel-testing.repo /etc/yum.repos.d/epel-testing.repo.backup 2>/dev/null
sudo curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
# 3. 修正 repo 文件,强制使用 baseurl(避免残留国外 CDN 地址)
sudo sed -i 's/mirrorlist=/#mirrorlist=/g' /etc/yum.repos.d/epel.repo
sudo sed -i 's|#baseurl=http://download.fedoraproject.org/pub/epel|baseurl=http://mirrors.aliyun.com/epel|g' /etc/yum.repos.d/epel.repo
# 4. 彻底清理 EPEL 旧缓存
sudo yum clean all
sudo rm -rf /var/cache/yum/x86_64/7/epel
sudo yum makecache
三、安装编译依赖
bash
# 1. 处理 Development Tools 组安装
sudo yum groups mark install "Development Tools"
sudo yum groups mark convert "Development Tools"
sudo yum groupinstall -y "Development Tools"
# 2. 安装基础编译依赖
sudo yum install -y gcc zlib-devel bzip2-devel libffi-devel readline-devel
# 3. 安装 SQLite 编译依赖(用于后续升级)
sudo yum install -y sqlite-devel
# 4. 安装 OpenSSL 1.1(Python 3.11 的关键依赖)
sudo yum install -y openssl-devel openssl11 openssl11-devel
# 5. 安装缺失的可选模块依赖
sudo yum install -y xz-devel libuuid-devel gdbm-devel
# 6. 安装 wget(后续下载用)
sudo yum install -y wget
依赖说明:
sqlite-devel:虽然系统版本低,但编译时需要头文件,后续通过编译新版 SQLite 解决版本问题openssl11-devel:Python 3.11 要求 OpenSSL 1.1.1+xz-devel:提供_lzma模块支持libuuid-devel:提供_uuid模块支持gdbm-devel:提供_dbm和_gdbm模块支持
四、升级系统 SQLite
CentOS 7 自带的 SQLite 版本为 3.7.17,而 Django 2.2+ 要求 3.8.3+。必须手动升级。
4.1 下载并编译新版 SQLite
bash
# 1. 下载 SQLite 源码(以 3.42.0 为例,2023 年的稳定版本)
cd /tmp
wget https://www.sqlite.org/2023/sqlite-autoconf-3420000.tar.gz
tar -xzf sqlite-autoconf-3420000.tar.gz
cd sqlite-autoconf-3420000
# 2. 编译安装到 /usr/local
./configure --prefix=/usr/local
make -j $(nproc)
sudo make install
4.2 替换系统旧版 SQLite
bash
# 1. 备份旧版本
sudo mv /usr/bin/sqlite3 /usr/bin/sqlite3.old 2>/dev/null
# 2. 创建新版本软链接
sudo ln -sf /usr/local/bin/sqlite3 /usr/bin/sqlite3
# 3. 配置动态链接库路径
echo "/usr/local/lib" | sudo tee /etc/ld.so.conf.d/sqlite3.conf
sudo ldconfig
4.3 验证升级结果
bash
sqlite3 --version
预期输出:3.42.0 2023-05-16 ...
五、下载并编译 Python 3.11
5.1 设置编译环境变量
让编译器找到新版 OpenSSL 和新版 SQLite:
bash
export CFLAGS="$(pkg-config --cflags openssl11) -I/usr/local/include"
export LDFLAGS="$(pkg-config --libs openssl11) -L/usr/local/lib"
export LD_RUN_PATH="/usr/local/lib"
环境变量说明:
CFLAGS:添加/usr/local/include让编译器找到新版 SQLite 的头文件LDFLAGS:添加/usr/local/lib让链接器找到新版 SQLite 的库文件LD_RUN_PATH:指定运行时动态库搜索路径,避免运行时找不到新版 SQLite 库
5.2 下载 Python 源码
bash
cd /tmp
wget https://www.python.org/ftp/python/3.11.9/Python-3.11.9.tgz
tar -xzf Python-3.11.9.tgz
cd Python-3.11.9
5.3 配置、编译、安装
重要提示 :CentOS 7 自带的 GCC 4.8.5 与
--enable-optimizations参数不兼容,会导致编译失败,因此不能加该参数。
bash
./configure \
--prefix=/usr/local/python311 \
--enable-loadable-sqlite-extensions
make -j $(nproc)
sudo make altinstall
参数说明:
--prefix=/usr/local/python311:安装到独立目录,不覆盖系统 Python--enable-loadable-sqlite-extensions:确保 sqlite3 模块可以正常加载扩展altinstall:只创建python3.11命令,不动/usr/bin/python,保证 yum 不受影响-j $(nproc):使用所有 CPU 核心并行编译,加快速度
六、创建软链接并验证
6.1 创建软链接
bash
sudo ln -sf /usr/local/python311/bin/python3.11 /usr/bin/python3.11
sudo ln -sf /usr/local/python311/bin/pip3.11 /usr/bin/pip3.11
6.2 验证安装
bash
# 验证 Python 版本
python3.11 --version
# 预期输出:Python 3.11.9
# 验证 pip 版本
pip3.11 --version
# 预期输出:pip 24.0 ...
# 验证 SSL 模块
python3.11 -c "import ssl; print(ssl.OPENSSL_VERSION)"
# 预期输出:OpenSSL 1.1.1k ...
# 验证 SQLite 版本(关键!Django 需要 ≥ 3.8.3)
python3.11 -c "import sqlite3; print(sqlite3.sqlite_version)"
# 预期输出:3.42.0
# 验证其他重要模块
python3.11 -c "import lzma, uuid, bz2, ssl, sqlite3; print('所有核心模块正常')"
# 预期输出:所有核心模块正常
七、配置 pip 国内镜像源
推荐使用华为云镜像源加速包下载:
bash
pip3.11 config set global.index-url https://repo.huaweicloud.com/repository/pypi/simple
验证配置:
bash
pip3.11 config list
其他国内镜像源(可选):
- 阿里云:
https://mirrors.aliyun.com/pypi/simple/ - 清华:
https://pypi.tuna.tsinghua.edu.cn/simple/ - 中科大:
https://pypi.mirrors.ustc.edu.cn/simple/
八、升级 pip(可选)
bash
pip3.11 install --upgrade pip
九、重要提醒
9.1 绝对不要替换系统 Python
CentOS 7 的 yum 等核心工具依赖 /usr/bin/python(指向 Python 2.7),使用新版本时请明确输入 python3.11 和 pip3.11。
9.2 使用虚拟环境(强烈建议)
安装第三方包时创建虚拟环境,避免污染系统级 Python 和依赖冲突:
bash
# 创建虚拟环境
python3.11 -m venv myenv
# 激活虚拟环境
source myenv/bin/activate
# 退出虚拟环境
deactivate
9.3 SQLite 版本问题排查
如果之前已用旧版 SQLite 编译了 Python,即使后来升级了系统 SQLite,Python 仍会使用旧的库。必须重新编译 Python 并设置 LD_RUN_PATH 才能生效。
验证命令:
bash
python3.11 -c "import sqlite3; print(sqlite3.sqlite_version)"
如果输出 3.7.17 而不是你安装的新版本,说明 Python 仍在使用旧版 SQLite,需要重新编译。
9.4 常见缺失模块处理
如果运行程序时遇到 ModuleNotFoundError: No module named '_xxx' 的错误,通常是缺少对应的 -devel 包,安装后重新编译 Python 即可:
| 错误模块 | 缺失的 devel 包 | 安装命令 |
|---|---|---|
_sqlite3 |
sqlite-devel |
sudo yum install -y sqlite-devel |
_ssl |
openssl11-devel |
sudo yum install -y openssl11-devel |
_bz2 |
bzip2-devel |
sudo yum install -y bzip2-devel |
_lzma |
xz-devel |
sudo yum install -y xz-devel |
_uuid |
libuuid-devel |
sudo yum install -y libuuid-devel |
_dbm / _gdbm |
gdbm-devel |
sudo yum install -y gdbm-devel |
附录一:完整操作命令汇总
以下是所有步骤的纯净版命令(无多余试错):
bash
# ========== 第一部分:更换 Yum 源 ==========
sudo mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
sudo curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
sudo yum clean all
sudo yum makecache
# ========== 第二部分:配置 EPEL 源 ==========
sudo yum install -y epel-release
sudo mv /etc/yum.repos.d/epel.repo /etc/yum.repos.d/epel.repo.backup 2>/dev/null
sudo mv /etc/yum.repos.d/epel-testing.repo /etc/yum.repos.d/epel-testing.repo.backup 2>/dev/null
sudo curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
sudo sed -i 's/mirrorlist=/#mirrorlist=/g' /etc/yum.repos.d/epel.repo
sudo sed -i 's|#baseurl=http://download.fedoraproject.org/pub/epel|baseurl=http://mirrors.aliyun.com/epel|g' /etc/yum.repos.d/epel.repo
sudo yum clean all
sudo rm -rf /var/cache/yum/x86_64/7/epel
sudo yum makecache
# ========== 第三部分:安装编译依赖 ==========
sudo yum groups mark install "Development Tools"
sudo yum groups mark convert "Development Tools"
sudo yum groupinstall -y "Development Tools"
sudo yum install -y gcc zlib-devel bzip2-devel libffi-devel readline-devel
sudo yum install -y sqlite-devel xz-devel libuuid-devel gdbm-devel
sudo yum install -y openssl-devel openssl11 openssl11-devel
sudo yum install -y wget
# ========== 第四部分:升级系统 SQLite ==========
cd /tmp
wget https://www.sqlite.org/2023/sqlite-autoconf-3420000.tar.gz
tar -xzf sqlite-autoconf-3420000.tar.gz
cd sqlite-autoconf-3420000
./configure --prefix=/usr/local
make -j $(nproc)
sudo make install
sudo mv /usr/bin/sqlite3 /usr/bin/sqlite3.old 2>/dev/null
sudo ln -sf /usr/local/bin/sqlite3 /usr/bin/sqlite3
echo "/usr/local/lib" | sudo tee /etc/ld.so.conf.d/sqlite3.conf
sudo ldconfig
# ========== 第五部分:编译安装 Python 3.11 ==========
cd /tmp
wget https://www.python.org/ftp/python/3.11.9/Python-3.11.9.tgz
tar -xzf Python-3.11.9.tgz
cd Python-3.11.9
export CFLAGS="$(pkg-config --cflags openssl11) -I/usr/local/include"
export LDFLAGS="$(pkg-config --libs openssl11) -L/usr/local/lib"
export LD_RUN_PATH="/usr/local/lib"
./configure --prefix=/usr/local/python311 --enable-loadable-sqlite-extensions
make -j $(nproc)
sudo make altinstall
# ========== 第六部分:创建软链接并验证 ==========
sudo ln -sf /usr/local/python311/bin/python3.11 /usr/bin/python3.11
sudo ln -sf /usr/local/python311/bin/pip3.11 /usr/bin/pip3.11
python3.11 --version
pip3.11 --version
python3.11 -c "import ssl; print(ssl.OPENSSL_VERSION)"
python3.11 -c "import sqlite3; print(sqlite3.sqlite_version)"
# ========== 第七部分:配置 pip 镜像源 ==========
pip3.11 config set global.index-url https://repo.huaweicloud.com/repository/pypi/simple
附录二:自动化安装脚本
保存以下内容为 install_python311.sh,然后执行 sudo ./install_python311.sh:
bash
#!/bin/bash
#===============================================================================
# CentOS 7 自动化安装 Python 3.11.9 脚本
# 适用环境:CentOS 7 初始系统,可连接外网
# 功能:
# 1. 更换阿里云 Yum 源和 EPEL 源
# 2. 升级系统 SQLite 到 3.42.0
# 3. 编译安装 Python 3.11.9(含 SSL、SQLite、lzma、uuid 等模块)
# 4. 配置 pip 华为云镜像源
# 使用方法:
# chmod +x install_python311.sh
# sudo ./install_python311.sh
#===============================================================================
set -e # 遇到错误立即退出
# ============================================================================
# 颜色定义
# ============================================================================
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# ============================================================================
# 日志函数
# ============================================================================
log_info() {
echo -e "${GREEN}[INFO]${NC} $1"
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
exit 1
}
log_step() {
echo ""
echo -e "${BLUE}============================================${NC}"
echo -e "${BLUE}$1${NC}"
echo -e "${BLUE}============================================${NC}"
}
# ============================================================================
# 环境检查
# ============================================================================
check_root() {
if [ "$(id -u)" != "0" ]; then
log_error "请使用 root 用户或 sudo 执行此脚本"
fi
log_info "当前为 root 用户,继续执行..."
}
check_network() {
log_info "检查网络连接..."
if ! ping -c 2 -W 3 www.baidu.com > /dev/null 2>&1; then
log_error "无法连接外网,请检查网络配置"
fi
log_info "网络连接正常"
}
# ============================================================================
# 第一部分:更换 Yum 源
# ============================================================================
replace_yum_repo() {
log_step "第一步:更换阿里云 Yum 源"
# 备份原配置
if [ -f /etc/yum.repos.d/CentOS-Base.repo ]; then
mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
log_info "已备份原 CentOS-Base.repo"
fi
# 下载阿里云源
curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
# 清理并重建缓存
yum clean all
yum makecache
log_info "基础 Yum 源更换完成"
}
# ============================================================================
# 第二部分:配置 EPEL 源
# ============================================================================
configure_epel() {
log_step "第二步:配置阿里云 EPEL 源"
# 安装 EPEL
yum install -y epel-release
# 备份原 EPEL 配置
[ -f /etc/yum.repos.d/epel.repo ] && mv /etc/yum.repos.d/epel.repo /etc/yum.repos.d/epel.repo.backup 2>/dev/null || true
[ -f /etc/yum.repos.d/epel-testing.repo ] && mv /etc/yum.repos.d/epel-testing.repo /etc/yum.repos.d/epel-testing.repo.backup 2>/dev/null || true
# 下载阿里云 EPEL 镜像源
curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
# 强制使用 baseurl,避免残留国外 CDN 地址
sed -i 's/mirrorlist=/#mirrorlist=/g' /etc/yum.repos.d/epel.repo
sed -i 's|#baseurl=http://download.fedoraproject.org/pub/epel|baseurl=http://mirrors.aliyun.com/epel|g' /etc/yum.repos.d/epel.repo
# 彻底清理 EPEL 旧缓存
yum clean all
rm -rf /var/cache/yum/x86_64/7/epel
yum makecache
log_info "EPEL 源配置完成"
}
# ============================================================================
# 第三部分:安装编译依赖
# ============================================================================
install_dependencies() {
log_step "第三步:安装编译依赖"
# 安装 Development Tools 组
yum groups mark install "Development Tools" 2>/dev/null || true
yum groups mark convert "Development Tools" 2>/dev/null || true
yum groupinstall -y "Development Tools"
# 安装基础依赖
yum install -y gcc zlib-devel bzip2-devel libffi-devel readline-devel
# 安装 SQLite 编译依赖
yum install -y sqlite-devel
# 安装可选模块依赖
yum install -y xz-devel libuuid-devel gdbm-devel
# 安装 OpenSSL 1.1(Python 3.11 必需)
yum install -y openssl-devel openssl11 openssl11-devel
# 安装 wget
yum install -y wget
log_info "编译依赖安装完成"
}
# ============================================================================
# 第四部分:升级系统 SQLite
# ============================================================================
upgrade_sqlite() {
log_step "第四步:升级系统 SQLite 到 3.42.0"
local SQLITE_VERSION="3420000"
local SQLITE_DIR="/tmp/sqlite-autoconf-${SQLITE_VERSION}"
# 如果已编译过,跳过
if [ -f /usr/local/bin/sqlite3 ]; then
INSTALLED_VERSION=$(/usr/local/bin/sqlite3 --version | awk '{print $1}')
if [ "$INSTALLED_VERSION" = "3.42.0" ]; then
log_info "SQLite 3.42.0 已安装,跳过编译"
return
fi
fi
cd /tmp
# 下载源码
if [ ! -f "sqlite-autoconf-${SQLITE_VERSION}.tar.gz" ]; then
log_info "下载 SQLite 源码..."
wget -q https://www.sqlite.org/2023/sqlite-autoconf-${SQLITE_VERSION}.tar.gz
else
log_info "SQLite 源码包已存在,跳过下载"
fi
# 解压
tar -xzf sqlite-autoconf-${SQLITE_VERSION}.tar.gz
cd "$SQLITE_DIR"
# 编译安装
log_info "编译安装 SQLite..."
./configure --prefix=/usr/local
make -j $(nproc)
make install
# 替换系统旧版本
mv /usr/bin/sqlite3 /usr/bin/sqlite3.old 2>/dev/null || true
ln -sf /usr/local/bin/sqlite3 /usr/bin/sqlite3
# 配置动态链接库
echo "/usr/local/lib" > /etc/ld.so.conf.d/sqlite3.conf
ldconfig
# 验证
SQLITE_VER=$(sqlite3 --version | awk '{print $1}')
log_info "SQLite 版本:${SQLITE_VER}"
}
# ============================================================================
# 第五部分:编译安装 Python 3.11
# ============================================================================
compile_python() {
log_step "第五步:编译安装 Python 3.11.9"
local PYTHON_VERSION="3.11.9"
local PYTHON_PREFIX="/usr/local/python311"
local SOURCE_DIR="/tmp/Python-${PYTHON_VERSION}"
cd /tmp
# 下载源码
if [ ! -f "Python-${PYTHON_VERSION}.tgz" ]; then
log_info "下载 Python ${PYTHON_VERSION} 源码..."
wget -q https://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTHON_VERSION}.tgz
else
log_info "Python 源码包已存在,跳过下载"
fi
# 清理旧目录(如果存在)
if [ -d "$SOURCE_DIR" ]; then
rm -rf "$SOURCE_DIR"
log_info "清理旧的源码目录"
fi
# 解压
tar -xzf Python-${PYTHON_VERSION}.tgz
cd "$SOURCE_DIR"
# 设置编译环境变量
# 1. CFLAGS:添加 /usr/local/include 让编译器找到新版 SQLite 头文件
# 2. LDFLAGS:添加 /usr/local/lib 让链接器找到新版 SQLite 库文件
# 3. LD_RUN_PATH:指定运行时动态库搜索路径
export CFLAGS="$(pkg-config --cflags openssl11) -I/usr/local/include"
export LDFLAGS="$(pkg-config --libs openssl11) -L/usr/local/lib"
export LD_RUN_PATH="/usr/local/lib"
# 配置编译选项
# 注意:不加 --enable-optimizations,因为 CentOS 7 的 GCC 4.8.5 不兼容
log_info "配置编译选项..."
./configure \
--prefix="${PYTHON_PREFIX}" \
--enable-loadable-sqlite-extensions
# 编译
local CPU_CORES=$(nproc)
log_info "使用 ${CPU_CORES} 个核心并行编译..."
make -j ${CPU_CORES}
# 安装
log_info "安装 Python ${PYTHON_VERSION}..."
make altinstall
cd /tmp
log_info "Python ${PYTHON_VERSION} 编译安装完成"
}
# ============================================================================
# 第六部分:创建软链接
# ============================================================================
create_links() {
log_step "第六步:创建软链接"
ln -sf /usr/local/python311/bin/python3.11 /usr/bin/python3.11
ln -sf /usr/local/python311/bin/pip3.11 /usr/bin/pip3.11
log_info "软链接创建完成"
}
# ============================================================================
# 第七部分:验证安装
# ============================================================================
verify_installation() {
log_step "第七步:验证安装"
# 验证 Python 版本
PYTHON_VER=$(python3.11 --version 2>&1)
log_info "Python 版本:${PYTHON_VER}"
# 验证 pip 版本
PIP_VER=$(pip3.11 --version 2>&1)
log_info "pip 版本:${PIP_VER}"
# 验证 SSL 模块
SSL_VER=$(python3.11 -c "import ssl; print(ssl.OPENSSL_VERSION)" 2>&1)
log_info "SSL 版本:${SSL_VER}"
# 验证 SQLite 版本(关键检查)
SQLITE_VER=$(python3.11 -c "import sqlite3; print(sqlite3.sqlite_version)" 2>&1)
log_info "SQLite 版本:${SQLITE_VER}"
# 检查 SQLite 版本是否满足 Django 要求(≥ 3.8.3)
SQLITE_MAJOR=$(echo "$SQLITE_VER" | cut -d. -f1)
SQLITE_MINOR=$(echo "$SQLITE_VER" | cut -d. -f2)
if [ "$SQLITE_MAJOR" -ge 3 ] && [ "$SQLITE_MINOR" -ge 8 ]; then
log_info "SQLite 版本满足 Django 要求(≥ 3.8.3)"
else
log_warn "SQLite 版本过低,Django 可能无法正常运行!"
log_warn "请检查环境变量 LD_RUN_PATH 是否正确设置"
fi
# 验证其他关键模块
python3.11 -c "import lzma, uuid, bz2; print('其他核心模块验证通过')" 2>&1
log_info "lzma、uuid、bz2 模块正常"
}
# ============================================================================
# 第八部分:配置 pip 镜像源
# ============================================================================
configure_pip_mirror() {
log_step "第八步:配置 pip 华为云镜像源"
pip3.11 config set global.index-url https://repo.huaweicloud.com/repository/pypi/simple
log_info "pip 镜像源配置为华为云"
# 显示当前配置
pip3.11 config list 2>/dev/null || true
}
# ============================================================================
# 第九部分:清理临时文件
# ============================================================================
cleanup() {
log_step "第九步:清理临时文件"
rm -rf /tmp/Python-3.11.9 /tmp/Python-3.11.9.tgz
rm -rf /tmp/sqlite-autoconf-3420000 /tmp/sqlite-autoconf-3420000.tar.gz
log_info "临时文件清理完成"
}
# ============================================================================
# 完成提示
# ============================================================================
print_summary() {
echo ""
echo -e "${GREEN}============================================${NC}"
echo -e "${GREEN} Python 3.11.9 安装完成!${NC}"
echo -e "${GREEN}============================================${NC}"
echo ""
echo -e "安装位置:${BLUE}/usr/local/python311${NC}"
echo -e "Python 命令:${BLUE}python3.11${NC}"
echo -e "pip 命令:${BLUE}pip3.11${NC}"
echo -e "pip 镜像源:${BLUE}华为云${NC}"
echo ""
echo -e "${YELLOW}使用示例:${NC}"
echo " 查看版本:python3.11 --version"
echo " 安装包:pip3.11 install <package>"
echo " 创建虚拟环境:python3.11 -m venv myenv"
echo " 激活虚拟环境:source myenv/bin/activate"
echo ""
echo -e "${RED}⚠ 重要提醒:${NC}"
echo " 1. 切勿使用 python 或 pip 命令,避免影响系统 Python 2.7"
echo " 2. 请使用 python3.11 和 pip3.11"
echo " 3. 建议在虚拟环境中安装第三方包"
echo -e "${GREEN}============================================${NC}"
echo ""
}
# ============================================================================
# 主函数
# ============================================================================
main() {
echo ""
echo -e "${GREEN}============================================${NC}"
echo -e "${GREEN} CentOS 7 自动安装 Python 3.11.9${NC}"
echo -e "${GREEN} 版本:2026-04-25${NC}"
echo -e "${GREEN}============================================${NC}"
echo ""
# 环境检查
check_root
check_network
# 执行安装步骤
replace_yum_repo
configure_epel
install_dependencies
upgrade_sqlite
compile_python
create_links
verify_installation
configure_pip_mirror
cleanup
# 打印完成摘要
print_summary
}
# 执行主函数
main "$@"
使用方法
-
保存脚本:
bashvi install_python311.sh -
粘贴上面的完整脚本内容,保存退出
-
添加执行权限并运行:
bashchmod +x install_python311.sh sudo ./install_python311.sh
脚本二
sh
#!/bin/bash
#===============================================================================
# CentOS 7 自动化安装 Python 3.11.9 脚本(带进度显示 + 断点续传)
# 适用环境:CentOS 7 初始系统,可连接外网
# 功能:
# 1. 更换阿里云 Yum 源和 EPEL 源
# 2. 升级系统 SQLite 到 3.42.0(国内/官网双下载源)
# 3. 编译安装 Python 3.11.9(含 SSL、SQLite、lzma、uuid 等模块)
# 4. 配置 pip 华为云镜像源
# 5. 支持中断后继续(断点续传)
# 使用方法:
# chmod +x install_python311.sh
# sudo ./install_python311.sh
#===============================================================================
set -e # 遇到错误立即退出
# ============================================================================
# 全局变量
# ============================================================================
TOTAL_STEPS=9
CURRENT_STEP=0
SCRIPT_START_TIME=$(date +%s)
STATE_FILE="/tmp/python311_install_state"
# 状态值:
# 0 - 未开始
# 1 - yum_repo 完成
# 2 - epel 完成
# 3 - dependencies 完成
# 4 - sqlite 完成
# 5 - python_compile 完成
# 6 - links 完成
# 7 - verify 完成
# 8 - pip_mirror 完成
# 9 - cleanup 完成
# ============================================================================
# 颜色定义
# ============================================================================
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
MAGENTA='\033[0;35m'
NC='\033[0m' # No Color
BOLD='\033[1m'
# 如果标准输出不是终端(如被重定向),去掉颜色
if [ ! -t 1 ]; then
RED='' GREEN='' YELLOW='' BLUE='' CYAN='' MAGENTA='' NC='' BOLD=''
fi
# ============================================================================
# 工具函数:检测 wget 版本,选择合适的参数
# ============================================================================
WGET_OPTS="-q"
detect_wget() {
# 检测 wget 是否支持 --show-progress
if wget --help 2>&1 | grep -q '\-\-show-progress'; then
WGET_OPTS="-q --show-progress"
else
# 旧版 wget 不支持,使用 -nv 显示基本信息
WGET_OPTS="-nv"
fi
}
# ============================================================================
# 通用下载函数(兼容新旧 wget)
# ============================================================================
wget_download() {
local url="$1"
local output="$2"
local desc="$3"
local timeout="${4:-60}"
local tries="${5:-3}"
if [ -n "$output" ]; then
wget ${WGET_OPTS} --timeout=${timeout} --tries=${tries} -O "$output" "$url" 2>&1
else
wget ${WGET_OPTS} --timeout=${timeout} --tries=${tries} "$url" 2>&1
fi
return $?
}
# ============================================================================
# 状态管理函数
# ============================================================================
get_state() {
if [ -f "$STATE_FILE" ]; then
cat "$STATE_FILE"
else
echo "0"
fi
}
set_state() {
echo "$1" > "$STATE_FILE"
chmod 644 "$STATE_FILE" 2>/dev/null || true
}
clear_state() {
rm -f "$STATE_FILE"
}
# ============================================================================
# 进度条和日志函数
# ============================================================================
show_progress() {
local step_num=$1
local total=$2
local percent=$((step_num * 100 / total))
local bar_width=40
local filled=$((percent * bar_width / 100))
local empty=$((bar_width - filled))
printf "\r${CYAN}[进度]${NC} ["
printf "${GREEN}%-${filled}s${NC}" | tr ' ' '█'
printf "${RED}%-${empty}s${NC}" | tr ' ' '░'
printf "] ${BOLD}%3d%%${NC} (步骤 %d/%d)" "$percent" "$step_num" "$total"
}
log_info() {
echo -e "\n${GREEN}[INFO]${NC} $1"
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
log_error() {
echo -e "\n${RED}[ERROR]${NC} $1"
exit 1
}
log_step_header() {
CURRENT_STEP=$((CURRENT_STEP + 1))
echo ""
echo -e "${BLUE}╔══════════════════════════════════════════════════════════════╗${NC}"
printf "${BLUE}║${NC} ${BOLD}步骤 %d/%d:%s${NC}" "$CURRENT_STEP" "$TOTAL_STEPS" "$1"
local header_text="步骤 $CURRENT_STEP/$TOTAL_STEPS:$1"
local text_length=${#header_text}
local padding=$((58 - text_length))
[ $padding -lt 1 ] && padding=1
printf "%${padding}s${BLUE}║${NC}\n" ""
echo -e "${BLUE}╚══════════════════════════════════════════════════════════════╝${NC}"
if [ -t 1 ]; then
show_progress "$CURRENT_STEP" "$TOTAL_STEPS"
fi
}
log_substep() {
echo -e " ${CYAN}➤${NC} $1"
}
log_success() {
echo -e " ${GREEN}✔${NC} $1"
}
log_fail() {
echo -e " ${RED}✘${NC} $1"
}
log_skip() {
echo -e " ${MAGENTA}◎${NC} $1 (已完成,跳过)"
}
# 显示耗时
show_elapsed() {
local current_time=$(date +%s)
local elapsed=$((current_time - $1))
local hours=$((elapsed / 3600))
local minutes=$(((elapsed % 3600) / 60))
local seconds=$((elapsed % 60))
if [ $hours -gt 0 ]; then
echo -e "${MAGENTA}⏱ 耗时:${hours}小时${minutes}分${seconds}秒${NC}"
elif [ $minutes -gt 0 ]; then
echo -e "${MAGENTA}⏱ 耗时:${minutes}分${seconds}秒${NC}"
else
echo -e "${MAGENTA}⏱ 耗时:${seconds}秒${NC}"
fi
}
# 旋转指示器(用于后台任务)
spinner() {
local pid=$1
local delay=0.1
local spinstr='⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏'
if [ ! -t 1 ]; then
wait $pid
return
fi
while kill -0 $pid 2>/dev/null; do
local temp=${spinstr#?}
printf "\r ${CYAN}[%c]${NC} 处理中..." "$spinstr"
local spinstr=$temp${spinstr%"$temp"}
sleep $delay
done
printf "\r ${GREEN}✔${NC} 完成 \n"
}
# ============================================================================
# 环境检查
# ============================================================================
check_root() {
log_step_header "检查运行权限"
log_substep "检查是否为 root 用户..."
if [ "$(id -u)" != "0" ]; then
log_fail "当前用户不是 root"
log_error "请使用 root 用户或 sudo 执行此脚本"
fi
log_success "当前为 root 用户"
set_state "0.5"
show_elapsed "$SCRIPT_START_TIME"
}
check_network() {
log_step_header "检查网络连接"
log_substep "测试外网连通性..."
if ping -c 2 -W 3 www.baidu.com > /dev/null 2>&1; then
log_success "网络连接正常"
else
log_fail "无法连接外网"
log_error "请检查网络配置后重试"
fi
show_elapsed "$SCRIPT_START_TIME"
}
# ============================================================================
# 第一部分:更换 Yum 源
# ============================================================================
replace_yum_repo() {
if [ "$(get_state)" -ge 1 ]; then
log_step_header "更换阿里云 Yum 源"
log_skip "Yum 源已配置"
show_elapsed "$SCRIPT_START_TIME"
return
fi
log_step_header "更换阿里云 Yum 源"
log_substep "备份原 CentOS-Base.repo..."
if [ -f /etc/yum.repos.d/CentOS-Base.repo ]; then
mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
log_success "已备份原配置"
else
log_warn "原配置文件不存在,跳过备份"
fi
log_substep "下载阿里云 CentOS 7 源..."
if curl -s -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo; then
log_success "下载完成"
else
log_fail "下载失败"
log_error "请检查网络连接"
fi
log_substep "清理 Yum 缓存..."
yum clean all > /dev/null 2>&1
log_success "缓存清理完成"
log_substep "重建 Yum 缓存..."
yum makecache -q > /dev/null 2>&1 &
spinner $!
log_success "缓存重建完成"
set_state "1"
show_elapsed "$SCRIPT_START_TIME"
}
# ============================================================================
# 第二部分:配置 EPEL 源
# ============================================================================
configure_epel() {
if [ "$(get_state)" -ge 2 ]; then
log_step_header "配置阿里云 EPEL 源"
log_skip "EPEL 源已配置"
show_elapsed "$SCRIPT_START_TIME"
return
fi
log_step_header "配置阿里云 EPEL 源"
log_substep "安装 EPEL 源..."
yum install -y -q epel-release > /dev/null 2>&1 &
spinner $!
log_success "EPEL 源安装完成"
log_substep "备份原 EPEL 配置..."
[ -f /etc/yum.repos.d/epel.repo ] && mv /etc/yum.repos.d/epel.repo /etc/yum.repos.d/epel.repo.backup 2>/dev/null || true
[ -f /etc/yum.repos.d/epel-testing.repo ] && mv /etc/yum.repos.d/epel-testing.repo /etc/yum.repos.d/epel-testing.repo.backup 2>/dev/null || true
log_success "备份完成"
log_substep "下载阿里云 EPEL 镜像源..."
if curl -s -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo; then
log_success "下载完成"
else
log_fail "下载失败"
log_error "请检查网络连接"
fi
log_substep "修正 EPEL 配置(强制使用 baseurl)..."
sed -i 's/mirrorlist=/#mirrorlist=/g' /etc/yum.repos.d/epel.repo
sed -i 's|#baseurl=http://download.fedoraproject.org/pub/epel|baseurl=http://mirrors.aliyun.com/epel|g' /etc/yum.repos.d/epel.repo
log_success "配置修正完成"
log_substep "清理 EPEL 旧缓存..."
yum clean all > /dev/null 2>&1
rm -rf /var/cache/yum/x86_64/7/epel
log_success "旧缓存清理完成"
log_substep "重建缓存..."
yum makecache -q > /dev/null 2>&1 &
spinner $!
log_success "EPEL 源配置完成"
set_state "2"
show_elapsed "$SCRIPT_START_TIME"
}
# ============================================================================
# 第三部分:安装编译依赖
# ============================================================================
install_dependencies() {
if [ "$(get_state)" -ge 3 ]; then
log_step_header "安装编译依赖"
log_skip "编译依赖已安装"
show_elapsed "$SCRIPT_START_TIME"
return
fi
log_step_header "安装编译依赖"
log_substep "准备安装 Development Tools 组..."
yum groups mark install "Development Tools" > /dev/null 2>&1 || true
yum groups mark convert "Development Tools" > /dev/null 2>&1 || true
log_substep "安装 Development Tools(可能需要几分钟)..."
yum groupinstall -y -q "Development Tools" > /dev/null 2>&1 &
spinner $!
log_success "Development Tools 安装完成"
log_substep "安装基础编译依赖..."
local pkgs="gcc zlib-devel bzip2-devel libffi-devel readline-devel"
echo -e " ${CYAN} →${NC} 安装: ${pkgs}"
yum install -y -q $pkgs > /dev/null 2>&1 &
spinner $!
log_success "基础依赖安装完成"
log_substep "安装 SQLite 编译依赖..."
yum install -y -q sqlite-devel > /dev/null 2>&1 &
spinner $!
log_success "SQLite 依赖安装完成"
log_substep "安装可选模块依赖(lzma、uuid、gdbm)..."
yum install -y -q xz-devel libuuid-devel gdbm-devel > /dev/null 2>&1 &
spinner $!
log_success "可选模块依赖安装完成"
log_substep "安装 OpenSSL 1.1(Python 3.11 必需)..."
yum install -y -q openssl-devel openssl11 openssl11-devel > /dev/null 2>&1 &
spinner $!
log_success "OpenSSL 1.1 安装完成"
log_substep "安装 wget..."
yum install -y -q wget > /dev/null 2>&1 &
spinner $!
log_success "wget 安装完成"
# 检测 wget 版本
detect_wget
set_state "3"
show_elapsed "$SCRIPT_START_TIME"
}
# ============================================================================
# 下载函数(支持国内备用源,兼容新旧 wget)
# ============================================================================
download_with_fallback() {
local primary_url="$1"
local fallback_url="$2"
local output_file="$3"
local description="$4"
log_substep "尝试从主源下载 ${description}..."
echo -e " ${CYAN} →${NC} 主源:${primary_url}"
if wget_download "$primary_url" "$output_file" "$description"; then
log_success "从主源下载成功"
return 0
fi
log_warn "主源下载失败,切换到备用源(国内 Gitee)..."
echo -e " ${CYAN} →${NC} 备用:${fallback_url}"
if [ -n "$fallback_url" ]; then
if wget_download "$fallback_url" "$output_file" "$description" 120 5; then
log_success "从备用源下载成功"
return 0
fi
log_fail "备用源下载也失败"
fi
# 如果还是失败,尝试用 curl 作为最后的备用方案
log_warn "wget 下载失败,尝试使用 curl 下载..."
if curl -L -o "$output_file" "$primary_url" --connect-timeout 30 --retry 3 -# 2>&1; then
log_success "使用 curl 从主源下载成功"
return 0
fi
if [ -n "$fallback_url" ]; then
if curl -L -o "$output_file" "$fallback_url" --connect-timeout 30 --retry 3 -# 2>&1; then
log_success "使用 curl 从备用源下载成功"
return 0
fi
fi
return 1
}
# ============================================================================
# 第四部分:升级系统 SQLite
# ============================================================================
upgrade_sqlite() {
# 检查是否已完成(通过验证 SQLite 版本判断)
if [ -f /usr/local/bin/sqlite3 ]; then
INSTALLED_VERSION=$(/usr/local/bin/sqlite3 --version 2>/dev/null | awk '{print $1}')
if [ "$INSTALLED_VERSION" = "3.42.0" ]; then
if [ "$(get_state)" -ge 4 ]; then
log_step_header "升级系统 SQLite 到 3.42.0"
log_skip "SQLite 3.42.0 已安装"
show_elapsed "$SCRIPT_START_TIME"
return
fi
fi
fi
if [ "$(get_state)" -ge 4 ]; then
log_warn "状态文件异常,重新执行 SQLite 升级"
set_state "3"
fi
log_step_header "升级系统 SQLite 到 3.42.0"
local SQLITE_VERSION="3420000"
local SQLITE_DIR="/tmp/sqlite-autoconf-${SQLITE_VERSION}"
local SQLITE_TAR="sqlite-autoconf-${SQLITE_VERSION}.tar.gz"
# 主源和备用源
local PRIMARY_URL="https://www.sqlite.org/2023/${SQLITE_TAR}"
local FALLBACK_URL="https://gitee.com/suifenglzy/test/raw/master/${SQLITE_TAR}"
cd /tmp
# 验证已有的 tar 包是否完整
if [ -f "$SQLITE_TAR" ]; then
if tar -tzf "$SQLITE_TAR" > /dev/null 2>&1; then
log_substep "SQLite 源码包已存在且有效"
log_success "跳过下载"
else
log_warn "SQLite 源码包损坏,重新下载..."
rm -f "$SQLITE_TAR"
fi
fi
# 下载
if [ ! -f "$SQLITE_TAR" ]; then
if ! download_with_fallback "$PRIMARY_URL" "$FALLBACK_URL" "$SQLITE_TAR" "SQLite 3.42.0"; then
echo ""
echo -e " ${RED}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e " ${RED} 所有下载方式均失败!${NC}"
echo -e " ${RED}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo ""
echo -e " 请手动执行以下命令:"
echo -e " ${YELLOW}cd /tmp${NC}"
echo -e " ${YELLOW}wget ${PRIMARY_URL}${NC}"
echo -e " 或"
echo -e " ${YELLOW}curl -L -o ${SQLITE_TAR} ${FALLBACK_URL}${NC}"
echo -e " 然后重新运行本脚本"
echo ""
log_error "SQLite 源码下载失败"
fi
fi
# 解压
log_substep "解压 SQLite 源码..."
if [ -d "$SQLITE_DIR" ]; then
rm -rf "$SQLITE_DIR"
fi
tar -xzf "$SQLITE_TAR"
cd "$SQLITE_DIR"
log_success "解压完成"
# 配置
log_substep "配置编译选项..."
./configure --prefix=/usr/local > /dev/null 2>&1
log_success "配置完成"
# 编译
log_substep "编译 SQLite(使用 $(nproc) 个核心)..."
local cpu_cores=$(nproc)
make -j ${cpu_cores} > /dev/null 2>&1 &
spinner $!
log_success "编译完成"
# 安装
log_substep "安装 SQLite..."
make install > /dev/null 2>&1
log_success "安装完成"
# 替换系统版本
log_substep "替换系统旧版 SQLite..."
mv /usr/bin/sqlite3 /usr/bin/sqlite3.old 2>/dev/null || true
ln -sf /usr/local/bin/sqlite3 /usr/bin/sqlite3
echo "/usr/local/lib" > /etc/ld.so.conf.d/sqlite3.conf
ldconfig > /dev/null 2>&1
log_success "替换完成"
# 验证
SQLITE_VER=$(sqlite3 --version 2>/dev/null | awk '{print $1}')
log_substep "已安装 SQLite 版本:${BOLD}${SQLITE_VER}${NC}"
log_success "SQLite 升级完成"
set_state "4"
show_elapsed "$SCRIPT_START_TIME"
}
# ============================================================================
# 第五部分:编译安装 Python 3.11
# ============================================================================
compile_python() {
# 检查是否已完成
if [ "$(get_state)" -ge 5 ]; then
if [ -f /usr/local/python311/bin/python3.11 ]; then
log_step_header "编译安装 Python 3.11.9"
log_skip "Python 3.11.9 已编译安装"
show_elapsed "$SCRIPT_START_TIME"
return
else
log_warn "状态文件异常,重新执行 Python 编译"
set_state "4"
fi
fi
log_step_header "编译安装 Python 3.11.9"
local PYTHON_VERSION="3.11.9"
local PYTHON_PREFIX="/usr/local/python311"
local SOURCE_DIR="/tmp/Python-${PYTHON_VERSION}"
local PYTHON_TAR="Python-${PYTHON_VERSION}.tgz"
local PYTHON_URL="https://www.python.org/ftp/python/${PYTHON_VERSION}/${PYTHON_TAR}"
cd /tmp
# 验证已有的 tar 包
if [ -f "$PYTHON_TAR" ]; then
if tar -tzf "$PYTHON_TAR" > /dev/null 2>&1; then
log_substep "Python 源码包已存在且有效"
log_success "跳过下载"
else
log_warn "Python 源码包损坏,重新下载..."
rm -f "$PYTHON_TAR"
fi
fi
# 下载
if [ ! -f "$PYTHON_TAR" ]; then
log_substep "下载 Python ${PYTHON_VERSION} 源码..."
echo -e " ${CYAN} →${NC} URL:${PYTHON_URL}"
# 尝试 wget 下载
if wget_download "$PYTHON_URL" "$PYTHON_TAR" "Python ${PYTHON_VERSION}" 120 5; then
log_success "下载完成"
else
# 尝试 curl 下载
log_warn "wget 下载失败,尝试使用 curl..."
if curl -L -o "$PYTHON_TAR" "$PYTHON_URL" --connect-timeout 60 --retry 5 -# 2>&1; then
log_success "下载完成"
else
log_fail "下载失败"
echo ""
echo -e " 请手动下载并放置在 /tmp/:"
echo -e " ${YELLOW}cd /tmp && curl -L -o ${PYTHON_TAR} ${PYTHON_URL}${NC}"
echo ""
log_error "Python 源码下载失败"
fi
fi
fi
# 清理旧目录
if [ -d "$SOURCE_DIR" ]; then
log_substep "清理旧的源码目录..."
rm -rf "$SOURCE_DIR"
log_success "清理完成"
fi
# 解压
log_substep "解压 Python 源码..."
tar -xzf "$PYTHON_TAR"
cd "$SOURCE_DIR"
log_success "解压完成"
# 设置环境变量
log_substep "配置编译环境变量..."
export CFLAGS="$(pkg-config --cflags openssl11) -I/usr/local/include"
export LDFLAGS="$(pkg-config --libs openssl11) -L/usr/local/lib"
export LD_RUN_PATH="/usr/local/lib"
echo -e " ${CYAN} →${NC} CFLAGS: ${CFLAGS}"
echo -e " ${CYAN} →${NC} LDFLAGS: ${LDFLAGS}"
echo -e " ${CYAN} →${NC} LD_RUN_PATH: ${LD_RUN_PATH}"
log_success "环境变量配置完成"
# 配置
log_substep "运行 ./configure(检测依赖和配置编译选项)..."
echo -e " ${CYAN} →${NC} 安装路径: ${PYTHON_PREFIX}"
echo -e " ${CYAN} →${NC} 启用可加载 SQLite 扩展"
echo -e " ${CYAN} →${NC} 不启用 PGO 优化(兼容 GCC 4.8.5)"
./configure \
--prefix="${PYTHON_PREFIX}" \
--enable-loadable-sqlite-extensions > /dev/null 2>&1 &
spinner $!
log_success "配置完成"
# 编译(这是最耗时的步骤)
local cpu_cores=$(nproc)
echo ""
echo -e " ${YELLOW}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e " ${BOLD}开始编译 Python ${PYTHON_VERSION}${NC}"
echo -e " ${CYAN} →${NC} 使用 ${BOLD}${cpu_cores}${NC} 个 CPU 核心并行编译"
echo -e " ${CYAN} →${NC} 预计耗时:5-15 分钟(取决于 CPU 性能)"
echo -e " ${CYAN} →${NC} 可随时按 Ctrl+C 中断,下次运行将从此继续"
echo -e " ${YELLOW}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo ""
local compile_start=$(date +%s)
# 显示实时编译输出
if make -j ${cpu_cores} 2>&1 | while IFS= read -r line; do
printf "\r ${CYAN}[编译中]${NC} %-65s" "${line:0:65}"
done; then
local compile_end=$(date +%s)
local compile_elapsed=$((compile_end - compile_start))
echo ""
log_success "编译完成"
echo -e " ${MAGENTA}⏱ 编译耗时:${compile_elapsed}秒${NC}"
else
echo ""
log_fail "编译失败!"
log_error "请查看上方错误信息,修复后重新运行脚本(会自动从本步骤继续)"
fi
# 安装
log_substep "安装 Python ${PYTHON_VERSION}..."
make altinstall > /dev/null 2>&1 &
spinner $!
log_success "安装完成"
cd /tmp
set_state "5"
show_elapsed "$SCRIPT_START_TIME"
}
# ============================================================================
# 第六部分:创建软链接
# ============================================================================
create_links() {
if [ "$(get_state)" -ge 6 ]; then
log_step_header "创建软链接"
log_skip "软链接已创建"
show_elapsed "$SCRIPT_START_TIME"
return
fi
log_step_header "创建软链接"
log_substep "创建 python3.11 软链接..."
ln -sf /usr/local/python311/bin/python3.11 /usr/bin/python3.11
log_success "/usr/bin/python3.11 → /usr/local/python311/bin/python3.11"
log_substep "创建 pip3.11 软链接..."
ln -sf /usr/local/python311/bin/pip3.11 /usr/bin/pip3.11
log_success "/usr/bin/pip3.11 → /usr/local/python311/bin/pip3.11"
set_state "6"
show_elapsed "$SCRIPT_START_TIME"
}
# ============================================================================
# 第七部分:验证安装
# ============================================================================
verify_installation() {
if [ "$(get_state)" -ge 7 ]; then
log_step_header "验证安装"
log_skip "已验证"
show_elapsed "$SCRIPT_START_TIME"
return
fi
log_step_header "验证安装"
echo ""
echo -e " ${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e " ${BOLD} 执行完整验证${NC}"
echo -e " ${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
local all_ok=true
# 验证 Python
echo ""
echo -e " ${CYAN}[1/5]${NC} 检查 Python 版本..."
PYTHON_VER=$(python3.11 --version 2>&1)
if [ $? -eq 0 ]; then
log_success "Python: ${BOLD}${PYTHON_VER}${NC}"
else
log_fail "Python 安装失败"
all_ok=false
fi
# 验证 pip
echo -e " ${CYAN}[2/5]${NC} 检查 pip 版本..."
PIP_VER=$(pip3.11 --version 2>&1)
if [ $? -eq 0 ]; then
log_success "pip: ${BOLD}${PIP_VER}${NC}"
else
log_fail "pip 安装失败"
all_ok=false
fi
# 验证 SSL
echo -e " ${CYAN}[3/5]${NC} 检查 SSL 模块..."
SSL_VER=$(python3.11 -c "import ssl; print(ssl.OPENSSL_VERSION)" 2>&1)
if [ $? -eq 0 ]; then
log_success "SSL: ${BOLD}${SSL_VER}${NC}"
else
log_fail "SSL 模块异常"
all_ok=false
fi
# 验证 SQLite
echo -e " ${CYAN}[4/5]${NC} 检查 SQLite 版本..."
SQLITE_VER=$(python3.11 -c "import sqlite3; print(sqlite3.sqlite_version)" 2>&1)
if [ $? -eq 0 ]; then
log_success "SQLite: ${BOLD}${SQLITE_VER}${NC}"
SQLITE_MAJOR=$(echo "$SQLITE_VER" | cut -d. -f1)
SQLITE_MINOR=$(echo "$SQLITE_VER" | cut -d. -f2)
if [ "$SQLITE_MAJOR" -gt 3 ] || ([ "$SQLITE_MAJOR" -eq 3 ] && [ "$SQLITE_MINOR" -ge 8 ]); then
log_success "SQLite 版本满足 Django 要求(≥ 3.8.3) ✅"
else
log_fail "SQLite 版本过低!当前 ${SQLITE_VER},需要 ≥ 3.8.3"
all_ok=false
fi
else
log_fail "SQLite 模块异常"
all_ok=false
fi
# 验证其他模块
echo -e " ${CYAN}[5/5]${NC} 检查其他核心模块(lzma, uuid, bz2)..."
OTHER_MODULES=$(python3.11 -c "import lzma, uuid, bz2; print('OK')" 2>&1)
if [ $? -eq 0 ]; then
log_success "核心模块全部正常 ✅"
else
log_warn "部分模块缺失:${OTHER_MODULES}"
log_warn "不影响基本使用,但建议安装对应的 devel 包后重新编译"
fi
echo ""
if [ "$all_ok" = true ]; then
echo -e " ${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e " ${GREEN} ✅ 所有验证通过${NC}"
echo -e " ${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
set_state "7"
else
echo -e " ${RED}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e " ${RED} ❌ 验证未通过,请检查失败项${NC}"
echo -e " ${RED}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
log_error "安装验证失败,请修复后重新运行脚本"
fi
show_elapsed "$SCRIPT_START_TIME"
}
# ============================================================================
# 第八部分:配置 pip 镜像源
# ============================================================================
configure_pip_mirror() {
if [ "$(get_state)" -ge 8 ]; then
log_step_header "配置 pip 华为云镜像源"
log_skip "pip 镜像源已配置"
show_elapsed "$SCRIPT_START_TIME"
return
fi
log_step_header "配置 pip 华为云镜像源"
log_substep "设置 pip 镜像源为华为云..."
pip3.11 config set global.index-url https://repo.huaweicloud.com/repository/pypi/simple > /dev/null 2>&1
log_success "镜像源配置完成"
echo ""
echo -e " ${BOLD}当前 pip 配置:${NC}"
pip3.11 config list 2>/dev/null | while read line; do echo -e " ${CYAN} →${NC} ${line}"
done
set_state "8"
show_elapsed "$SCRIPT_START_TIME"
}
# ============================================================================
# 第九部分:清理临时文件
# ============================================================================
cleanup() {
if [ "$(get_state)" -ge 9 ]; then
log_step_header "清理临时文件"
log_skip "已清理"
show_elapsed "$SCRIPT_START_TIME"
return
fi
log_step_header "清理临时文件"
log_substep "清理 Python 源码和编译目录..."
if [ -d "/tmp/Python-3.11.9" ]; then
rm -rf /tmp/Python-3.11.9
log_success "已删除 /tmp/Python-3.11.9"
fi
if [ -f "/tmp/Python-3.11.9.tgz" ]; then
rm -f /tmp/Python-3.11.9.tgz
log_success "已删除 /tmp/Python-3.11.9.tgz"
fi
log_substep "清理 SQLite 源码和编译目录..."
if [ -d "/tmp/sqlite-autoconf-3420000" ]; then
rm -rf /tmp/sqlite-autoconf-3420000
log_success "已删除 /tmp/sqlite-autoconf-3420000"
fi
if [ -f "/tmp/sqlite-autoconf-3420000.tar.gz" ]; then
rm -f /tmp/sqlite-autoconf-3420000.tar.gz
log_success "已删除 /tmp/sqlite-autoconf-3420000.tar.gz"
fi
log_success "所有临时文件清理完成"
set_state "9"
show_elapsed "$SCRIPT_START_TIME"
}
# ============================================================================
# 完成提示
# ============================================================================
print_summary() {
local total_elapsed=$(( $(date +%s) - SCRIPT_START_TIME ))
local hours=$((total_elapsed / 3600))
local minutes=$(((total_elapsed % 3600) / 60))
local seconds=$((total_elapsed % 60))
echo ""
echo -e "${GREEN}╔══════════════════════════════════════════════════════════════════╗${NC}"
echo -e "${GREEN}║ ║${NC}"
echo -e "${GREEN}║${NC} ${BOLD}✅ Python 3.11.9 安装完成!${NC} ${GREEN}║${NC}"
echo -e "${GREEN}║ ║${NC}"
echo -e "${GREEN}╚══════════════════════════════════════════════════════════════════╝${NC}"
echo ""
echo -e "${BOLD}📦 安装信息:${NC}"
echo -e " ${CYAN}├─${NC} Python 路径:${BOLD}/usr/local/python311${NC}"
echo -e " ${CYAN}├─${NC} Python 命令:${BOLD}python3.11${NC}"
echo -e " ${CYAN}├─${NC} pip 命令:${BOLD}pip3.11${NC}"
echo -e " ${CYAN}├─${NC} pip 镜像源:${BOLD}华为云${NC}"
echo -e " ${CYAN}└─${NC} 总耗时:${BOLD}${hours}时${minutes}分${seconds}秒${NC}"
echo ""
echo -e "${BOLD}📝 使用示例:${NC}"
echo -e " ${CYAN}├─${NC} 查看版本:${BOLD}python3.11 --version${NC}"
echo -e " ${CYAN}├─${NC} 安装包:${BOLD}pip3.11 install <package>${NC}"
echo -e " ${CYAN}├─${NC} 创建虚拟环境:${BOLD}python3.11 -m venv myenv${NC}"
echo -e " ${CYAN}└─${NC} 激活虚拟环境:${BOLD}source myenv/bin/activate${NC}"
echo ""
echo -e "${YELLOW}⚠ ${BOLD}重要提醒:${NC}${YELLOW}"
echo -e "${YELLOW} ├─ 切勿使用 python 或 pip 命令(会调用系统 Python 2.7)${NC}"
echo -e "${YELLOW} ├─ 请始终使用 python3.11 和 pip3.11${NC}"
echo -e "${YELLOW} └─ 建议在虚拟环境中安装第三方包${NC}"
echo ""
echo -e "${GREEN}══════════════════════════════════════════════════════════════════${NC}"
echo ""
# 安装完成,清除状态文件
clear_state
}
# ============================================================================
# 询问用户是否继续上次进度
# ============================================================================
ask_resume() {
local state=$(get_state)
if [ "$state" = "0" ] || [ "$state" = "0.5" ]; then
return
fi
echo ""
echo -e "${YELLOW}╔══════════════════════════════════════════════════════════════════╗${NC}"
echo -e "${YELLOW}║ ║${NC}"
echo -e "${YELLOW}║${NC} ${BOLD}检测到上次安装进度${NC} ${YELLOW}║${NC}"
echo -e "${YELLOW}║ ║${NC}"
echo -e "${YELLOW}║${NC} 上次已完成步骤:${BOLD}$state / $TOTAL_STEPS${NC} ${YELLOW}║${NC}"
echo -e "${YELLOW}║ ║${NC}"
echo -e "${YELLOW}║${NC} ${CYAN}[1]${NC} 从上次中断处继续(推荐) ${YELLOW}║${NC}"
echo -e "${YELLOW}║${NC} ${CYAN}[2]${NC} 重新开始(清除所有进度) ${YELLOW}║${NC}"
echo -e "${YELLOW}║${NC} ${CYAN}[q]${NC} 退出安装 ${YELLOW}║${NC}"
echo -e "${YELLOW}║ ║${NC}"
echo -e "${YELLOW}╚══════════════════════════════════════════════════════════════════╝${NC}"
echo ""
while true; do
read -p "请输入选择 [1/2/q](默认 1): " choice
choice=${choice:-1}
case $choice in
1)
echo ""
echo -e "${GREEN}从上次中断处继续安装...${NC}"
echo ""
case $state in
1) set_state "0"; log_info "将重新配置 EPEL 源";;
2) set_state "1"; log_info "将重新安装编译依赖";;
3) set_state "2"; log_info "将重新升级 SQLite";;
4) set_state "3"; log_info "将重新编译 Python";;
# 5~8 保留状态,直接跳过
esac
return
;;
2)
echo ""
echo -e "${YELLOW}清除所有进度,重新开始...${NC}"
clear_state
echo ""
return
;;
q|Q)
echo ""
echo -e "${CYAN}安装已取消${NC}"
exit 0
;;
*)
echo -e "${RED}无效输入,请输入 1、2 或 q${NC}"
;;
esac
done
}
# ============================================================================
# 主函数
# ============================================================================
main() {
# 检测 wget 版本
detect_wget
# 清屏
clear
echo ""
echo -e "${BLUE}╔══════════════════════════════════════════════════════════════════╗${NC}"
echo -e "${BLUE}║ ║${NC}"
echo -e "${BLUE}║${NC} ${BOLD}CentOS 7 自动安装 Python 3.11.9${NC} ${BLUE}║${NC}"
echo -e "${BLUE}║${NC} ${CYAN}版本:2026-04-25${NC} ${BLUE}║${NC}"
echo -e "${BLUE}║${NC} ${CYAN}特性:进度显示 · 断点续传 · 国内备用源 · 三重下载保障${NC} ${BLUE}║${NC}"
echo -e "${BLUE}║ ║${NC}"
echo -e "${BLUE}╚══════════════════════════════════════════════════════════════════╝${NC}"
echo ""
# 询问是否继续上次进度
ask_resume
echo -e "${BOLD}本脚本将执行以下操作:${NC}"
echo -e " ${CYAN}[1]${NC} 检查运行权限和网络连接"
echo -e " ${CYAN}[2]${NC} 更换阿里云 Yum 源"
echo -e " ${CYAN}[3]${NC} 配置阿里云 EPEL 源"
echo -e " ${CYAN}[4]${NC} 安装编译依赖"
echo -e " ${CYAN}[5]${NC} 升级系统 SQLite 到 3.42.0"
echo -e " ${CYAN}[6]${NC} 编译安装 Python 3.11.9"
echo -e " ${CYAN}[7]${NC} 创建软链接"
echo -e " ${CYAN}[8]${NC} 验证安装"
echo -e " ${CYAN}[9]${NC} 配置 pip 镜像源并清理"
echo ""
local state=$(get_state)
if [ "$state" != "0" ] && [ "$state" != "0.5" ]; then
echo -e "${GREEN}将从步骤 $state 之后继续执行${NC}"
echo ""
else
echo -e "${YELLOW}预计总耗时:10-30 分钟${NC}"
echo ""
fi
read -p "按回车键开始安装,或按 Ctrl+C 取消..."
# 根据状态跳过已完成的步骤
local current_state=$(get_state)
if [ "$current_state" = "0" ] || [ "$current_state" = "0.5" ]; then
check_root
check_network
fi
replace_yum_repo
configure_epel
install_dependencies
upgrade_sqlite
compile_python
create_links
verify_installation
configure_pip_mirror
cleanup
# 最终进度条 100%
echo ""
if [ -t 1 ]; then
show_progress "$TOTAL_STEPS" "$TOTAL_STEPS"
fi
echo ""
# 打印完成摘要
print_summary
}
# 捕获中断信号
trap 'echo -e "\n\n${YELLOW}安装已中断,进度已保存${NC}"; echo -e "${YELLOW}下次运行脚本可选择从断点继续${NC}"; exit 1' INT
# 执行主函数
main "$@"