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 包,还能自动解决依赖关系,极大简化了运维工作。

bash 复制代码
# 在 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 转换

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

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

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

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

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

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

bash 复制代码
安装 RPM 包
rpm -ivh sogou-*.rpm 

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

err 复制代码
error: Failed dependencies:
	libQt5Core.so.5 is needed by sogou-xxx.x86_64

关键点解析:

  • RPM 不自动解析依赖项,仅检查是否存在所需库文件;
  • yumdnf 在安装 .rpm 时能自动下载并解决依赖关系;
  • 因此建议优先使用 yum localinstall 来安装本地 RPM 包:
bash 复制代码
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 官网 下载最新版本源码压缩包:

bash 复制代码
wget https://github.com/htop-dev/htop/archive/refs/tags/3.2.0.tar.gz -O htop-3.2.0.tar.gz

2.2 解压源码包

bash 复制代码
tar -zxvf htop-3.2.0.tar.gz
cd htop-3.2.0

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

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

bash 复制代码
./configure

此脚本作用包括:

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

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

err 复制代码
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 安装编译依赖

bash 复制代码
yum install -y ncurses-devel
# 或
yum install -y ncurses-devel ncurses-base ncurses-term

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

关键术语说明:

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

重新运行配置脚本:

bash 复制代码
./configure --enable-unicode

确认输出末尾显示 "Configuration complete" 表示准备就绪

生成 Makefile 文件

2.5 执行编译:调用 make

bash 复制代码
make

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

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

2.6 安装程序:make install

bash 复制代码
sudo make install    # 需 root 权限

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

bash 复制代码
echo $PATH | grep /usr/local/bin
# 或 查看验证 
ls /usr/local/bin/htop

验证安装结果:

bash 复制代码
htop --version 

启动 htop:

bash 复制代码
htop

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

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

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

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

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

使用 wget 下载与 RAR 工具部署

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

使用 wget 下载远程资源

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

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

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

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

解压并进入目录:

bash 复制代码
tar -xzf rarlinux-x64-6.2.4.tar.gz
cd rar 

目录结构如下:

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

使用 Make 安装预编译二进制

虽然不是传统意义上的"编译",但仍可通过 make 实现标准化安装

2 ) 部署预编译 RAR 工具

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

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

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

bash 复制代码
sudo make

查看 makefile 内容:

makefile 复制代码
install:
	install -m 755 rar /usr/local/bin/
	install -m 755 unrar /usr/local/bin/

makefile 复制代码
INSTALL_DIR = /usr/local/bin
 
install:
	cp rar $(INSTALL_DIR)/rar
	cp unrar $(INSTALL_DIR)/unrar 
	chmod 755 $(INSTALL_DIR)/rar $(INSTALL_DIR)/unrar

之后

bash 复制代码
sudo make install    # 需 root 权限

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

为何需要makemake install

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

验证是否安装成功

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

3 ) RAR 常用操作示例

压缩目录为 .rar 文件

bash 复制代码
rar a sorting.rar sorting/

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

解压 .rar 文件

bash 复制代码
unrar x sorting.rar

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

仅列出内容而不解压

bash 复制代码
unrar l sorting.rar

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

log 复制代码
     Sorting/
     Sorting/A.java
     Sorting/B.java
     Sorting/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 的轻量级"编译任务调度系统"原型,可用于自动化管理源码构建流程:

typescript 复制代码
// 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: Compile
      execSync('make', { stdio: 'inherit' });
 
      // Step 5: Install
      execSync(`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;
  }
}
typescript 复制代码
// 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'],
    );
  }
}
typescript 复制代码
// 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 的自动化构建服务模块,模拟对源码包的下载、校验、解压、编译与安装流程控制。

typescript 复制代码
// 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: Download
      await this.downloadFile(sourceUrl, filePath);
 
      // Step 2: Extract
      const extractDir = await this.extractTarGz(filePath, workDir);
 
      // Step 3: Configure
      const buildPath = path.join(workDir, extractDir);
      await this.runCommand('./configure', [
        ...configureArgs,
        `--prefix=${prefix}`,
      ], buildPath);
 
      // Step 4: Make
      await this.runCommand('make', [], buildPath);
 
      // Step 5: Install
      await 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 层)

typescript 复制代码
// 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 流水线控制、远程主机管理、教学演示等场景。

项目结构

tree 复制代码
src/
├── compiler/
│   ├── compiler.service.ts
│   ├── compiler.controller.ts
│   └── dto/
│       └── compile.dto.ts

DTO 定义:接收编译参数

ts 复制代码
// 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 接口

ts 复制代码
// 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 命令)

ts 复制代码
// 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);
      });
    });
  }
}

启动应用并测试

bash 复制代码
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 即可使用

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

相关推荐
超级大福宝3 小时前
在 Linux 下修改百度网盘的缩放比例
linux·运维·服务器·ubuntu
smileNicky3 小时前
AI+Linux 命令高效提取大量日志数据
linux·人工智能·firefox
怪只怪满眼尽是人间烟火3 小时前
Linux端口监控脚本
运维·javascript
Wang's Blog3 小时前
Linux小课堂: 深入理解前后台进程控制机制——基于 &、nohup、Ctrl+Z、bg 与 fg 的完整实践体系
linux·运维·服务器
-SGlow-3 小时前
Linux相关概念和易错知识点(48)(epoll的底层原理、epoll的工作模式、反应堆模式)
linux·服务器·c语言·网络·c++
秉承初心3 小时前
Linux中Expect脚本和Shell的脚本核心特点解析、以及比对分析和应用场景
linux·运维·服务器·sh·exp
脏脏a3 小时前
【Linux】Linux:sudo 白名单配置与 GCC/G++ 编译器使用指南
linux·运维·服务器
---学无止境---3 小时前
Linux中初始化字符设备子系统chrdev_init的实现
linux
十铭忘3 小时前
基于SAM2的眼动数据跟踪2
java·服务器·前端