Linux 下将程序打包为安装包

news/2025/10/21 23:05:38/文章来源:https://www.cnblogs.com/dengjialing/p/19156617

对于 Linux 下的程序打包,个人首推 FPM 构建工具。它比 dpkg、rpmbuild 要好用的多(至少 2021 年那会如此),并且它同时支持 deb、rpm 等包格式。

以下回顾一下以前写过的安装包构建脚本:

#!/bin/bash#-----------------------------------------------------------------------------------------------------------------------------------------
#----------------------------------------------- ---------------------------------------------------- 该块属于定制化部分,根据项目需要进行修改# 软件名称,主要作用于安装包名称和软件包管理器显示的软件名称
name="AppName"
# 软件中文名称,主要作用于桌面快捷方式
name_zh="你的软件名称"# 软件描述
comment="Description"
comment_zh="你的软件描述"# 版本号:
# 版本号通常由开发人员指定,其由 4 个数值组成,分别为:主版本号.子版本号.修正版本号.编译版本号。
#
# 主版本号:当产品有大的功能性变动,不再向前兼容时,比如产品重构,重大功能修改等,可变更主版本号。
# 主版本号提升后,子版本号与修正版本号归 0,编译版本号归 1。
#
# 子版本号:新功能增加、重要的且大批量的 Bug 修复或稳定版本发布时,将变更子版本号以体现每次发布。
# 子版本号提升后,修正版本号归 0,编译版本号归 1。
#
# 修正版本号:主要用于表述该产品的子版本号在发布后,经过了多少次修正;当完成某个或批次的 bug 修正、功能小改动并要提测时,可变更修正版本号。
# 修正版本号提升后,编译版本号归 1。
#
# 编译版本号:当对提测版本进行修正时将用到编译版本号,用于区分提测版本,避免每次提交给测试人员的程序中出现相同的版本号。
# 编译版本号一般由编译器自动累加,当上级版本号变更时由开发人员手动重置为 1。
version="1.1.0"
# 编译版本号
iteration=1# 目标平台的 CPU 架构
arch="arm64"# 安装包类型
type="deb"# 程序的安装目录
installPath="opt/AppDir"# 程序的可执行文件名称,其通常与软件名称保持一致
exe="${name}"
# 程序启动脚本名称,其通常与程序的可执行文件名称保持一致
startupScript="${exe}.sh"# 待打包的程序文件所在目录
source="file"# 待打包程序的资源文件所在目录
resourcesPath="resources"# desktop 文件名称,我们可以将其简单理解为桌面快捷方式文件。该文件描述了程序的启动配置信息。
desktopFile="${name}.desktop"# 桌面图标文件
desktopIcon="icons/desktop.png"# 安装包名称
package=${name}_${version}-${iteration}_${arch}.${type}# 安装包的输出目录
outputDir="packages"# 临时文件目录
temp="temp"# 必要的程序子目录,由开发人员维护
installPath_bin="${installPath}/bin"
installPath_desktop="${installPath}/desktop"
installPath_resources="${installPath}/resources"
installPath_script="${installPath}/script"# 一些必须的安装脚本文件,由开发人员维护
# 这些脚本将由软件包管理器自动调用,详情参见 fpm --help 的输出
afterInstall="after-install.sh"
afterUpgrade="after-upgrade.sh"
beforeRemove="before-remove.sh"
beforeUpgrade="before-upgrade.sh"# 指定 qt 将要加载的 QPA 插件,通常我们都指定 xcb。
# NOTE: 
# 如果我们不指定的话将有可能出现程序无法启动的问题(例如 UOS+Huawei 系统)。
# 详情请参见:https://blog.martin-graesslin.com/blog/2018/03/unsetting-qt_qpa_platform-environment-variable-by-default/
defineQpa="QT_QPA_PLATFORM='xcb'"#-----------------------------------------------------------------------------------------------------------------------------------------
#-----------------------------------------------------------------------------------------------------------------------------------------# 当任何语句出现错误时中断执行
set -ecurData=$(date "+%Y-%-m-%-d-%H%M%S")# -------- 生成一些必要的程序安装文件 start -------- ## 删除上次打包时可能遗留的程序安装目录
rm -rf ./${installPath}
# 生成必要的安装目录
mkdir -p ./${installPath}
mkdir -p ./${installPath_bin}
mkdir -p ./${installPath_desktop}
mkdir -p ./${installPath_resources}
mkdir -p ./${installPath_script}echo "移动源文件至构建目录下..."
# 将待打包的程序文件移至程序安装目录下(为了效率我们选择移动文件而不是复制)
mv ${source}/* ./${installPath_bin}
rm -rf ${source}echo "复制资源文件至构建目录下..."
# 放置相关资源文件至程序的资源目录下
cp -rp ${resourcesPath}/* ./${installPath_resources}/echo "生成 ${startupScript} 脚本..."
# 生成启动脚本,该脚本用于启动程序
cat > ./${installPath_script}/${startupScript} << EOF
#!/bin/bash${defineQpa}# 为保险起见,每次都重新赋值一下权限
chmod -R 777 /${installPath}
cd /${installPath_bin}
./${exe}
EOFecho "生成 ${afterInstall} 脚本..."
# 生成 afterInstall 脚本,该脚本将在程序安装后由软件包管理器自动调用
cat > ./${installPath_script}/${afterInstall} << EOF
#!/bin/bashchmod -R 777 /${installPath}# 生成桌面快捷方式 #
# 我们只创建链接文件,以图方便后续 desktop 的更新deskFileName=${desktopFile}
desktopFile=/${installPath_desktop}/\${deskFileName}if [ -e "\${desktopFile}" ]; thenzhDesktop=/root/桌面enDesktop=/root/Desktopif [ -d "\${zhDesktop}" ]; thenln -sf \${desktopFile} \${zhDesktop}/chmod 777 \${zhDesktop}/\${deskFileName}fiif [ -d "\${enDesktop}" ]; thenln -sf \${desktopFile} \${enDesktop}/chmod 777 \${enDesktop}/\${deskFileName}fifor FILENAME in /home/*; dozhDesktop=\${FILENAME}/桌面enDesktop=\${FILENAME}/Desktopif [ -d "\${zhDesktop}" ]; then			ln -sf \${desktopFile} \${zhDesktop}/chmod 777 \${zhDesktop}/\${deskFileName}fiif [ -d "\${enDesktop}" ]; then			ln -sf \${desktopFile} \${enDesktop}/chmod 777 \${enDesktop}/\${deskFileName}fidone
fiapplications=/usr/share/applications
ln -sf \${desktopFile} \${applications}/
chmod 777 \${applications}/\${deskFileName}
EOFecho "生成 ${afterUpgrade} 脚本..."
# 生成 afterUpgrade 脚本,该脚本将在程序升级后由软件包管理器自动调用
cat > ./${installPath_script}/${afterUpgrade} << EOF
#!/bin/bashchmod -R 777 /${installPath}
EOFecho "生成 ${beforeRemove} 脚本..."
# 生成 beforeRemove 脚本,该脚本将在程序卸载前由软件包管理器自动调用
cat > ./${installPath_script}/${beforeRemove} << EOF
#!/bin/bash# 删除桌面快捷方式 #deskFileName=${desktopFile}
zhDesktop=/root/桌面/\${deskFileName}
enDesktop=/root/Desktop/\${deskFileName}
applications=/usr/share/applications/\${deskFileName}if [ -e "\${zhDesktop}" ]; thenrm -f \${zhDesktop}
fi
if [ -e "\${enDesktop}" ]; thenrm -f \${enDesktop}
fi
if [ -e "\${applications}" ]; thenrm -f \${applications}
fifor FILENAME in /home/*; dozhDesktop=\${FILENAME}/桌面/\${deskFileName}enDesktop=\${FILENAME}/Desktop/\${deskFileName}if [ -e "\${zhDesktop}" ]; thenrm -f \${zhDesktop}fiif [ -e "\${enDesktop}" ]; thenrm -f \${enDesktop}fi
done
EOFecho "生成 ${desktopFile} ..."
# 生成 desktop 文件
cat > ./${installPath_desktop}/${desktopFile} << EOF
#!/usr/bin/env xdg-open
[Desktop Entry]
Name=${name}
Name[zh_CN]=${name_zh}
Comment=${comment}
Comment[zh_CN]=${comment_zh}
GenericName=${name}
GenericName[zh_CN]=${name_zh}
Exec=/${installPath_script}/${startupScript} %u
Icon=/${installPath_resources}/${desktopIcon}
Terminal=false
Type=Application
X-Ubuntu-Touch=true
Categories=Office;
StartupNotify=false
EOF# 为了支持多用户使用,我们直接为程序安装目录赋上 777 权限
chmod 777 -R ./${installPath}# -------- 生成一些必要的程序安装文件 end -------- ## -------- 生成一些必要的临时文件 start -------- ## 删除上次打包时可能遗留的临时目录
rm -rf ./${temp}
mkdir -p ./${temp}createTempScript() 
{fileName=$1
cat > ./${temp}/${fileName} << EOF
#!/bin/bashecho "%{version}-%{release}: exec ${fileName} for arg=\$*"scriptPath=/${installPath_script}
scriptFile=\${scriptPath}/${fileName}if [ -e "\${scriptFile}" ]; thencd \${scriptPath}bash \${scriptFile} \$@
elseecho \${scriptFile} not exist
fi
EOF
}# XXX: 
# 生成打包时引用的安装脚本,这些脚本实际上什么也不做,只是转调程序安装目录下的脚本。
# 这么做是为了让程序能够在安装后对这些脚本进行修改。虽然几乎用不上该特性。
createTempScript ${afterInstall}
createTempScript ${afterUpgrade}
createTempScript ${beforeRemove}
createTempScript ${beforeUpgrade}# -------- 生成一些必要的临时文件 end -------- #mkdir -p ./${outputDir}echo "开始构建安装包..."
# 执行 fpm 打包
fpm -f -s dir -t ${type} -n ${name} -v ${version} --iteration ${iteration} -a ${arch} --after-install ./${temp}/${afterInstall} --before-remove ./${temp}/${beforeRemove} --before-upgrade ./${temp}/${beforeUpgrade} --after-upgrade ./${temp}/${afterUpgrade} --deb-no-default-config-files --log warn --no-auto-depends -p ./${outputDir}/${package} -C . ${installPath}echo "成功构建安装包至 ./${outputDir}/${package}"echo "清理临时文件和构建目录..."
rm -rf ./${installPath}
rm -rf ./${temp}echo "完成"

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/942753.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

低代码如何推动企业敏捷创新与业务赋能

在创新驱动发展的时代,企业需要更快地响应市场变化,更灵活地调整业务策略。然而,传统的软件开发模式往往无法满足这种敏捷性要求。低代码技术的出现,正在改变这一现状,成为推动企业敏捷创新的重要力量。低代码与敏…

hevc解码器下载

如果你使用的是品牌电脑,那电脑重装系统后会自动下载,无需手动安装,连机械革命都会自动安装的 如果不是,那么直接下载最新版(本文截稿于2025/10/21) Microsoft.HEVCVideoExtensions_2.4.23下载 双击打开即可安装…

低代码如何成为企业数字化转型的加速器

在当今快速变化的商业环境中,企业数字化转型已从"选择题"变成了"必答题"。然而,传统软件开发模式的高成本、长周期,让许多企业在数字化转型的道路上步履维艰。这时,低代码技术应运而生,正以其…

2025.10.18 刷题

2025.10.18 刷题1. P14253 旅行(trip) 一眼,区间肯定到结尾 然后从后面扫,随便统计一下个数即可 2. P14254 分割(divide) 刚看很难 再看诈骗 发现限制是要求同等深度,然后最小的必须有两个 然后这个是个独立问题…

[网络] [iproute2] tc命令:Linux网络异常模拟(Network Emulation, netem)指南

[网络] [iproute2] tc命令:Linux网络异常模拟(Network Emulation, netem)指南$(".postTitle2").removeClass("postTitle2").addClass("singleposttitle");目录01 简介02 前提条件2.1…

删除链表的倒数第N个结点-leetcode

题目描述 给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。 示例 1:输入:head = [1,2,3,4,5], n = 2 输出:[1,2,3,5]示例 2: 输入:head = [1], n = 1 输出:[]示例 3: 输入:head = [1,2], n =…

NOI 八

根号分治?+吉司机/扫描线/单调栈A. 先考虑 unordered_map 暴力记录的做法,容易发现 LCM 太大了存不下,状态数也不可接受。 LCM 考虑质因数分解,发现 \(V=300\) ,\(>17\) 的质因数只会至多出现一次。 这样的质…

2025.10.21总结

今天继续看软考相关内容,今天复习了计算机网络相关知识,和程序设计语言基础,还有汇编语言,汇编语言太晦涩难懂了,看了一部分,例题跟着过了一下就过了,系统的学的话需要很长时间,这部分以做题为主吧。 目前也还…

10.18测试

T1 Bug 题目描述 A 君在机缘巧合下得到了一把养蛊神器,于是 A 君希望培养出迄今为止战斗力最强的 Bug。A 君把现有的 \(n\) 个 Bug 排成一个序列 \(a_1, a_2, \dots, a_n\),其中 \(a_i\) 表示第 \(i\) 个 Bug 的战斗…

Day1标签的关系与vs的注释

<html><head></head><body></body> </html>标签之间的关系有两种,嵌套与并列关系,也可形象对的理解为父子与兄弟 在上述代码中,head与body都是html的子标,而head与body则是并…

软件工程学习日志2025.10.21

项目概述 在本次开发任务中,我使用Trae框架成功实现了一个功能完整的即时在线聊天软件。该应用支持文字和图片的实时发送与接收,界面简洁美观,充分体现了现代Web应用的设计理念。 技术架构 前端技术栈 • 核心框架:…

[PaperReading] DeepSeek-OCR: Contexts Optical Compression

目录DeepSeek-OCR: Contexts Optical CompressionTL;DRMethodDeepEncoderDeepDecoderDataExperiment总结与思考相关链接 DeepSeek-OCR: Contexts Optical Compression link 时间:25.10.20 单位:DeepSeek 作者相关工作…

Win10安装WindowsCamera相机

在一些很旧的win10非正式版中,相机可能缺失,很老的win10只能用过时的WindowsCamera相机。这里给出一个安装包,当然新系统也可安装 夸克网盘下载 首先,打开开发者模式(如果有),不然无法安装然后右键打开——以管…

简易的本地部署OI-Wiki方法 for CCSP

在联网环境下执行 git clone https://gitee.com/OI-wiki/OI-wiki.git -b gh-pages拷贝文件后,在离线环境下执行 cd OI-wiki python -m http.server即可本地运行OI-wiki, 默认在localhost:8000上运行

[systemd] 如何为systemd服务进行资源限制

[systemd] 如何为systemd服务进行资源限制$(".postTitle2").removeClass("postTitle2").addClass("singleposttitle");目录01 简介02 查看限制03 可配置的参数3.1 CPU限制3.1.1 CPU时间…

以TrustedInstaller/System用户运行软件

有时电脑上会出现一些不明杀毒软件,直接删除是删不掉的:这时候我们需要TrustedInstaller/System权限,这个软件就派上用场了,这个软件并非漏洞提权,而是administer权限平级运行 警告:使用本工具需要有一定的计算机…

10月21号

今天上午进行了激光工程实训

React Native 启动流程 (Android版)

React Native 启动流程 (Android版)React Native 启动流程 (Android版) 我们从骨架项目MainActivity说起.其继承实现了ReactActivity. 进入MainActivity,先反射MainActivity执行其父类ReactActivity和自己的构造方法。…

NOIP 二十六

区间DPA. 圆心处向周围连边就将整个圆分成了若干个不相关的部分。断环成链,记 \(f[l, r]\) 为 \([l, r]\) 内连通的最小代价,转移考虑是否选择 \((l, r)\) 这条边。 枚举分界点转移。 注意当目前区间大于半圆的时候不…

Say 题选记 (10.19 - 10.25)

P3702 [SDOI2017] 序列计数 首先至少 1 个质数可以容斥成随便选 - 只选合数。然后注意到第二维很小,直接矩阵快速幂即可。Code #include <bits/stdc++.h> using namespace std; const int M = 2e7 + 5, K = 1e2…