如何使用FPM轻松创建多种格式的包
介绍
对于希望以易于使用的方式发布项目的软件开发人员来说,不同 Linux 发行版使用的打包格式可能是一个痛点。 Debian 和 Ubuntu 依赖 .deb
包,而 Fedora 和 RedHat 都使用 .rpm
风格的包系统。 这些是不兼容的,对于那些不熟悉它们的怪癖的人来说,创建它们所需的工具可能相当困难。
虽然发行版的软件包维护者对官方存储库中包含的软件包进行了繁重的工作,但如果您计划在自己的站点上为这些发行版发布软件或需要为您的组织创建软件包,您通常需要自己提供软件包。 传统上,这涉及为每个封装系列学习至少一些工具的工作原理。
为了尽量减少此过程的复杂性,创建了一个名为 fpm
的工具。 使用 fpm
,您可以轻松创建 .deb
和 .rpm
文件,而无需了解它所利用的打包工具的任何命令。 在本指南中,我们将讨论如何使用 fpm
在 Ubuntu 14.04 服务器上创建不同格式的包。
安装 FPM
fpm
工具本身的主要分发方法是作为 Ruby gem。 通过安装 Ruby 开发包和编译其他软件所需的软件构建工具,我们可以让我们的系统准备好安装 fpm
。
首先,更新您的本地包缓存,然后继续进行必备安装:
sudo apt-get update sudo apt-get install ruby-dev build-essential
安装上述软件包后,您可以通过键入以下内容获取 fpm
软件包本身:
sudo gem install fpm
这将在系统级别安装 fpm
并使其可供系统上的任何用户使用。 传统的打包智慧建议您以普通的非 root 用户身份创建包。 如果出现可能影响系统的打包错误,这样会更安全。
您现在应该在您的系统上拥有可用的 fpm
可执行文件。 您可以通过查看该工具丰富的帮助信息来验证这一点:
fpm --help
Intro: This is fpm version 1.2.0 If you think something is wrong, it's probably a bug! :) Please file these here: https://github.com/jordansissel/fpm/issues You can find support on irc (#fpm on freenode irc) or via email with fpm-users@googlegroups.com Usage: fpm [OPTIONS] [ARGS] ... . . .
您现在可以开始构建包了。
熟悉基本的 FPM 功能
fpm
工具非常擅长告诉您完成包构建需要什么。 要了解最基本的要求,您可以调用不带参数的命令:
fpm
Missing required -s flag. What package source did you want? {:level=>:warn} Missing required -t flag. What package output did you want? {:level=>:warn} No parameters given. You need to pass additional command arguments so that I know what you want to build packages from. For example, for '-s dir' you would pass a list of files and directories. For '-s gem' you would pass a one or more gems to package from. As a full example, this will make an rpm of the 'json' rubygem: `fpm -s gem -t rpm json` {:level=>:warn} Fix the above problems, and you'll be rolling packages in no time! {:level=>:fatal}
此输出告诉我们创建包所需提供的基础知识。 一个典型的调用的基本形式如下所示:
fpm -s source_type -t target_type source_name_or_location
源可以是多种类型中的任何一种。 源类型还将规定源名称或位置传递给命令的方式。 我们将在下一节讨论可能的输入和输出格式。
某些格式需要安装与要安装的单个包类型相关的附加帮助实用程序才能进行转换。 由于我们已经安装了 Ruby 基本组件以使 fpm
正常工作,并且由于我们使用的是 Ubuntu 系统,因此应该可以将 Ruby gem 文件转换为 .deb
包。
让我们选择一个常用的gem,比如bundler
。 我们可以通过键入以下命令从位于 rubygems.org 上的 bundler
包创建一个 .deb
包:
fpm -s gem -t deb bundler
Created package {:path=>"rubygem-bundler_1.6.5_all.deb"}
在本地目录中创建了一个名为 rubygem-bundler_1.6.5_all.deb
的文件(您的版本号可能不同)。 我们现在可以像安装任何其他 .deb
包一样安装它:
sudo dpkg -i rubygem-bundler_1.6.5_all.deb
当您检查已安装的 gems 列表时,您会看到我们现在有可用的捆绑程序:
gem list
*** LOCAL GEMS *** arr-pm (0.0.9) backports (3.6.0) bundler (1.6.5) cabin (0.6.1) childprocess (0.5.3) clamp (0.6.3) ffi (1.9.3) fpm (1.2.0) json (1.8.1)
我们可以很容易地使用不同的源或输出格式,但是这些需要我们系统上的一些额外工具来转换格式。 我们稍后会讨论这个。
源格式和目标格式
fpm
工具可以处理很多不同的源和目标格式。 这些都有自己的要求和特点。
如果网上有相对标准的包索引格式(如 rubygems.org 用于 Ruby gem 文件),fpm
能够自动搜索索引并下载必要的文件。 它将首先在当前目录中搜索匹配项,如果没有找到本地匹配项,则在索引中查找。
当前支持以下源类型:
来源类型 | 来源说明 | 如何传递源名称或位置 | 需要额外的软件包 |
---|---|---|---|
目录 | 目录或文件 | 传递本地文件系统上项目文件的绝对或相对路径。 | (没有任何) |
柏油 | 一个 tarball 源码包 | 将路径传递到本地文件系统上 tarball(压缩或未压缩)的位置。 | (没有任何) |
宝石 | 一颗红宝石 | 传递可以在 www.rubygems.org 上找到的 Ruby gem 的名称。 它将自动下载以创建包。 | ruby 、rubygems-integration
|
Python | 一个 Python 包 | 将 Python 包的名称传递给 easy_install 。 在 Python 包索引中搜索名称并自动下载以创建包。
|
python-setuptools
|
梨 | 一个 PHP 扩展 | 传递在 pear.php.net 上找到的 PHP 扩展或应用程序的名称。 创建包时将自动下载相应的文件。 | php-pear
|
盘 | Perl 模块 | 传递在 cpan.org 中找到的 Perl 模块的名称。 这些文件将被自动下载并用于构建包。 | cpanminus
|
压缩 | 压缩目录结构 | 传递包含包的 zip 文件在本地文件系统上的位置。 | zip
|
npm | 一个 Node.js 模块 | 传递 npmjs.org 上指定的节点模块的名称。 该包将被自动下载并用于制作输出包。 | npm
|
osxpkg | 一个 OS X 包 | 传递 OS X 包的本地文件系统上的位置(这仅适用于路径中有 pkgbuild 的 OS X 系统)。
|
pkgbuild (仅适用于 OS X 系统)
|
空的 | (无来源) | 用于创建没有任何实际包的包。 这最常用于仅包含依赖项的元包。 | (没有任何) |
deb | 一个.deb 包
|
传递本地文件系统上的 .deb 文件的位置。
|
(在基于 Debian 的系统上没有) |
转数 | .rpm 包
|
传递本地文件系统上 .rpm 文件的位置。
|
rpm
|
您希望创建的目标包装格式也有很多选项。 下表描述了一些不同的选项:
输出类型 | 输出说明 | 需要额外的软件包 |
---|---|---|
deb | 可以安装在 Debian 或 Ubuntu 系统上的 Debian 风格的软件包。 | (在基于 Debian 的系统上没有) |
转数 | 可以安装在 CentOS、Fedora 或 RedHat 系统上的 RedHat 风格的软件包。 | rpm
|
压缩 | 包含输入包的目录和文件结构的 zip 文件。 | zip
|
柏油 | 输入包的目录结构的 tarball(压缩或未压缩)。 | (没有任何) |
目录 | 提取输入包的目录。 | (没有任何) |
嘘 | 一个自解压的 .sh 文件。 这是一个带有 bzip 压缩的 tar 文件的 shell 脚本,运行时将被解压缩。
|
(没有任何) |
osxpkg | OS X 的包文件。 您必须在安装了 pkgbuild 的 OS X 安装上工作才能创建这些包。
|
pkgbuild (仅适用于 OS X 系统)
|
太阳能 | 适合安装在 Solaris 系统上的软件包。 您必须安装 pkgproto 和 pkgmk ,它们仅在 Solaris 机器上可用。
|
pkgproto 、pkgmk (仅在 Solaris 系统上可用)
|
包金 | 适合安装在 BSD 系统上的软件包。 您必须安装 pkg_create 软件包,该软件包仅在 BSD 系统上可用。
|
pkg_create (仅适用于 BSD 系统)
|
木偶 | 可用于安装在各种系统上的 puppet 模块。 (注意:此格式在当前版本的 fpm 中无法正常工作)。 | (非工作状态下无法测试) |
如您所见,源规范和目标规范的某些格式要求您使用特定的操作系统。 由于我们在 Ubuntu 14.04 上演示此工具,因此 osxpkg
源格式以及 osxpkg
、solaris
和 pkgin
输出格式将不可用。
使用选项改变 FPM 行为
使用上节表格中的信息,您应该能够使用 fpm
默认设置创建一些基本包。 但是,大多数时候,您需要提供一些额外的信息来塑造生成的包。
选项应该在指定原始包的位置或名称的源参数之前指定。
fpm
有 许多 不同的选项可用。 我们将只介绍下面一些较常见的。 如需完整列表,请查看 fpm --help
命令。
您可能希望使用的一些常见选项是:
- -C:指定在查找文件之前要更改的目录。
- –prefix:一个目录路径,指定生成的包中的文件将被安装到哪里。
- -p:你的包的包名和路径。 这可以覆盖生成的包文件的文件名。
- -n:您希望用于包的名称。 这是您平台的打包工具中显示的名称。
- -v:你希望用于你的包的版本号。
- –iteration:包的发布信息。 这个数字的发行版名称各不相同,但它通常是一种跟踪包版本的方法,而不是应用程序的版本。
- –license:包的许可名称。 这将在包的元数据中包含许可证类型,但不会在包本身中包含相关的许可证文件。
- –category:这个包所属的类别。 这可用于在 repos 中组织包。
- -d:这个可以多次使用来指定包的依赖关系。
- –provides:可以用来指定这个包提供的系统功能。 这通常在有多个选择来满足要求时使用。
- –conflicts:用于指定不能安装的包。
- –replaces:用于指定安装此包时应删除的包。
- –config-files:用于将包内的文件标记为配置文件。 通常,包管理器会在删除包时将这些原封不动地保留下来。
- –directories:将目录标记为包拥有。
- -a:指定包的架构。
- -m:覆盖包维护者字段。 默认情况下,此字段将使用
username@host
。 - -e:在构建包之前手动查看和编辑规范文件。 这可用于调整已用于包规范的任何默认值。
- –description:设置包的描述。
- –after-install, –before-install, –after-remove, –before-remove: 应该运行的脚本文件在适当的时候。
还有很多特定于您选择的包装格式的选项。 如需完整列表,请查看帮助。
定制包
如果您想自定义更多细节并且不希望将一种格式直接转换为您的输出格式,您可能需要采用不同的工作流程。
这个过程将更接近地反映传统包装,但也将提供能够快速生成多种输出格式的好处。 我们可以在下面演示一般工作流程,假设有问题的应用程序使用标准的 ./configure
、make
、make install
编译和安装过程。
首先,安装包所需的所有依赖项。 然后,从其网站获取项目的源代码包并将其放在工作目录中:
mkdir ~/build cd ~/build wget http://example.com/project.tar.gz
现在,您可以提取文件并更改为生成的目录:
tar xzvf project.tar.gz cd project
在此目录中,您将拥有要打包的应用程序的源文件。 您现在有机会对文件进行一些调整并配置一些选项。
在构建过程中指定选项的常规方法是使用包含的 ./configure
脚本。 查看项目的文档以了解可用的编译选项。 您可以通过使用您的选项调用 configure
脚本来指定它们:
./configure --compilation_option=value --another_option=value --optional_flag ...
这将创建或修改在构建包时由 make
命令读取的文件。 我们现在可以通过键入以下内容来创建实际的安装文件:
make
我们不会安装我们在系统上配置的这些文件,而是将它们安装到一个空的虚拟目录中,我们可以从中构建一个真正的包。 创建一个目录以将软件包安装到:
mkdir -p /tmp/project
我们可以通过将 DESTDIR
选项传递给 make install
来将此新目录标记为根安装位置:
make DESTDIR=/tmp/project install
我们的包现在已经被干净地安装到一个空的骨架目录中。 它创建了所有必要的目录结构,但该目录中没有与包无关的内容。
这是您自定义设置的第二次机会。 如果您希望在安装层次结构中包含其他文件,您现在可以将它们添加到此结构中的适当位置。
准备好后,可以使用 fpm
创建相应的包文件。 例如,我们可以在 fpm
命令中传递一些版本信息和包的描述。 我们还可以列出依赖信息或提供将影响打包元文件创建的其他详细信息。
我们可以使用目录结构来构建多种打包格式。 例如,我们可以通过键入以下内容创建一个 .deb
包:
fpm -s dir -t deb -C /tmp/project --name project_name --version 1.0.0 --iteration 1 --depends debian_dependency1 --description "A sample package" .
这将在当前目录中创建一个名为 project-name_1.0.0-1_amd64.deb
的包。
然后,您可以修改一些选项来创建 .rpm
包(假设您从存储库安装了 rpm
包):
fpm -s dir -t rpm -C /tmp/project --name project_name --version 1.0.0 --iteration 1 --depends redhat_dependency1 --description "A sample package" .
这将在您的当前目录中创建一个名为 project_name-1.0.0-1.x86_64.rpm
的包。
如您所见,使用 fpm
创建自定义包相当容易。 大多数困难的任务仍然由该工具处理。
结论
使用 fpm
可以让您在尝试创建包以在您的基础架构中使用或分发项目的可公开下载包时更轻松。 尽管出于政策考虑,它可能不是打包实际发行版存储库的理想解决方案,但它的优势在许多情况下都很有吸引力。