前言
当我们开发完一个应用程序后,需要把它打包成安装包分发给用户。在 Windows 上,我们通常使用 NSIS、Inno Setup 等工具生成 .exe 安装程序;而在 Linux(Debian/Ubuntu 系)上,我们则需要制作 .deb 包。
本文将从一个 Windows 开发者的视角,介绍这两种打包方式的基础知识和核心区别。
一、NSIS 基础知识
1.1 什么是 NSIS?
NSIS(Nullsoft Scriptable Install System)是一个开源的 Windows 安装程序制作工具,由 Winamp 的开发商 Nullsoft 创建。它通过脚本语言来定义安装流程,最终生成一个独立的 .exe 安装程序。
1.2 NSIS 的核心特点
- 脚本驱动:使用
.nsi脚本文件定义安装逻辑 - 高度可定制:支持自定义安装界面、多语言、插件扩展
- 体积小巧:生成的安装包压缩率高,体积小
- 功能丰富:支持注册表操作、文件操作、快捷方式创建等
1.3 NSIS 安装包结构
一个典型的 NSIS 项目结构如下:
nsis-project/
├── Setup.nsi # 主脚本文件
├── Scripts/
│ ├── Const.nsh # 常量定义
│ ├── Functions/
│ │ ├── OnInit.nsh # 初始化函数
│ │ ├── Files.nsh # 文件安装
│ │ ├── Registry.nsh # 注册表操作
│ │ ├── ShortCuts.nsh # 快捷方式创建
│ │ └── OnEnd.nsh # 安装结束处理
│ └── Languages.nsh # 多语言支持
├── Plugins/ # 插件目录
└── Resources/ # 资源文件(图标、图片等)
1.4 NSIS 安装流程
用户双击 Setup.exe
↓
OnInit(初始化检查)
↓
显示安装界面(欢迎页、协议页、路径选择等)
↓
Files(复制文件到安装目录)
↓
Registry(写入注册表信息)
↓
ShortCuts(创建桌面/开始菜单快捷方式)
↓
OnEnd(完成处理)
↓
安装完成
1.5 NSIS 核心概念
注册表(Registry)
Windows 的注册表是软件信息的中央数据库。NSIS 安装包通常会写入以下信息:
# 写入卸载信息
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\MyApp" "DisplayName" "My Application"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\MyApp" "UninstallString" "$INSTDIR\Uninstall.exe"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\MyApp" "DisplayVersion" "1.0.0"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\MyApp" "Publisher" "My Company"
# 写入软件信息
WriteRegStr HKLM "Software\MyCompany\MyApp" "InstallPath" "$INSTDIR"
快捷方式(.lnk 文件)
# 创建桌面快捷方式
CreateShortCut "$DESKTOP\MyApp.lnk" "$INSTDIR\MyApp.exe"
# 创建开始菜单快捷方式
CreateDirectory "$SMPROGRAMS\MyApp"
CreateShortCut "$SMPROGRAMS\MyApp\MyApp.lnk" "$INSTDIR\MyApp.exe"
1.6 NSIS 常用命令
| 命令 | 说明 |
|---|---|
OutFile | 指定输出的安装包文件名 |
InstallDir | 指定默认安装目录 |
SetOutPath | 设置文件输出路径 |
File | 添加要安装的文件 |
CreateDirectory | 创建目录 |
CreateShortCut | 创建快捷方式 |
WriteRegStr | 写入注册表字符串 |
DeleteRegKey | 删除注册表项 |
ExecWait | 执行程序并等待 |
RMDir | 删除目录 |
Delete | 删除文件 |
二、dpkg 基础知识
2.1 什么是 dpkg?
dpkg(Debian Package)是 Debian 及其衍生发行版(如 Ubuntu、Deepin、Linux Mint 等)的底层包管理工具。它负责 .deb 包的安装、卸载和查询等操作。
可以把 dpkg 理解为 Linux 版的 MSI 安装程序,它是最基础的包管理工具。
2.2 deb 包的结构
一个 .deb 包本质上是一个 ar 格式的压缩文件,包含以下核心部分:
myapp_1.0.0_amd64.deb
├── debian-binary # deb格式版本号
├── control.tar.gz # 控制信息
│ ├── control # 包的元数据(必需)
│ ├── preinst # 安装前脚本
│ ├── postinst # 安装后脚本
│ ├── prerm # 卸载前脚本
│ └── postrm # 卸载后脚本
└── data.tar.gz # 实际安装的文件
└── usr/
└── local/
├── bin/ # 可执行文件
└── share/
├── applications/ # .desktop 文件
└── icons/ # 图标文件
2.3 control 文件详解
control 文件是 deb 包的核心元数据文件,类似于 package.json:
Package: myapp
Version: 1.0.0
Section: utils
Priority: optional
Architecture: amd64
Depends: libc6 (>= 2.17), libgtk-3-0
Maintainer: Your Name <your.email@example.com>
Description: My awesome application
This is a longer description of my application.
It can span multiple lines.
Homepage: https://myapp.example.com
字段说明:
| 字段 | 说明 | 是否必需 |
|---|---|---|
Package | 包名(小写,可含数字和连字符) | ✅ |
Version | 版本号 | ✅ |
Architecture | 架构(amd64, i386, arm64, all) | ✅ |
Maintainer | 维护者信息 | ✅ |
Description | 软件描述 | ✅ |
Depends | 依赖包列表 | ❌ |
Section | 软件分类 | ❌ |
Priority | 优先级 | ❌ |
Homepage | 项目主页 | ❌ |
2.4 维护者脚本
dpkg 提供了四个维护者脚本,在安装/卸载的不同阶段执行:
| 脚本 | 执行时机 | 典型用途 |
|---|---|---|
preinst | 安装前 | 停止旧服务、备份配置 |
postinst | 安装后 | 创建快捷方式、启动服务、初始化配置 |
prerm | 卸载前 | 停止服务、清理运行时数据 |
postrm | 卸载后 | 删除快捷方式、清理残留文件 |
postinst 示例:
#!/bin/bash
# 更新图标缓存
gtk-update-icon-cache /usr/share/icons/hicolor/ -t
# 创建桌面快捷方式
DESKTOP_FILE="/usr/share/applications/myapp.desktop"
for USER_HOME in /home/*; do
if [ -d "$USER_HOME/Desktop" ]; then
cp "$DESKTOP_FILE" "$USER_HOME/Desktop/"
chmod +x "$USER_HOME/Desktop/myapp.desktop"
fi
done
exit 0
2.5 .desktop 文件
.desktop 文件是 Linux 下的"快捷方式",定义了应用程序的启动信息:
[Desktop Entry]
Version=1.0
Type=Application
Name=My Application
Name[zh_CN]=我的应用
Comment=A great application
Comment[zh_CN]=一个很棒的应用
Exec=/usr/local/bin/myapp %F
Icon=myapp
Terminal=false
Categories=Utility;
StartupWMClass=myapp
MimeType=application/x-myapp;
字段说明:
| 字段 | 说明 |
|---|---|
Name | 应用显示名称 |
Exec | 执行命令 |
Icon | 图标名称或路径 |
Terminal | 是否在终端中运行 |
Categories | 应用分类 |
MimeType | 支持的文件类型 |
2.6 dpkg 安装流程
执行 dpkg -i myapp.deb
↓
解压 deb 包
↓
执行 preinst 脚本(安装前准备)
↓
解压 data.tar.gz(复制文件到目标位置)
↓
执行 postinst 脚本(安装后配置)
↓
更新 dpkg 数据库(/var/lib/dpkg/)
↓
安装完成
三、dpkg 常用命令
3.1 安装相关
# 安装 deb 包
sudo dpkg -i package.deb
# 安装目录下所有 deb 包
sudo dpkg -i *.deb
# 强制安装(忽略依赖,谨慎使用)
sudo dpkg -i --force-depends package.deb
# 修复依赖问题(配合 apt 使用)
sudo apt install -f
3.2 卸载相关
# 卸载软件(保留配置文件)
sudo dpkg -r package-name
# 完全卸载(包括配置文件)
sudo dpkg -P package-name
# 或
sudo dpkg --purge package-name
3.3 查询相关
# 列出所有已安装的包
dpkg -l
# 搜索包含特定关键字的包
dpkg -l | grep keyword
# 查看包的详细信息
dpkg -s package-name
# 查看包安装了哪些文件
dpkg -L package-name
# 查看某个文件属于哪个包
dpkg -S /path/to/file
# 查看 deb 包的信息(未安装的包)
dpkg -I package.deb
# 查看 deb 包的内容(未安装的包)
dpkg -c package.deb
3.4 其他常用命令
# 重新配置已安装的包
sudo dpkg-reconfigure package-name
# 查看包的状态
dpkg --status package-name
# 比较版本号
dpkg --compare-versions 1.0 gt 0.9 && echo "1.0 大于 0.9"
# 解压 deb 包到指定目录(不安装)
dpkg -x package.deb /target/directory
# 解压 control 信息到指定目录
dpkg -e package.deb /target/directory
3.5 构建 deb 包
# 从目录构建 deb 包
dpkg-deb --build package-directory
# 指定输出文件名
dpkg-deb --build package-directory output.deb
# 使用 fakeroot 构建(推荐)
fakeroot dpkg-deb --build package-directory
四、NSIS vs dpkg 对比
4.1 核心概念对照表
| Windows 概念 | Linux 对应 | 说明 |
|---|---|---|
.exe 安装程序 | .deb 包 | 安装包格式 |
| 注册表 (Registry) | dpkg 数据库 | 软件信息存储 |
.lnk 快捷方式 | .desktop 文件 | 桌面/菜单快捷方式 |
C:\Program Files\ | /usr/local/ 或 /opt/ | 默认安装位置 |
| 控制面板 → 卸载 | dpkg -r / apt remove | 卸载方式 |
| Windows 应用商店 | apt + 软件仓库 | 软件分发渠道 |
4.2 安装流程对比
NSIS (Windows):
用户双击 setup.exe
→ 显示安装界面(可交互)
→ 用户选择安装路径
→ 复制文件到安装目录
→ 写入注册表
→ 创建快捷方式
→ 显示完成页面
dpkg (Linux):
执行 sudo dpkg -i xxx.deb
→ 解压deb包
→ 运行 preinst 脚本
→ 复制文件到目标位置(路径固定)
→ 运行 postinst 脚本
→ 更新dpkg数据库
→ 命令行显示完成
4.3 主要差异
| 特性 | NSIS | dpkg |
|---|---|---|
| 安装界面 | 图形化、可交互 | 命令行、无界面 |
| 安装路径 | 用户可选择 | 包内固定 |
| 依赖处理 | 需自行打包或检测 | 声明依赖,由系统处理 |
| 软件信息存储 | 注册表 | 数据库文件 |
| 卸载方式 | 运行 Uninstall.exe | dpkg -r 或 apt remove |
| 多版本共存 | 可以(不同目录) | 通常不可以 |
4.4 图标格式差异
在electron-builder 里面会要求不同的图标格式,看看他们的区别
Windows (.ico 格式)
Windows 使用 .ico 格式的图标文件,这是一个容器格式,可以在单个文件中包含多种尺寸的图标:
myapp.ico
├── 16x16
├── 32x32
├── 48x48
├── 64x64
├── 128x128
└── 256x256
特点:
- 单个
.ico文件包含所有尺寸 - NSIS 安装时只需指定一个图标文件
- 系统自动选择合适尺寸显示
NSIS 中使用图标:
# 设置安装程序图标
Icon "resources\app.ico"
# 设置卸载程序图标
UninstallIcon "resources\uninstall.ico"
# 快捷方式会自动使用 exe 内嵌的图标
CreateShortCut "$DESKTOP\MyApp.lnk" "$INSTDIR\MyApp.exe"
Linux (多尺寸 PNG 格式)
Linux 采用 freedesktop.org 图标主题规范,使用独立的 PNG 文件存放在特定目录结构中:
/usr/share/icons/hicolor/
├── 16x16/apps/
│ └── myapp.png
├── 32x32/apps/
│ └── myapp.png
├── 48x48/apps/
│ └── myapp.png
├── 64x64/apps/
│ └── myapp.png
├── 128x128/apps/
│ └── myapp.png
├── 256x256/apps/
│ └── myapp.png
└── scalable/apps/
└── myapp.svg # 可选:SVG 矢量图标
特点:
- 每个尺寸是独立的 PNG 文件
- 遵循
hicolor图标主题规范 - 支持 SVG 矢量图标(scalable 目录)
- 需要在安装后执行
gtk-update-icon-cache更新缓存
deb 包中的图标目录结构:
myapp_1.0.0_amd64/
└── usr/
└── share/
└── icons/
└── hicolor/
├── 48x48/
│ └── apps/
│ └── myapp.png
├── 128x128/
│ └── apps/
│ └── myapp.png
└── 256x256/
└── apps/
└── myapp.png
postinst 中更新图标缓存:
#!/bin/bash
# 更新图标缓存,使新图标生效
gtk-update-icon-cache /usr/share/icons/hicolor/ -t 2>/dev/null || true
exit 0
.desktop 文件中引用图标:
[Desktop Entry]
Name=MyApp
Exec=/usr/local/bin/myapp
Icon=myapp # 只需写图标名称,系统自动查找对应尺寸
Terminal=false
Type=Application
图标格式对比总结
| 特性 | Windows (.ico) | Linux (.png) |
|---|---|---|
| 文件格式 | 单个 .ico 容器文件 | 多个独立 .png 文件 |
| 尺寸管理 | 内嵌在一个文件 | 分目录存放 |
| 矢量支持 | ❌ 不支持 | ✅ 支持 SVG |
| 主题支持 | ❌ 不支持 | ✅ 支持图标主题 |
| 缓存机制 | 系统自动处理 | 需手动更新缓存 |
| 引用方式 | 完整路径 | 图标名称(无扩展名) |
常用图标尺寸建议
| 尺寸 | 用途 |
|---|---|
| 16x16 | 任务栏、小列表 |
| 32x32 | 开始菜单、中等列表 |
| 48x48 | 应用程序菜单 |
| 64x64 | 大列表视图 |
| 128x128 | 文件管理器图标视图 |
| 256x256 | 高分辨率显示、软件中心 |
五、dpkg vs apt
这是新手最容易混淆的概念!
5.1 关系说明
apt = dpkg + 依赖管理 + 网络下载 + 仓库管理
apt 是基于 dpkg 的高级包管理工具。当你执行 apt install 时,apt 实际上在后台调用 dpkg 来完成安装。
5.2 功能对比
| 特性 | dpkg | apt |
|---|---|---|
| 层级 | 底层工具 | 高层工具 |
| 依赖处理 | ❌ 不处理 | ✅ 自动解决 |
| 软件源 | ❌ 只能安装本地包 | ✅ 可从网络仓库下载 |
| 自动更新 | ❌ 不支持 | ✅ 支持 |
| 软件搜索 | ❌ 只能查已安装 | ✅ 可搜索仓库 |
5.3 使用场景
使用 dpkg 的场景:
- 安装本地下载的
.deb文件 - 查询已安装软件的详细信息
- 手动管理软件包
- 打包制作 deb 包
使用 apt 的场景:
- 从官方仓库安装软件
- 自动解决依赖关系
- 批量更新系统软件
- 搜索可用软件包
5.4 常见工作流
# 场景1:安装本地 deb 包
sudo dpkg -i downloaded-app.deb
# 如果提示缺少依赖
sudo apt install -f # apt 帮你自动安装缺失的依赖
# 场景2:从仓库安装
sudo apt update # 更新软件源
sudo apt install nginx # 自动下载、解决依赖、安装
# 场景3:查看软件信息
dpkg -L nginx # 查看安装了哪些文件
apt show nginx # 查看软件详细信息
总结
| 平台 | 打包工具 | 包格式 | 包管理器 |
|---|---|---|---|
| Windows | NSIS, Inno Setup | .exe | 无(注册表) |
| Debian/Ubuntu | dpkg-deb | .deb | dpkg, apt |
| RedHat/CentOS | rpmbuild | .rpm | rpm, yum/dnf |
| macOS | pkgbuild | .pkg | installer |
从 Windows 迁移到 Linux 的开发者,最重要的是理解以下几点:
- Linux 没有注册表,软件信息由包管理器的数据库管理
- 快捷方式是 .desktop 文件,而不是 .lnk 文件
- dpkg 是底层工具,apt 是建立在它之上的高级工具
- deb 包路径是固定的,不像 Windows 可以让用户选择安装位置
希望这篇文章能帮助你快速理解 Linux 下的软件打包!