Python 3.5 使用 pyinstaller 生成的可执行文件创建 .rpm
Python 3.5 create .rpm with pyinstaller generated executable
我有一个使用 pyinstaller 生成的构建。
我需要创建 .rpm 包,它将可执行文件放入 /usr/bin/
并创建一个 systemd 服务,它将 运行 该可执行文件。
我找到了这个
https://docs.python.org/3/distutils/builtdist.html and https://docs.python.org/2.0/dist/creating-rpms.html
然而它并没有给我一个完整的画面。
可以做吗
我需要使用什么工具集? (基本上,how
就可以了)。
如果可能 - 示例代码
首先,忘记 bdist_rpm
。它用于 distutils
/setuptools
项目,因此您需要一个 setup.py
脚本在后台调用 pyinstaller
来捆绑可执行文件,以某种方式重新定义 install_scripts
命令能够打包二进制可执行文件并处理 systemd
单元文件的打包。相反,编写一个 spec 文件,它是 rpm
构建和安装包的说明手册。
设置
这是要玩的示例项目。
so-51640995
├── bacon.service
├── bacon.spec
├── bacon.timer
└── spam.py
spam.py
这里没有魔法 - 调用后打印 eggs
。将通过 pyinstaller
捆绑到名为 bacon
的二进制文件中。我没有将项目命名为 spam
以避免歧义,因为 pyinstaller
还创建了一个扩展名为 .spec
的文件,因此 运行 它不会覆盖 rpm 规范文件。
#!/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
与 systemd
单元文件一起安装到 /usr/bin/bacon
。
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 Packaging Guidelines,所以这里只列出最小的命令序列:
$ # 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
测试包
<s>$ sudo rpm -ivp $HOME/rpmbuild/RPMS/x86_64/bacon-1-1.x86_64.rpm</s>
编辑:如评论中所述,使用-U
代替-i
。引自rpm
mans:
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
应该可以从命令行获得:
$ 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
:
$ sudo systemctl stop bacon.timer
$ sudo rpm -e bacon
$ sudo systemctl daemon-reload
$ sudo systemctl reset-failed
我有一个使用 pyinstaller 生成的构建。
我需要创建 .rpm 包,它将可执行文件放入 /usr/bin/
并创建一个 systemd 服务,它将 运行 该可执行文件。
我找到了这个 https://docs.python.org/3/distutils/builtdist.html and https://docs.python.org/2.0/dist/creating-rpms.html
然而它并没有给我一个完整的画面。
可以做吗
我需要使用什么工具集? (基本上,
how
就可以了)。如果可能 - 示例代码
首先,忘记 bdist_rpm
。它用于 distutils
/setuptools
项目,因此您需要一个 setup.py
脚本在后台调用 pyinstaller
来捆绑可执行文件,以某种方式重新定义 install_scripts
命令能够打包二进制可执行文件并处理 systemd
单元文件的打包。相反,编写一个 spec 文件,它是 rpm
构建和安装包的说明手册。
设置
这是要玩的示例项目。
so-51640995
├── bacon.service
├── bacon.spec
├── bacon.timer
└── spam.py
spam.py
这里没有魔法 - 调用后打印 eggs
。将通过 pyinstaller
捆绑到名为 bacon
的二进制文件中。我没有将项目命名为 spam
以避免歧义,因为 pyinstaller
还创建了一个扩展名为 .spec
的文件,因此 运行 它不会覆盖 rpm 规范文件。
#!/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
与 systemd
单元文件一起安装到 /usr/bin/bacon
。
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 Packaging Guidelines,所以这里只列出最小的命令序列:
$ # 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
测试包
<s>$ sudo rpm -ivp $HOME/rpmbuild/RPMS/x86_64/bacon-1-1.x86_64.rpm</s>
编辑:如评论中所述,使用-U
代替-i
。引自rpm
mans:
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
应该可以从命令行获得:
$ 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
:
$ sudo systemctl stop bacon.timer
$ sudo rpm -e bacon
$ sudo systemctl daemon-reload
$ sudo systemctl reset-failed