Linux 程序安装 | 旧版安装及多版本并存

注:本文为 "Linux 旧版程序安装及多版本并存" 相关合辑。

英文引文,机翻未校。

中文引文,略作重排。

如有内容异常,请看原文。


1 概述

1.1 应用场景

在新版 Linux 系统环境中,时常需要部署仅兼容旧版本系统的专用程序,同时可能存在同一程序多版本协同运行的需求。本指南聚焦两大关键目标:其一,在不修改系统主源配置文件(/etc/apt/sources.list)的前提下,实现老版本程序的自动化安装与依赖适配;其二,通过隔离机制实现程序多版本无冲突共存,保障系统现有组件的运行稳定性。

1.2 原则

  • 配置隔离原则:规避对系统主源配置的修改,防止配置环境受到污染;

  • 依赖自动化适配:实现程序及其依赖组件的自动匹配、下载与安装流程,最大限度减少人工干预;

  • 环境隔离原则:通过路径隔离、容器虚拟化等技术手段,实现多版本程序在文件系统、配置参数及依赖环境层面的隔离,杜绝版本冲突。

2 前置准备:旧软件源可用性测试(不更新 apt 状态)

当需从老版本软件源获取程序时,需预先验证旧源的可用性,且严禁执行 sudo apt update 命令更新系统 apt 缓存状态。通过"网络连通性-端口可达性-资源存在性"三层测试体系,实现旧源可用性的精准校验。

2.1 第一步:基础网络连通性测试

验证本地主机与旧源服务器之间的网络连通状态,为后续测试环节奠定基础。

2.1.1 测试工具

ping 命令

2.1.2 操作步骤

以旧源 old-releases.ubuntu.com 为例,发送4个数据包执行测试,以避免持续占用网络资源:

bash 复制代码
## 网络连通性测试命令
ping -c 4 old-releases.ubuntu.com
2.1.3 结果判断
  • 可用标识:输出信息中出现"64 bytes from ...",且数据包丢失率(packet loss)≤10%;

  • 不可用标识:输出"Destination Host Unreachable"信息或数据包丢失率达100%;

  • 补充说明:部分服务器可能禁用 ICMP 协议,此时 ping 测试失败不代表旧源不可用,需继续执行后续测试环节。

2.2 第二步:端口可达性测试

apt 软件源基于 HTTP/HTTPS 协议提供服务,默认使用端口为80(HTTP)和443(HTTPS),需对这两个端口的开放状态进行验证。

2.2.1 测试方法 1:telnet 工具
bash 复制代码
## 测试 80 端口
telnet old-releases.ubuntu.com 80
## 测试 443 端口
telnet old-releases.ubuntu.com 443

结果判断:输出"Connected to old-releases.ubuntu.com"表示端口处于开放状态;输出"Connection refused"或"Timeout"表示端口不可用。完成测试后,按 Ctrl + ] 组合键,输入 quit 命令退出。

2.2.2 测试方法 2:nc(netcat)工具(推荐方案)

通过 -z 参数仅执行端口连通性检测,不发送实际数据,操作流程更为简洁:

bash 复制代码
## 测试 80 端口
nc -zv old-releases.ubuntu.com 80
## 测试 443 端口
nc -zv old-releases.ubuntu.com 443

结果判断:输出"succeeded!"表示端口开放;输出"failed!"表示端口不可用。

2.3 第三步:资源存在性测试(校验环节)

验证旧源中是否存在与当前系统版本对应的软件包目录,确保旧源可提供实际可用的软件资源。

2.3.1 测试工具

curlwget 命令

2.3.2 原理

Ubuntu 软件源采用固定目录结构,格式为 https://<源地址>/ubuntu/dists/<系统版本代号>/,仅需验证该目录的可访问性即可完成校验。可通过以下命令获取当前系统版本代号(例如 Ubuntu 20.04 版本代号为 focal):

bash 复制代码
lsb_release -c
2.3.3 操作步骤
  1. 构造测试 URL:替换源地址与系统版本代号,示例 URL 为 https://old-releases.ubuntu.com/ubuntu/dists/focal/

  2. 执行测试命令:

    bash 复制代码
    ## 方法 1:curl 仅获取响应头信息
    curl -I https://old-releases.ubuntu.com/ubuntu/dists/focal/
    ## 方法 2:wget 蜘蛛模式(仅检测资源存在性)
    wget --spider https://old-releases.ubuntu.com/ubuntu/dists/focal/
2.3.4 结果判断
  • 可用标识:curl 命令返回 200 OK 响应码,wget 输出"Remote file exists"信息;

  • 不可用标识:curl 命令返回 404 Not Found 或 503 Service Unavailable 响应码,wget 输出"Remote file does not exist"信息。

2.4 测试流程总结

  1. 优先执行 ping 测试,初步校验网络连通性;

  2. 通过 nc 工具测试 80 与 443 端口,验证服务端口开放状态;

  3. 最终执行资源存在性测试,精准验证旧源是否可提供适配当前系统版本的软件资源;

  4. 仅当第三层测试通过时,方可判定旧源对当前系统具备实际可用性。

3 老版本程序自动化安装方法(不修改主源配置)

根据是否具备本地预编译包,将安装方法划分为"本地 DEB 包安装""老版本源独立配置安装""源码编译安装"三类,按操作复杂度从低到高排序。

3.1 方法 1:本地 DEB 包自动化安装(无需配置额外软件源)

无需配置任何额外软件源,直接依托本地 DEB 包完成程序部署,系统将自动处理依赖关系,适用于无可用老版本源的场景。

3.1.1 apt 工具直接安装
3.1.1.1 工作原理

apt 工具支持直接安装本地 DEB 包,可自动解析包内依赖清单,从系统默认源下载并安装缺失的依赖组件,实现一站式完整部署。

3.1.1.2 操作步骤
  1. 定位本地 DEB 包路径,执行安装命令(需添加 ./ 标识当前目录,避免 apt 工具从软件源中查找同名程序):

    bash 复制代码
    # 相对路径安装示例
    apt install ./xxx_1.2.3_amd64.deb
    # 绝对路径安装示例
    apt install /home/user/Downloads/xxx_1.2.3_amd64.deb
  2. 验证程序安装结果:

    bash 复制代码
    xxx --version
3.1.1.3 技术优势
  • 操作流程简洁高效,无需额外安装辅助工具;

  • 依托系统默认软件源,无配置污染风险;

  • 可自动适配老版本 DEB 包的依赖需求。

3.1.2 gdebi 工具安装(依赖解析)
3.1.2.1 工作原理

gdebi 是一款轻量化本地 DEB 包安装工具,专注于依赖解析与程序部署,无冗余操作流程,依赖匹配精度高于通用 apt 工具。

3.1.2.2 操作步骤
  1. 安装 gdebi 工具:

    bash 复制代码
    apt install gdebi-core -y
  2. 安装本地 DEB 包:

    bash 复制代码
    # 交互式安装(需输入 y 确认操作)
    gdebi ./xxx_1.2.3_amd64.deb
    # 非交互式安装(适用于自动化脚本场景)
    gdebi -n ./xxx_1.2.3_amd64.deb
  3. 验证程序安装结果:

    bash 复制代码
    xxx --version
3.1.2.3 技术优势
  • 依赖解析精度高,可识别 apt 工具忽略的隐性依赖;

  • 工具轻量化,运行效率高;

  • 支持非交互式运行模式,便于集成至自动化脚本。

3.2 方法 2:老版本源独立配置安装(需旧源具备可用性)

将老版本源配置文件存放于独立目录(/etc/apt/sources.list.d),不修改系统主源文件;通过优先级配置避免老版本包覆盖系统现有组件,实现程序及依赖组件的自动匹配与安装。

3.2.1 操作步骤
  1. 创建独立源配置文件:

    bash 复制代码
    touch /etc/apt/sources.list.d/old_release.list
  2. 编辑老版本源信息(以 Ubuntu 16.04 Xenial 版本为例):

    bash 复制代码
    nano /etc/apt/sources.list.d/old_release.list

    写入以下配置内容:

    bash 复制代码
    # 老版本 Ubuntu 16.04 软件源
    deb http://old-releases.ubuntu.com/ubuntu/ xenial main restricted universe multiverse
  3. 配置源优先级(防止与系统组件发生冲突):

    bash 复制代码
    nano /etc/apt/preferences.d/old_release.pref

    写入优先级规则(将老版本源优先级设置为 100,低于系统默认源优先级):

    bash 复制代码
    Package: *
    Pin: release n=xenial
    Pin-Priority: 100
  4. 自动安装老版本程序:

    bash 复制代码
    # 更新 apt 缓存(仅更新新增的老版本源缓存)
    apt update
    # 指定版本安装
    apt install xxx=1.2.3 -y
    # 或指定发行版代号安装
    apt install -t xenial xxx -y
  5. 验证程序安装结果:

    bash 复制代码
    xxx --version
3.2.2 后续清理(可选操作)

当不再需要老版本程序时,可删除对应配置文件以恢复系统默认状态:

bash 复制代码
rm /etc/apt/sources.list.d/old_release.list
rm /etc/apt/preferences.d/old_release.pref
apt update
3.2.3 技术优势
  • 老版本源与系统主源实现隔离,便于管理与清理;

  • 通过优先级配置保障系统现有组件的运行稳定性;

  • apt 工具自动完成版本与依赖匹配,无需人工手动查找。

3.3 方法 3:源码编译半自动化安装(无预编译包场景)

适用于无预编译 DEB 包的小众或老旧程序,通过 apt build-dep 工具自动获取编译依赖组件,实现半自动化编译与安装流程。

3.3.1 操作步骤
  1. 安装基础编译工具:

    bash 复制代码
    apt install build-essential cmake autoconf libtool pkg-config -y
  2. 自动获取编译依赖(需目标程序在已配置软件源中有记录):

    bash 复制代码
    apt build-dep xxx -y
  3. 下载并解压老版本源码包:

    bash 复制代码
    wget https://xxx.org/releases/xxx-1.2.3.tar.gz 
    tar -zxvf xxx-1.2.3.tar.gz
    cd xxx-1.2.3
  4. 编译并安装程序(可通过 --prefix 参数指定安装路径):

    bash 复制代码
    ## 配置编译参数
    ./configure --prefix=/usr/local/xxx
    ## 编译(-j 后跟随 CPU 数以提升编译效率)
    make -j4
    ## 安装程序
    make install
  5. 配置环境变量(可选操作,指定自定义安装路径时需执行):

    bash 复制代码
    nano /etc/profile
    ## 添加路径信息
    export PATH=/usr/local/xxx/bin:$PATH
    ## 使配置生效
    source /etc/profile
  6. 验证程序安装结果:

    bash 复制代码
    xxx --version
3.3.2 技术优势
  • 适用于无预编译包的老旧程序场景;

  • apt build-dep 工具大幅降低人工查找依赖组件的工作量;

  • 支持自定义安装路径,可实现程序与系统文件的隔离存储。

4 进阶应用:应用程序多版本并存实现方案

基于"安装路径隔离、配置文件隔离、依赖环境隔离"三大维度,提供四种实现方案,按操作复杂度从低到高排序。

4.1 方法 1:源码编译安装(指定独立路径)

适用于大多数开源软件,通过手动指定不同安装路径实现版本隔离,属于通用性解决方案。

4.1.1 操作步骤(以 nginx 1.20.0 和 1.24.0 版本为例)
  1. 安装基础编译依赖:

    bash 复制代码
    sudo apt install build-essential gcc g++ make
  2. 下载并解压不同版本源码包:

    bash 复制代码
    ## 解压 1.20.0 版本至 ~/nginx-1.20.0 目录
    tar -zxvf nginx-1.20.0.tar.gz -C ~/
    ## 解压 1.24.0 版本至 ~/nginx-1.24.0 目录
    tar -zxvf nginx-1.24.0.tar.gz -C ~/
  3. 指定独立路径编译安装:

    bash 复制代码
    ## 安装 nginx 1.20.0 至 /usr/local/nginx-1.20.0 目录
    cd ~/nginx-1.20.0
    ./configure --prefix=/usr/local/nginx-1.20.0
    make && sudo make install
    
    ## 安装 nginx 1.24.0 至 /usr/local/nginx-1.24.0 目录
    cd ~/nginx-1.24.0
    ./configure --prefix=/usr/local/nginx-1.24.0
    make && sudo make install
  4. 通过绝对路径或差异化软链接调用对应版本:

    bash 复制代码
    ## 直接通过绝对路径启动程序
    /usr/local/nginx-1.20.0/sbin/nginx
    /usr/local/nginx-1.24.0/sbin/nginx
    
    ## 创建差异化软链接(可选操作)
    sudo ln -s /usr/local/nginx-1.20.0/sbin/nginx /usr/local/bin/nginx120
    sudo ln -s /usr/local/nginx-1.24.0/sbin/nginx /usr/local/bin/nginx124
    ## 通过软链接调用程序
    nginx120 -v
    nginx124 -v
4.1.2 技术优势与适用场景
  • 技术优势:通用性强,隔离效果彻底,不影响系统现有运行状态;

  • 适用场景:无专属版本管理工具的开源软件、需自定义编译参数的应用场景。

4.2 方法 2:容器化部署(Docker/Podman,隔离级别最高)

为每个程序版本创建独立的"沙箱"运行环境,包含专属文件系统、依赖组件及配置参数,与主机环境完全隔离,是实现无冲突共存的最优方案。

4.2.1 操作步骤(以 Docker 部署 MySQL 5.7 和 8.0 版本为例)
  1. 安装 Docker 运行环境:

    bash 复制代码
    sudo apt install docker.io
    sudo systemctl start docker
    sudo systemctl enable docker
  2. 拉取不同版本镜像:

    bash 复制代码
    ## 拉取 MySQL 5.7 版本镜像
    sudo docker pull mysql:5.7
    ## 拉取 MySQL 8.0 版本镜像
    sudo docker pull mysql:8.0
  3. 启动独立容器(指定不同主机端口和数据挂载目录以避免冲突):

    bash 复制代码
    # 启动 MySQL 5.7 容器(主机端口 3306,数据挂载至 /mnt/mysql57 目录)
    sudo docker run -d --name mysql57 -p 3306:3306 -v /mnt/mysql57:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
    # 启动 MySQL 8.0 容器(主机端口 3307,数据挂载至 /mnt/mysql80 目录)
    sudo docker run -d --name mysql80 -p 3307:3306 -v /mnt/mysql80:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 mysql:8.0
  4. 访问对应版本程序:

    bash 复制代码
    # 进入 MySQL 5.7 容器
    sudo docker exec -it mysql57 bash
    # 进入 MySQL 8.0 容器
    sudo docker exec -it mysql80 bash
4.2.2 技术优势与适用场景
  • 技术优势:隔离级别最高,不影响主机运行环境,无需处理依赖冲突,版本切换操作便捷;

  • 适用场景:支持容器镜像的软件、依赖敏感型软件(如数据库、中间件)、需快速部署多版本的应用场景。

4.3 方法 3:专属版本管理工具

主流开发类软件通常提供专属版本管理工具,可实现多版本的一键安装与切换,自动完成隔离配置。

4.3.1 常用软件与版本管理工具对应表
软件类型 版本管理工具 适用场景
Python pyenv 实现 Python 2.x 与 3.x 多版本切换,隔离虚拟运行环境
Node.js nvm / n 管理 Node.js 不同版本,自动配置环境变量
Go gvm 部署 Go 多版本,隔离依赖组件与配置参数
Java jenv / sdkman 管理 JDK 不同版本(含 OpenJDK 与 Oracle JDK)
4.3.2 操作示例(基于 pyenv 管理 Python 多版本)
  1. 安装 pyenv 工具:

    bash 复制代码
    git clone https://github.com/pyenv/pyenv.git ~/.pyenv
    # 配置环境变量(确保永久生效)
    echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc
    echo 'command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc
    echo 'eval "$(pyenv init -)"' >> ~/.bashrc
    # 使配置参数生效
    source ~/.bashrc
  2. 安装多版本 Python:

    bash 复制代码
    pyenv install 3.8.18
    pyenv install 3.10.14
  3. 切换与验证版本:

    bash 复制代码
    # 查看已安装版本列表
    pyenv versions
    # 配置全局默认版本为 3.8.18
    pyenv global 3.8.18
    # 配置当前目录局部版本为 3.10.14
    pyenv local 3.10.14
    # 验证当前版本
    python --version
4.3.3 技术优势与适用场景
  • 技术优势:操作便捷性最优,支持一键安装与版本切换,自动处理路径配置与环境变量隔离;

  • 适用场景:开发类软件(如 Python、Node.js 等)、具备专属版本管理工具的软件。

4.4 方法 4:打包格式隔离(AppImage/Flatpak/Snap)

上述三种打包格式均属于"自包含"类型,内置完整依赖组件,无需依赖系统库文件,不同版本可直接实现并存运行。

4.4.1 操作示例(基于 AppImage 格式)
  1. 下载不同版本的 AppImage 包(以 VS Code 为例);

  2. 添加可执行权限:

    bash 复制代码
    chmod +x VSCode-1.80.0-x64.AppImage
    chmod +x VSCode-1.90.0-x64.AppImage
  3. 直接运行对应版本程序:

    bash 复制代码
    ./VSCode-1.80.0-x64.AppImage
    ./VSCode-1.90.0-x64.AppImage
4.4.2 技术优势与适用场景
  • 技术优势:无需执行安装流程,可直接运行,内置完整依赖组件,版本独立性强,不修改系统配置;

  • 适用场景:提供对应打包格式的软件、无需全局安装的桌面应用程序。

5 注意事项

  • 版本与架构匹配:下载 DEB 包或源码包时,需确保与系统架构(如 amd64 / i386)及老版本系统发行代号相匹配,避免安装失败;

  • 源优先级配置:使用老版本源时,必须配置优先级参数,防止老版本包覆盖系统组件;

  • 安全隔离要求:老版本程序可能存在安全漏洞,建议通过容器化方式实现隔离运行;

  • 依赖冲突处理:自动安装过程中出现依赖冲突时,可尝试卸载冲突的高版本依赖组件,或选择源码编译方式自定义依赖版本;

  • 环境变量管理:多版本程序应避免配置全局环境变量,优先通过绝对路径或差异化软链接调用;

  • 配置备份要求:对重要程序的不同版本配置文件执行单独备份,避免误操作导致配置覆盖。

6 方法选型总结

6.1 老版本程序安装方法选型

方法类型 适用场景 推荐优先级
apt 直接安装本地 DEB 包 具备本地 DEB 包,无可用老版本源 1
gdebi 安装本地 DEB 包 具备本地 DEB 包,需高精度依赖解析 2
老版本源独立配置安装 无本地 DEB 包,需从老版本源获取程序 3
源码编译半自动化安装 无预编译包,仅提供源码的老旧程序 4

6.2 多版本并存方法选型

实现方法 隔离强度 操作便捷性 适用场景
源码编译安装(指定路径) 无专属工具的开源软件、需自定义编译参数的场景
容器化部署 强(最优) 支持容器镜像的软件、依赖敏感型软件
专属版本管理工具 极高(最优) 开发类软件(Python/Node.js 等)
打包格式隔离 提供 AppImage/Flatpak/Snap 格式的桌面应用

via: