当前位置: 首页 > news >正文

Linux小课堂: 软件安装与源码编译实战之从 RPM 到源码构建的完整流程

Linux 发行版软件安装方式概览

在主流 Linux 系统中,尤其是 Red Hat 家族(如 CentOS、Fedora)发行版中,YUM(Yellowdog Updater, Modified)是核心的包管理工具。通过 yum install 命令即可轻松安装绝大多数已收录于官方仓库的软件,极大地简化了依赖管理和安装流程。

然而,并非所有软件都能通过 YUM 直接获取。一些较新、处于开发阶段或未广泛普及的程序往往未被纳入标准仓库。此时,传统的二进制安装和源码编译成为必要手段。

在 Linux 系统中,软件安装并非仅依赖单一方式。面对不同发行版和软件状态,用户需掌握多种安装策略以应对实际需求。总体而言,常见的软件获取与部署路径可分为三类:

  1. 通过包管理器从官方仓库安装(如 yum / dnf / apt
  2. 手动下载二进制包并转换格式安装(如 .deb.rpm 使用 alien
  3. 从源代码出发完成编译安装(适用于无预编译包的新项目)

当目标软件未被收录于当前系统的软件仓库时,前两种方法可能失效,此时必须回归最底层的方式——源码编译安装。该过程虽复杂,但能深度理解操作系统如何构建可执行程序,并提升对依赖管理、编译流程的认知

包管理器是首选:Yum 与软件仓库机制

绝大多数现代 Linux 发行版都提供了强大的包管理系统,使得用户无需手动处理依赖或编译过程即可完成软件安装。

对于 Red Hat 家族的系统(如 CentOS、Fedora),Yum 是默认的高级包管理工具。它不仅能安装 .rpm 包,还能自动解决依赖关系,极大简化了运维工作。

# 在 CentOS 中安装 htop
yum install -y htop# 在 Ubuntu 中安装 htop
apt install -y htop

该命令会自动查找 htop 软件及其所有依赖项(如 ncurses 开发库),并完成安装。这种方式高效、安全且可重复

这类命令的优势在于:

  • 自动解析并下载所需的所有依赖库
  • 验证签名确保安全性
  • 提供统一的升级与卸载机制

然而,并非所有软件都能通过这种方式获得。特别是处于开发阶段、小众或定制化的工具,往往不会进入官方仓库。此时,我们需转向其他手段

注意:Debian 系列(如 Ubuntu)则使用 apt.deb 包;二者机制相似但命令不同

然而,并非所有软件都能通过 yumapt 获取——有些新版本、实验性项目或未被收录的工具不在官方仓库中。此时需转向其他方法

跨平台安装包转换:RPM 与 DEB 的互转实践

当目标软件未提供适用于当前系统的安装包时,可尝试使用第三方工具进行格式转换
例如,在基于 Red Hat 的系统上需要安装 Debian 的 .deb 包时,可通过 Alien 工具实现跨包管理系统兼容

1 ) Alien 工具简介

  • Alien 是一个支持多种包格式相互转换的实用程序。
  • 支持格式包括:
    • .deb(Debian/Ubuntu)
    • .rpm(Red Hat/CentOS/Fedora)
    • .tgz(Slackware)
    • .pkg(Solaris)
    • .slp(Stampede)

注意:

  • alien 默认不预装于多数系统,需手动安装
  • 转换后的包可能无法完全适配原生环境,尤其在依赖库版本不一致或架构差异情况下易导致安装失败

2 )安装 Alien 并执行 DEB → RPM 转换

切换至 root 用户(或使用 sudo)
su -使用 YUM 安装 Alien
yum install -y alien 查看 alien 帮助文档 
man alien

实际操作示例:将搜狗输入法 DEB 包转换为 RPM

# 将下载的搜狗拼音输入法 .deb 文件拷贝到当前目录
cp /share/sogoupinyin_*.deb ./sogou.deb # 使用 alien 进行转换 
alien -r sogou.deb

成功后生成同名 .rpm 文件,如 sogou-xxxx.rpm

直接安装 RPM 包及其常见问题处理

完成转换后,使用 rpm 命令进行安装:

安装 RPM 包
rpm -ivh sogou-*.rpm 

但通常会遇到如下错误提示:

error: Failed dependencies:libQt5Core.so.5 is needed by sogou-xxx.x86_64

关键点解析:

  • RPM 不自动解析依赖项,仅检查是否存在所需库文件;
  • yumdnf 在安装 .rpm 时能自动下载并解决依赖关系;
  • 因此建议优先使用 yum localinstall 来安装本地 RPM 包:
yum localinstall -y sogou-*.rpm

此命令利用 Yum 的依赖解析引擎,先下载缺失库(如 Qt5、Fcitx 等),再完成安装
它会自动分析依赖并从网络仓库拉取缺失组件,显著提高成功率

提示:Alien 转换后的包可能存在兼容问题,建议优先寻找原生 .rpm

源码编译安装全流程详解 (终极手段)

当既无可用仓库包,也找不到合适二进制安装包时,必须回归“石器时代”——从源代码开始编译安装

1 ) 源码编译的本质

编译(Compilation) 是将高级语言书写的源代码(如 C/C++)翻译为机器可执行的二进制文件的过程。

简言之:编译的本质:源代码 → 可执行文件

类比比喻:

  • 源代码 ≈ 面粉、鸡蛋等原料
  • 编译器 ≈ 烤箱
  • 编译过程 ≈ 制作蛋糕的烘焙工序
  • 可执行程序 ≈ 成品蛋糕

Linux 上大多数开源项目均开放源码,允许用户根据自身硬件环境(CPU 架构、位数等)定制化构建。

标准编译安装五步法

以下是通用的从源码编译安装的标准流程:

步骤命令说明
1. 下载源码wget https://example.com/app.tar.gz获取压缩包
2. 解压源码tar -zxvf app.tar.gz && cd app-x.x.x展开项目目录
3. 配置构建环境./configure检查依赖、设置路径
4. 编译make执行编译动作
5. 安装sudo make install复制到系统路径

2 ) 编译安装通用步骤(以 htop 为例)

2.1 获取源码包

访问 htop 官网 下载最新版本源码压缩包:

wget https://github.com/htop-dev/htop/archive/refs/tags/3.2.0.tar.gz -O htop-3.2.0.tar.gz

2.2 解压源码包

tar -zxvf htop-3.2.0.tar.gz
cd htop-3.2.0

.tar.gz 是典型的 GNU 归档压缩格式,结合 targzip 实现高效打包

2.3 配置编译环境:运行 configure 脚本

./configure

此脚本作用包括:

  • 检测系统是否具备必要的编译工具链(gcc、make 等)
  • 检查依赖库是否存在(如 ncurses 开发库)
  • 生成适配当前系统的 Makefile 文件

若出现以下错误(可能在首次运行时):

configure: error: Unicode/UTF-8 support requested but not found.
You may want to use --disable-unicode or install libncursesw5-dev.

缺少宽字符支持库 ncursesw(即带 Unicode 支持的 ncurses)

2.4 安装编译依赖

yum install -y ncurses-devel
# 或
yum install -y ncurses-devel ncurses-base ncurses-term

ncurses-devel 提供头文件与静态库,是许多终端应用(top、htop、vim)编译所必需。

关键术语说明:

  • ncurses: 终端界面绘图库
  • ncurses-devel: 开发头文件和静态库,用于编译期链接
  • 若缺少此类开发包,即使运行时库存在也无法成功编译

重新运行配置脚本:

./configure --enable-unicode

确认输出末尾显示 “Configuration complete” 表示准备就绪
生成 Makefile 文件

2.5 执行编译:调用 make

make

make 命令读取 Makefile 中定义的规则,调用编译器(如 gcc)逐个编译 .c 文件并链接成最终可执行体。

编译过程中若报错,应仔细阅读错误信息定位缺失组件或语法问题。

2.6 安装程序:make install

sudo make install    # 需 root 权限

默认安装路径为 /usr/local/bin,确保其包含在 $PATH 环境变量中:

echo $PATH | grep /usr/local/bin
# 或 查看验证 
ls /usr/local/bin/htop

验证安装结果:

htop --version 

启动 htop:

htop

界面应正常渲染,支持彩色高亮与滚动交互,进程监控等功能均可用

补充知识:README 文件的重要性

几乎所有开源项目根目录下都有一个 READMEINSTALL 文本文件,其中包含:

  • 构建依赖清单
  • 配置选项说明(如 --enable-feature, --prefix=/opt/myapp
  • 编译示例
  • 故障排查指南

务必在编译前阅读这些文档,避免走弯路

使用 wget 下载与 RAR 工具部署

某些闭源或专有工具无法通过包管理器获取,只能手动下载预编译二进制文件并部署

使用 wget 下载远程资源

wget 是 Linux 下常用的命令行下载工具,支持 HTTP、HTTPS、FTP 协议

1 ) 使用 wget 自动化获取远程资源

wget 是强大的命令行下载工具,支持 HTTP(S)、FTP 协议,适合脚本化批量下载。

示例:从 rarlab 下载 RAR for Linux
wget https://www.rarlab.com/rar/rarlinux-x64-6.2.4.tar.gz

解压并进入目录:

tar -xzf rarlinux-x64-6.2.4.tar.gz
cd rar 

目录结构如下:

rar/
├── rar        # 可执行程序(已编译)
├── unrar      # 解压程序 
├── makefile   # 提供 install/uninstall 规则
└── license.txt

使用 Make 安装预编译二进制
虽然不是传统意义上的“编译”,但仍可通过 make 实现标准化安装

2 ) 部署预编译 RAR 工具

该目录下已提供编译好的二进制文件:

  • rar:用于创建 .rar 压缩包
  • unrar:用于解压 .rar 文件

通过内置 makefile 安装至系统路径:

sudo make

查看 makefile 内容:

install:install -m 755 rar /usr/local/bin/install -m 755 unrar /usr/local/bin/

INSTALL_DIR = /usr/local/bininstall:cp rar $(INSTALL_DIR)/rarcp unrar $(INSTALL_DIR)/unrar chmod 755 $(INSTALL_DIR)/rar $(INSTALL_DIR)/unrar

之后

sudo make install    # 需 root 权限

make install 执行后,两个命令即全局可用

为何需要makemake install

  • make的作用:读取源码包中的Makefile(由./configure生成),将源码编译为二进制可执行文件(如unrar)和库文件。若跳过make,系统不会自动生成这些可执行文件。
  • make install的作用:将编译后的文件(如unrar可执行文件、库文件)复制到系统预设的安装路径(如/usr/local/bin),使系统能够识别并调用unrar命令。若跳过make install,即使编译成功,unrar也无法在终端中被调用

验证是否安装成功

echo $PATH | grep /usr/local/bin  # 确认路径存在
rar --help
unrar e archive.rar 

3 ) RAR 常用操作示例

压缩目录为 .rar 文件

rar a sorting.rar sorting/

参数 a 表示 add,即将指定目录加入压缩包,生成 sorting.rar

解压 .rar 文件

unrar x sorting.rar

x 保留原始目录结构(extract with full path );若用 e 则展平提取(提取内容不保留目录结构)。

仅列出内容而不解压

unrar l sorting.rar

这里会列出归档内所有文件及大小、时间戳等信息,输出类似:

     Sorting/Sorting/A.javaSorting/B.javaSorting/C.java

Linux 软件安装三大路径对比


方法工具特点适用场景
包管理器安装yum, dnf, apt自动处理依赖,安全稳定绝大多数常规软件
二进制包安装rpm, dpkg, alien快速部署,但依赖需手动满足第三方闭源软件
源码编译安装configure, make, make install最大灵活性,可定制优化新兴软件、嵌入式开发

最佳实践建议

方法适用场景优点缺点
Yum/Apt 包管理主流软件、稳定版本自动依赖解析、易于维护版本滞后
Alien 转换安装跨发行版临时使用快速获得可用包兼容风险高、依赖难管
源码编译安装新版、定制化需求完全可控、性能优化复杂、易出错

推荐操作顺序:

  1. 优先尝试 yum search <name>apt-cache search <name>
  2. 若不可用,搜索是否有 .rpm.deb 官方发布包
  3. 否则考虑使用 Alien 进行格式转换(注意依赖手动补全)
  4. 最终手段:下载源码 → 检查 README → 安装依赖 → configure → make → make install

NestJS + TypeScript 示例代码(模拟软件构建服务)

1 ) 方案1

以下是一个基于 NestJS 的轻量级“编译任务调度系统”原型,可用于自动化管理源码构建流程:

// src/build/build.service.ts
import { Injectable } from '@nestjs/common';
import { execSync } from 'child_process';@Injectable()
export class BuildService {compileFromSource(sourceUrl: string,configArgs: string[] = [],installPath: string = '/usr/local',): boolean {try {// Step 1: Download source console.log(`Downloading ${sourceUrl}...`);execSync(`wget -q ${sourceUrl}`);const tarball = sourceUrl.split('/').pop();const dirName = tarball.replace('.tar.gz', '').replace('.tgz', '');// Step 2: Extract execSync(`tar -zxvf ${tarball}`);// Step 3: Configure process.chdir(dirName);const configureCmd = ['./configure', ...configArgs].join(' ');execSync(configureCmd, { stdio: 'inherit' });// Step 4: CompileexecSync('make', { stdio: 'inherit' });// Step 5: InstallexecSync(`make PREFIX=${installPath} install`, { stdio: 'inherit' });console.log('Build and installation completed.');return true;} catch (err) {console.error('Build failed:', err.message);return false;}}checkDependencies(packages: string[]): boolean {const missing = packages.filter(pkg => {try {execSync(`rpm -q ${pkg}`, { stdio: 'pipe' });return false;} catch {return true;}});if (missing.length > 0) {console.log('Missing dependencies:', missing.join(', '));execSync(`yum install -y ${missing.join(' ')}`, { stdio: 'inherit' });}return true;}
}
// src/build/build.controller.ts
import { Controller, Post, Body } from '@nestjs/common';
import { BuildService } from './build.service';@Controller('build')
export class BuildController {constructor(private readonly buildService: BuildService) {}@Post('htop')buildHtop() {this.buildService.checkDependencies(['gcc', 'make', 'ncurses-devel']);return this.buildService.compileFromSource('https://github.com/htop-dev/htop/archive/refs/tags/3.2.0.tar.gz',['--enable-unicode'],);}
}
// src/app.module.ts
import { Module } from '@nestjs/common';
import { BuildModule } from './build/build.module';@Module({imports: [BuildModule],
})
export class AppModule {}

此模块可用于 CI/CD 流水线中,实现自动化构建与测试

2 )方案2

基于 NestJS 的自动化构建服务模块,模拟对源码包的下载、校验、解压、编译与安装流程控制。

// build.service.ts
import { Injectable } from '@nestjs/common';
import * as fs from 'fs';
import * as path from 'path';
import * as childProcess from 'child_process';
import { promisify } from 'util';const exec = promisify(childProcess.exec);interface BuildConfig {sourceUrl: string;checksum?: string;workDir: string;configureArgs?: string[];prefix?: string;
}@Injectable()
export class BuildService {async compileFromSource(config: BuildConfig): Promise<string> {const { sourceUrl, workDir, configureArgs = [], prefix = '/usr/local' } = config;try {await this.ensureDirectory(workDir);const fileName = this.getFilenameFromUrl(sourceUrl);const filePath = path.join(workDir, fileName);// Step 1: Downloadawait this.downloadFile(sourceUrl, filePath);// Step 2: Extractconst extractDir = await this.extractTarGz(filePath, workDir);// Step 3: Configureconst buildPath = path.join(workDir, extractDir);await this.runCommand('./configure', [...configureArgs,`--prefix=${prefix}`,], buildPath);// Step 4: Makeawait this.runCommand('make', [], buildPath);// Step 5: Installawait this.runCommand('make', ['install'], buildPath);return `${prefix}/bin/${extractDir.split('-')[0]}`;} catch (err) {console.error('Build failed:', err.message);throw new Error(`Compilation failed: ${err.message}`);}}private async ensureDirectory(dir: string) {if (!fs.existsSync(dir)) {fs.mkdirSync(dir, { recursive: true });}}private getFilenameFromUrl(url: string): string {return decodeURIComponent(url.split('/').pop());}private async downloadFile(url: string, dest: string) {if (fs.existsSync(dest)) {console.log('File already exists, skipping download.');return;}await exec(`wget '${url}' -O '${dest}'`);}private async extractTarGz(file: string, dest: string): Promise<string> {await exec(`tar -xzf '${file}' -C '${dest}'`);const dirName = path.basename(file, '.tar.gz');return dirName;}private async runCommand(cmd: string, args: string[], cwd: string) {const fullCmd = [cmd, ...args].join(' ');console.log(`Executing in ${cwd}: ${fullCmd}`);const { stdout, stderr } = await exec(fullCmd, { cwd });if (stdout) console.log(stdout);if (stderr) console.error(stderr);}
}

使用示例(Controller 层)

// build.controller.ts
import { Controller, Post, Body } from '@nestjs/common';
import { BuildService } from './build.service';@Controller('build')
export class BuildController {constructor(private readonly buildService: BuildService) {}@Post('htop')async buildHtop() {const config = {sourceUrl: 'https://github.com/htop-dev/htop/archive/refs/tags/2.2.0.tar.gz',workDir: '/tmp/build',configureArgs: ['--disable-unicode'],};const binaryPath = await this.buildService.compileFromSource(config);return { status: 'success', binary: binaryPath };}
}

说明:该服务可用于 CI/CD 流水线中自动编译私有模块,结合 Docker 更安全。

3 )方案3

模拟“源码下载 → 编译 → 安装”的抽象流程。

该服务可用于 CI/CD 流水线控制、远程主机管理、教学演示等场景。

项目结构

src/
├── compiler/
│   ├── compiler.service.ts
│   ├── compiler.controller.ts
│   └── dto/
│       └── compile.dto.ts

DTO 定义:接收编译参数

// src/compiler/dto/compile.dto.ts
export class CompileDto {readonly sourceUrl: string;           // 源码地址readonly configArgs?: string[];       // configure 参数数组readonly makeTargets?: string[];     // make 目标(如 all, install)readonly requireSudo?: boolean;      // 是否需要 sudo 权限
}

Controller:暴露 API 接口

// src/compiler/compiler.controller.ts
import { Controller, Post, Body } from '@nestjs/common';
import { CompilerService } from './compiler.service';
import { CompileDto } from './dto/compile.dto';@Controller('compile')
export class CompilerController {constructor(private readonly compilerService: CompilerService) {}@Post()async startCompilation(@Body() dto: CompileDto): Promise<{ success: boolean; output: string }> {const result = await this.compilerService.compile(dto);return { success: result.success, output: result.output };}
}

Service:核心逻辑封装(调用 shell 命令)

// src/compiler/compiler.service.ts
import { Injectable } from '@nestjs/common';
import * as childProcess from 'child_process';
import * as fs from 'fs';
import * as path from 'path';@Injectable()
export class CompilerService {private readonly TEMP_DIR = '/tmp/nestjs-compile';async compile(dto: CompileDto): Promise<{ success: boolean; output: string }> {let output = '';const cwd = path.join(this.TEMP_DIR, Date.now().toString());try {// 创建临时工作目录fs.mkdirSync(cwd, { recursive: true });output += `Created workspace: ${cwd}\n`;// Step 1: 下载源码const tarball = path.basename(dto.sourceUrl);const cmdWget = `wget -O ${tarball} ${dto.sourceUrl}`;output += await this.execCommand(cmdWget, cwd);// Step 2: 解压const cmdUntar = `tar -zxvf ${tarball}`;output += await this.execCommand(cmdUntar, cwd);// Step 3: 进入源码目录(假设目录名为去掉后缀)const srcDir = tarball.replace('.tar.gz', '').replace('.tgz', '');const fullSrcPath = path.join(cwd, srcDir);output += `Entering source directory: ${fullSrcPath}\n`;// Step 4: 配置const configArgs = dto.configArgs?.join(' ') || '';const cmdConfigure = `./configure ${configArgs}`;output += await this.execCommand(cmdConfigure, fullSrcPath);// Step 5: 编译const makeTargets = dto.makeTargets?.join(' ') || 'all';const cmdMake = `make ${makeTargets}`;output += await this.execCommand(cmdMake, fullSrcPath);// Step 6: 安装(可能需要 sudo)const cmdInstall = dto.requireSudo ? `sudo make install` : `make install`;output += await this.execCommand(cmdInstall, fullSrcPath);return { success: true, output };} catch (error) {return { success: false, output: output + '\nError: ' + error.message };}}private execCommand(command: string, cwd: string): Promise<string> {return new Promise((resolve) => {childProcess.exec(command, { cwd }, (err, stdout, stderr) => {const out = `[CMD] ${command}\n${stdout}\n${stderr}\n`;resolve(out);});});}
}

启动应用并测试

curl -X POST http://localhost:3000/compile \-H "Content-Type: application/json" \-d '{"sourceUrl": "https://hisham.hm/htop/releases/2.2.0/htop-2.2.0.tar.gz","configArgs": ["--disable-unicode"],"makeTargets": ["all", "install"],"requireSudo": true}'

此服务仅为演示用途,生产环境请结合权限控制、日志审计、沙箱隔离等安全措施

结论

无论是通过包管理器一键安装,还是借助 Alien 转换不同发行版的安装包,抑或是深入底层从源码编译,Linux 提供了多层次的软件部署机制。掌握这些方法不仅提升运维效率,更深化对操作系统运行原理的理解

真正的掌控力来自于理解底层机制——知道 yum 如何解决依赖、明白 configure 如何探测系统环境、清楚 make 如何调度编译任务,才能在面对各种“无法安装”的困境时游刃有余。

核心要点回顾:

  • 包管理器是首选
  • Alien 转换需慎用,依赖须手动补齐
  • 源码编译五步曲:下载 → 解压 → 配置 → 编译 → 安装
  • 开发包(-devel)必不可少
  • 合理使用 READMEconfigure --help 获取帮助

总结与技术凝练

技术点关键说明
包管理器安装首选方式,自动处理依赖,适合绝大多数场景
Alien 转换包格式解决跨发行版兼容问题,但不能保证 100% 成功,建议优先寻找原生 RPM/DEB
源码编译五大步download → extract → configure → make → make install,每一步都至关重要
configure 失败原因多为缺少开发包(如 xxx-devel),务必安装对应 -devel 版本
make 的本质执行 Makefile 中定义的编译规则,实现自动化构建
wget 的优势无需浏览器即可下载网络资源,适合无 GUI 环境
RAR 工具链官方提供编译好的二进制文件,直接复制到 PATH 即可使用

唯有不断实践,方能在复杂环境中自如应对各类软件部署挑战,真正的掌控力,始于亲手编译第一个程序

http://www.dtcms.com/a/512473.html

相关文章:

  • 【Python编程】之面向对象
  • Day67 Linux I²C 总线与设备驱动架构、开发流程与调试
  • 【AI增强质量管理体系结构】AI+自动化测试引擎 与Coze
  • 音频共享耳机专利拆解:碰击惯性数据监测与阈值减速识别机制研究
  • 青岛专业网站设计公司网站后台程序怎么做
  • MySQL创建用户、权限分配以及添加、修改权限
  • 【循环神经网络基础】
  • 郑州网站建设与设计校园网站建设年度总结
  • 中国新冠一共死去的人数网站优化和提升网站排名怎么做
  • 太仓手机网站建设阿里云如何做网站
  • 第二篇:按键交互入门:STM32 GPIO输入与消抖处理
  • JSP九大内置对象
  • 如何选择大良网站建设网站建设插件代码大全
  • 卡码网语言基础课(Python) | 17.判断集合成员
  • 温州专业网站建设成都营销推广公司
  • 淘客做网站还是做app佛山seo网站优化
  • 组合数常见的四种计算方法
  • 美容医疗服务小程序:功能集成,解锁一站式变美新体验
  • 网站建设的展望 视频搭建公司内部网站
  • Mac 从零开始配置 VS Code + Claude/Codex AI 协同开发环境教程
  • 鸿蒙flutter 老项目到新项目的遇到迁移坑点
  • 网站开发z亿玛酷1专注响应式官网设计
  • SD comfy:教程3 - 音频生成
  • 百度网盘登录福建键seo排名
  • Xshell效率实战系列一:内置Xftp快速启动——从1分钟到10秒的传输革命
  • 公路建设网站自己编写网站
  • EN 13986:2004+A1:2015 人造板检测
  • 酒店网站html模板长沙微信网站建设
  • 天河建设网站技术网站备案号密码
  • 步进电机(200 smart DM542)调试文档