fpm制作deb系统安装包

介绍

由于工作需要制作deb安装包,通过查阅资料记录在此,以制作percona-xtrabackup的deb安装包为例子。

安装fpm

fpm 是 ruby写的,因此系统环境需要ruby,且版本必须大于1.8.5

# centos/redhat
yum -y install ruby rubygems ruby-devel
# debian/ubuntu
apt install ruby-full -y

添加国内源:

gem sources -a http://mirrors.aliyun.com/rubygems/

移除国外源:

gem sources --remove https://rubygems.org/

安装FPM工具:

gem install fpm

查看版本:

fpm -v

目录结构

准备构建所需脚本以及安装包,不同软件请自行增减,此处以percona-xtrabackup为例

percona-xtrabackup/
├── build.sh # 安装percona-xtrabackup脚本
├── fpm.sh # 打包脚本
├── percona-xtrabackup-8.0.25-17.tar.gz # percona-xtrabackup源码包
├── post-install # 安装完成后执行
├── post-uninstall # 卸载完成后执行
├── pre-install # 安装前执行
└── pre-uninstall # 卸载前执行

build.sh

主脚本,安装软件以及打包逻辑都在里面

#!/usr/bin/env bash

BUILD_PATH="/tmp/$PACKAGE"
INSTALL_PATH="/opt/deb/per"
PACKAGE="percona-xtrabackup"
PREFIX="$PACKAGE"
VERSION="8.0.25-17"

os_name=`grep '^ID=' /etc/os-release |awk -F '=' '{print $2}'`
CPU_COUNT=$(python -c "import multiprocessing; print(multiprocessing.cpu_count())") 
ARCH="`uname -m`"

mkdir -p $BUILD_PATH
[ -d "$INSTALL_PATH" ] && { echo $INSTALL_PATH already exists; exit 1; } || { mkdir -p $INSTALL_PATH; }

# 清理打包环境
rm -rf $BUILD_PATH/*

SOURCE_DIR=$(pwd)
tar xvf ${PACKAGE}-${VERSION}.tar.* -C $BUILD_PATH > /dev/null
cd ${BUILD_PATH}/${PACKAGE}-${VERSION}
cmake -DCMAKE_INSTALL_PREFIX=$INSTALL_PATH/$PREFIX  -DWITH_BOOST=PATH-TO-BOOST-LIBRARY -DDOWNLOAD_BOOST=ON -DBUILD_CONFIG=xtrabackup_release -DWITH_MAN_PAGES=OFF -DFORCE_INSOURCE_BUILD=1 && make -j${CPU_COUNT} && make install

cd $SOURCE_DIR

pre-install

#!/usr/bin/env bash
# 安装前执行,比如停掉之前的服务

post-install

#!/usr/bin/env bash
# 安装完成后执行,比如设置环境变量,拷贝配置文件等

pre-uninstall

pre-uninstall脚本运行期间为 程序卸载删除之前,负责结束程序进程解除占用。

#!/usr/bin/env bash
# 卸载前执行,比如停掉之前的服务

post-uninstall

post-uninstall脚本运行期间为

#!/usr/bin/env bash
# 程序卸载删除完成后执行,清理程序残留文件。

fpm.sh

#################### 开始打包deb #####################
# FPM常用参数:
# -s:指定源类型
# -t:指定目标类型,即想要制作为什么包
# -n:指定包的名字
# -v:指定包的版本号
# -C:指定打包的相对路径 
# -d:指定依赖于哪些包
# -f:第二次包时目录下如果有同名安装包存在,则覆盖它
# -p:输出的安装包的目录,不想放在当前目录下就需要指定
# --post-install:软件包安装完成之后所要运行的脚本;同--offer-install
# --pre-install:软件包安装之前所要运行的脚本;同--before-install
# --post-uninstall:软件包卸载完成之后所要运行的脚本;同--offer-remove
# --pre-uninstall:软件包卸载之前所要运行的脚本;同—before-remove

# 有几个地方需要说一下
# -C 值的就是 你的程序安装路径 例如 你程序安装在 /opt/deb/percona-xtrabackup
# 那么 -C 路径就是 /opt/deb 而不是 /opt/deb/percona-xtrabackup 切记
# 因为 fpm 会把 -C 路径下的 所有文件夹都打包了。
# 因此 要保证 -C 路径下 只能有一个你的软件目录,而不能有其他的。
# 列如:-C 为 /opt/deb 此时 deb下有三个文件目录 percona-xtrabackup apaceh php 那么 
# fpm 会把这三个文件全部打包在一起。这不是我们想要,我们只想要单独的percona-xtrabackup。
# 所以要保证 percona-xtrabackup下只有一个文件目录。

# fpm打包后的deb,在安装的时候,安装路径为 -C 路径下的 文件目录为顶级安装路径。
# 也就是说 -C只是一个 打包时候所用的 寻找安装程序位置的路径。
# 安装deb时候 将 -C 转换为 /  也就是 根路径去安装 
# 例如 -C /opt/deb
# 软件为 nginx 此时完整路径为 /opt/deb/nginx
# 安装的时候 其实是安装在 /nginx 直接安装在了根路径下,而不是 /opt/deb下。

# 怎么才能安装在 /opt/deb下呢?
# 这时候就需要 --prefix 参数了。
# --prefix 指定安装软件时候的 绝对路径。
# 例如 指定 --prefix 为 /home/wo/deb
# 那么软件就会安装在 /home/wo/deb/percona-xtrabackup 路径下。

# 软件最终安装好时候的路径 一定要 与 软件编译安装时指定的安装路径一样,不然会有很多的路径错误。
# 例如 nginx 编译时候 指定的安装路径为 -prefix=/opt/deb/percona-xtrabackup
# 那么打包成deb 安装的时候 安装路径一定也要是 /opt/deb/percona-xtrabackup

PACKAGE="percona-xtrbackup"
VERSION="8.0.25"
INSTALL_PATH="/opt/deb/per"
ITERATION=`grep '^ID=' /etc/os-release |awk -F '=' '{print $2}'`

fpm_package() {
    LINUX_VERSION="$ITERATION"
    SCRIPTS_PATH=$(pwd)
    case $LINUX_VERSION in
        ubuntu|debian|uos)
            fpm -f -s dir \
                -t deb \
                -n $PACKAGE \
                -v $VERSION \
                -C $INSTALL_PATH \
                --prefix $INSTALL_PATH \
                --deb-no-default-config-files \
                --iteration $ITERATION \
                --pre-install $SCRIPTS_PATH/pre-install \
                --post-install $SCRIPTS_PATH/post-install \
                --pre-uninstall $SCRIPTS_PATH/pre-uninstall \
                --post-uninstall $SCRIPTS_PATH/post-uninstall
            ;;
        centos|redhat)
            fpm -f -s dir \
                -t $TARGET \
                -n $PACKAGE \
                -v $VERSION \
                -C $INSTALL_PATH \
                --prefix $INSTALL_PATH
                --deb-no-default-config-files \
                --iteration $ITERATION \
                --pre-install $SCRIPTS_PATH/pre-install \
                --post-install $SCRIPTS_PATH/post-install \
                --pre-uninstall $SCRIPTS_PATH/pre-uninstall \
                --post-uninstall $SCRIPTS_PATH/post-uninstall
            ;;
        *)
            echo "Unsupport platform."
            exit 1
    esac
}

fpm_package

安装

# 如果已经安装完成可跳过此步
sh ./build.sh

打包

# 可在脚本中指定已经安装好的目录
root@debian:~/percona-xtrabackup# ./fpm.sh 
Created package {:path=>"percona-xtrbackup_8.0.25-debian_amd64.deb"}

打包完成后会输出deb包路径

测试

dpkg -i nginx-1.20.1.aarch64.deb
/opt/deb/per/percona-xtrabackup/bin/xtrabackup --version