问题
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.
I found this https://docs.python.org/3/distutils/builtdist.html and https://docs.python.org/2.0/dist/creating-rpms.html
However it doesn't give me a full picture.
Is it possible to make it?
What toolset do i need to use? (Basically,
how
to make it).If possible - sample code
回答1:
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.
setup
This is the example project to play with.
so-51640995
├── bacon.service
├── bacon.spec
├── bacon.timer
└── spam.py
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
Simple service calling the binary bacon
.
[Unit]
Description=Bacon emitting eggs
[Service]
ExecStart=/usr/bin/bacon
Restart=always
bacon.timer
Will call bacon
every ten seconds.
[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
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
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
test the package
$ sudo rpm -ivp $HOME/rpmbuild/RPMS/x86_64/bacon-1-1.x86_64.rpm
Edit: as mentioned in the comments, use -U
in favor of -i
. Quote from the 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.
So use
$ sudo rpm -Uvp $HOME/rpmbuild/RPMS/x86_64/bacon-1-1.x86_64.rpm
for test installation.
Now bacon
should be available from command line:
$ bacon
eggs!
Start the timer:
$ 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
Check the logs:
$ 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!
...
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
来源:https://stackoverflow.com/questions/51640995/python-3-5-create-rpm-with-pyinstaller-generated-executable