Python 3.5 使用 pyinstaller 生成的可执行文件创建 .rpm [英] Python 3.5 create .rpm with pyinstaller generated executable

查看:149
本文介绍了Python 3.5 使用 pyinstaller 生成的可执行文件创建 .rpm的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用 pyinstaller 生成的构建.我需要创建 .rpm 包,它将可执行文件放入 /usr/bin/ 并创建一个将运行该可执行文件的 systemd 服务.

I've got a build generated with a pyinstaller. I need to create .rpm package which will put the executable into the /usr/bin/ and create a systemd service which will run that executable.

我发现了这个https://docs.python.org/3/distutils/builtdist.htmlhttps://docs.python.org/2.0/dist/creating-rpms.html

然而它并没有给我一个完整的画面.

However it doesn't give me a full picture.

  1. 能做到吗?

  1. Is it possible to make it?

我需要使用什么工具集?(基本上,如何制作它).

What toolset do i need to use? (Basically, how to make it).

如果可能 - 示例代码

If possible - sample code

推荐答案

首先,忘记 bdist_rpm.它用于 distutils/setuptools 项目,因此您需要一个 setup.py 脚本来调用 pyinstaller 下的hood 捆绑可执行文件,以某种方式重新定义 install_scripts 命令,以便能够打包二进制可执行文件,并处理 systemd 单元文件的打包.相反,编写一个规范文件,它是 rpm 的说明手册来构建和安装你的包.

First of all, forget about bdist_rpm. It's for a distutils/setuptools project, so you would need a setup.py script that invokes pyinstaller under the hood to bundle the executable, somehow redefines the install_scripts command to be able to package binary executables and also handles the packaging of the systemd unit files. Instead, write a spec file which is the instruction manual for rpm to build and install your package.

这是要使用的示例项目.

This is the example project to play with.

so-51640995
├── bacon.service
├── bacon.spec
├── bacon.timer
└── spam.py

spam.py

这里没有魔法 - 一旦调用就打印 eggs.将通过 pyinstaller 捆绑到一个名为 bacon 的二进制文件中.我没有将项目称为 spam 以避免歧义,因为 pyinstaller 还创建了一个带有 .spec 扩展名的文件,因此运行它不会覆盖 rpm 规范文件.

spam.py

No magic here - prints eggs once called. Will be bundled via pyinstaller to a binary named bacon. I didn't call the project spam to avoid ambiguity, because pyinstaller also creates a file with .spec extension, so that running it does not overwrite the rpm spec file.

#!/usr/bin/env python3

def eggs():
    print('eggs!')


if __name__ == '__main__':
    eggs()

bacon.service

调用二进制bacon的简单服务.

[Unit]
Description=Bacon emitting eggs

[Service]
ExecStart=/usr/bin/bacon
Restart=always

bacon.timer

每十秒调用一次bacon.

[Unit]
Description=Timer for bacon to emit eggs from time to time

[Timer]
OnUnitInactiveSec=10s
OnBootSec=10s
Unit=bacon.service

[Install]
WantedBy=timers.target

bacon.spec

包装说明.在 %build 部分,我们捆绑 spam.py,然后将捆绑的可执行文件 dist/spam 安装到 /usr/bin/bacon 连同 systemd 单元文件.

bacon.spec

The instruction for the package. In %build section, we bundle spam.py, then install the bundled executable dist/spam to /usr/bin/bacon along with the systemd unit files.

Name: bacon
Version: 1
Release: 1
Summary: bacon that shouts 'eggs!' from time to time
License: MIT
Requires: systemd

%description
bacon that shouts 'eggs!' from time to time

%build
pyinstaller --onefile %{_sourcedir}/spam.py

%install
mkdir -p %{buildroot}%{_bindir}
mkdir -p %{buildroot}%{_unitdir}
install -m 755 dist/spam %{buildroot}%{_bindir}/bacon
install -m 755 %{_sourcedir}/bacon.service %{buildroot}%{_unitdir}/bacon.service
install -m 755 %{_sourcedir}/bacon.timer %{buildroot}%{_unitdir}/bacon.timer

%files
%{_bindir}/bacon
%{_unitdir}/bacon.service
%{_unitdir}/bacon.timer

构建包

有很多教程可以深入解释如何构建 rpm 包,例如 Fedora 打包指南,所以只在这里列出最少的命令序列:

build the package

There are lots of tutorials out there that explain building rpm packages in-depth, for example Fedora Packaging Guidelines, so just listing the minimal sequence of commands here:

$ # install the bare minimum of required packages
$ sudo dnf install rpm-build rpm-devel rpmdevtools
$ # first-time setup of build dirs
$ rpmdev-setuptree
$ # copy the source files
$ cp * $HOME/rpmbuild/SOURCES/
$ # invoke the build
$ rpmbuild -ba bacon.spec

测试包

$ sudo rpm -ivp $HOME/rpmbuild/RPMS/x86_64/bacon-1-1.x86_64.rpm

编辑:如评论中所述,使用 -U 代替 -i.引用自 rpm mans:

Edit: as mentioned in the comments, use -U in favor of -i. Quote from the rpm mans:

rpm 升级命令的一般形式是

The general form of an rpm upgrade command is

 rpm {-U|--upgrade} [install-options] PACKAGE_FILE ...

这会将当前安装的软件包升级或安装到较新的版本.这与安装相同,除了在安装新软件包后删除所有其他版本的软件包.

This upgrades or installs the package currently installed to a newer version. This is the same as install, except all other version(s) of the package are removed after the new package is installed.

所以用

$ sudo rpm -Uvp $HOME/rpmbuild/RPMS/x86_64/bacon-1-1.x86_64.rpm

用于测试安装.

现在 bacon 应该可以从命令行使用了:

Now bacon should be available from command line:

$ bacon
eggs!

启动计时器:

$ sudo systemctl start bacon.timer
$ systemctl status bacon.timer
● bacon.timer - Timer for bacon to emit eggs from time to time
   Loaded: loaded (/usr/lib/systemd/system/bacon.timer; disabled; vendor preset: disabled)
   Active: active (waiting) since Tue 2018-08-07 15:36:28 CEST; 29s ago
  Trigger: Tue 2018-08-07 15:36:58 CEST; 979ms left

检查日志:

$ sudo journalctl -u bacon
-- Logs begin at Mon 2017-07-03 12:49:51 CEST, end at Tue 2018-08-07 15:37:02 CEST. --
Aug 07 15:36:28 XXX systemd[1]: Started Bacon emitting eggs.
Aug 07 15:36:28 XXX bacon[128222]: eggs!
Aug 07 15:36:28 XXX systemd[1]: bacon.service: Service hold-off time over, scheduling restart.
Aug 07 15:36:28 XXX systemd[1]: Stopped Bacon emitting eggs.
Aug 07 15:36:28 XXX systemd[1]: Started Bacon emitting eggs.
Aug 07 15:36:28 XXX bacon[128224]: eggs!
Aug 07 15:36:28 XXX systemd[1]: bacon.service: Service hold-off time over, scheduling restart.
Aug 07 15:36:28 XXX systemd[1]: Stopped Bacon emitting eggs.
Aug 07 15:36:28 XXX systemd[1]: Started Bacon emitting eggs.
Aug 07 15:36:29 XXX bacon[128226]: eggs!
...

一旦确认一切正常,停止计时器并卸载bacon:

Once verified things work, stop the timer and uninstall bacon:

$ sudo systemctl stop bacon.timer
$ sudo rpm -e bacon
$ sudo systemctl daemon-reload
$ sudo systemctl reset-failed

这篇关于Python 3.5 使用 pyinstaller 生成的可执行文件创建 .rpm的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆