Linux deb 应用打包

这里的Linux打包其实总共分以下几类, 更多是方便内网一键部署的情况:

  • Debian(.deb) 系列包系统: dpkg -i xxx.deb(安装)|dpkg -r xxx(卸载)
  • RedHat(.rpm) 系列包系统: rpm -ivh xxx.rpm(安装)|rpm -e xxx.rpm(卸载)
  • Docker 直接编写 Dockerfile 和 docker-compose 部署

一般来说如果是打包有分为 命令行桌面应用, 这里主要是用于部署服务端所以采用命令行操作

这里需要先采用 debian 打包方式说明, 适用于 Debian|Ubuntu 系列的虚拟环境, 其他因为不常用所以后续再补充.

deb打包

实际上需要按照以下命令来做打包:

1
2
3
4
5
# 按照文件夹规则放置到其中
dpkg -b 文件夹名称 安装包名称

# 比如以下方式打包, fusion-gateway 是当前目录下的子目录
dpkg -b fusion-gateway fusion-gateway_1.0_amd64.deb

按照以下流程测试打包名为 fusion-gateway 的应用, 该应用基于 Java17-Jre 依赖启动:

1
2
3
4
5
6
7
8
9
10
11
12
# 创建并进入目录之中, 注意 DEBIAN 目录是必须的
mkdir -p fusion-gateway/DEBIAN && cd fusion-gateway/DEBIAN

# 之后就是包信息文件 control
# 关键字首字母大写, 冒号后面必须有空格
# 必填字段: Package、Version、Architecture、Maintainer、Description,且内容不能为空
touch control

# postinst(安装后脚本) | prerm(卸载前脚本)
# 注意权限必须要 <= 775, 否则会出现包安装失败
touch postinst && chmod 755 postinst
touch prerm && chmod 755 prerm

这里为了演示移动文件, 所以下载个 MIT 许可文件放入依赖目录安装之后自动创建目录和移动文件,
文件地址为: MIT License,
下载或者复制内容之后命名为 License.

参考 debian打包策略

这里首先就是 control 包信息配置, 需要遵循以下字段:

control

所以这里最后 fusion-gateway 包信息如下( 注意包名特殊符号只能包含 -+. ):

1
2
3
4
5
6
7
8
Package: fusion-gateway
Version: 2025.3.29
Description: fusion gateway application
Section: net
Priority: standard
Architecture: amd64
Maintainer: MeteorCat
Pre-Depends: openjdk-17-jre, subversion

配置内部表明需要在脚本部署之前安装 openjdk-17-jresubversion,
如果没有该本地环境没有该引用会提示错误信息:

1
2
3
4
Selecting previously unselected package fusion-gateway.
dpkg: regarding fusion-gateway-2025.3.29.deb containing fusion-gateway, pre-dependency problem:
fusion-gateway pre-depends on subversion
subversion is not installed.

这里将 license 文件放入目录其中, 注意目前 deb 的根目录就是安装部署服务的根目录:

1
2
3
4
5
6
# 一般自己编写的依赖包文件最好放置 /usr/local 目录之中
# 注意这里必须要 DEBIAN 上级目录, 也就是 fusion-gateway 目录作为根目录
mkdir -p ../usr/local/fusion/gateway

# 将文件写入内部当中
touch ../usr/local/fusion/gateway/license

之后就是安装执行脚本 postinst, 现在仅仅做个创建目录操作和移动 README.md 的操作:

1
2
3
4
5
#!/bin/sh

# create directory
mkdir -p /usr/local/fusion/gateway
chmod -R 755 /usr/local/fusion/gateway

最后就是卸载删除的脚本 prerm, 实际上直接直接清理就行了:

1
2
3
4
#!/bin/sh

# remove directory
rm -rf /usr/local/fusion/gateway

之后直接测试打包自己的应用包:

1
2
3
4
5
6
7
8
9
10
11
12
13
cd ../../ # 回到 fusion-gateway 上级目录
dpkg -b fusion-gateway/ fusion-gateway-2025.3.29.deb # 打包为 *.deb 包
# 最后再同目录下生成的包
# fusion-gateway-2025.3.29.deb

# 这里最后测试下安装和卸载
sudo dpkg -i fusion-gateway-2025.3.29.deb

# 之后查看目录
ls /usr/local/fusion/gateway

# 最后没问题就卸载软件就行了, 没问题之后就能看到目录直接删除
sudo dpkg -r fusion-gateway

这里就是一个简单 deb 包软件, 内部其实带有很大隐患需要处理, 接下来就是指出和修复内部问题.

问题修复

上面虽然最后打包成功, 但是也暴露很多问题:

  • 权限控制, 如果后台服务类最好构建出单独 linux 账号来指定运行服务
  • 可执行冲突, 前往不要全局安装 jre 或者其他可执行, 可能会导致本来使用全局的服务应用因升级|降级奔溃
  • 日志导出, 如果有需要配置日志需要在 /var/log 构建好对应应用名录并写入
  • 配置归类, 系统应用应该统一写入在 /etc 目录之中
  • 系统注册, 需要将持久后台服务注册到 systemd 之中持续运行

实际测试发现打包成 deb 的流程并不比 docker 慢, 首先确定需要安装脚本 postinst 的操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/bin/sh

# create authority
useradd -M -s /usr/sbin/nologin fusion

# create directory
mkdir -p /usr/local/fusion/gateway
mkdir -p /var/log/fusiion

# change permission
chmod -R 755 /usr/local/fusion
chmod -R 755 /var/log/fusiion

chwon -R fusion:fusion /usr/local/fusion
chown -R fusion:fusion /var/log/fusiion

# download jre by zulu-java
# url: https://cdn.azul.com/zulu/bin/zulu17.56.15-ca-jre17.0.14-linux_x64.tar.gz

这里面实际上可以考虑直接 zulujdk 要么直接 wget 下载最新版本到 /usr/local/fusion 目录之中,
也可以官网下载之后之后追加打包丢在包内, 内网开发有时候没办法访问外网或者网络问题导致无法连接,
所以这里还是推荐直接去下载放到包内一起同步安装:

1
2
3
4
5
6
7
8
9
10
# 在打包目录之中创建 jre 目录用于放入执行二进制文件
# 这里把 zulu jre 的下载安装包解压放入其中就行了
mkdir -p fusion-gateway/usr/local/fusion/jre
cd fusion-gateway/usr/local/fusion/jre

# 官网直接下载 jre
wget -t 2 -T 10 -O jre17.tar.gz "https://cdn.azul.com/zulu/bin/zulu17.56.15-ca-jre17.0.14-linux_x64.tar.gz"

# 解压 jre 到当前目录, 可以考虑压缩文件保存不需要删除
tar -zxvf jre17.tar.gz --strip-components=1

并且还需要追加 systemd 的服务文件, 让其跟随一起创建注册服务:

1
2
3
4
5
6
# 在打包目录之中在系统目录创建生成 `fusion-gateway.service` 的 java 网关服务
mkdir -p fusion-gateway/usr/lib/systemd/system
cd fusion-gateway/usr/lib/systemd/system

# 创建系统服务文件, 注意服务文件一般是 root 操作
sudo touch fusion-gateway.service

卸载脚本 prerm 需要做清理工作, 这里没有加入 systemd 关闭操作, 建议正式环境清理之前停止服务再清理:

1
2
3
4
5
6
7
8
9
10
#!/bin/sh

# remove directory
rm -rf /usr/local/fusion/gateway
rm -rf /usr/local/fusion
rm -rf /var/log/fusiion

# remove user
userdel -r fusion
rm -rf /usr/lib/systemd/system/fusion-gateway.service

最后指定重新重新执行打包命令出包即可:

1
2
3
4
5
6
7
8
9
10
11
# 重新打包成 deb
dpkg -b fusion-gateway/ fusion-gateway-2025.3.30.deb # 打包为 *.deb 包

# 测试安装 deb 包, 注意内部有设计 root 的 service, 需要 root 权限
sudo dpkg -i fusion-gateway-2025.3.30.deb

# 可以看到 jre 版本
/usr/local/fusion/jre/bin/java -version

# 最后删除包就行了
sudo dpkg -r fusion-gateway

这里就完全隔离环境部署出 linux 的包, 如果需要假设其他环境基本只需要安装这个包即可.