As web search engines and IRC seems to be of no help, maybe someone here has a helpful idea. I have some service written in python that comes with a .service file for systemd. I now want to build&install a working service file from the software's setup.py. I can override the build/build_py commands of setuptools, however that way I still lack knowledge wrt. the bindir/prefix where my service script will be installed.
Solution
Turns out, if you override the install
command (not the
install_data
!), you will have self.root
and self.install_scripts
(and lots of other self.install_*
). As a result, you can read the
template and write the desired output file after calling super
's
run
method. The fix was inspired by GateOne (which, however
doesn't get the --root
parameter right, you need to strip
self.root
from the beginning of the path to actually make that work
as intended).
As suggested on IRC, the snippet (and my software) no use pkg-config
to get at the systemd path as well. This is a nice improvement
orthogonal to the original problem. The implementation here follows
bley.
def systemd_unit_path():
try:
command = ["pkg-config", "--variable=systemdsystemunitdir", "systemd"]
path = subprocess.check_output(command, stderr=subprocess.STDOUT)
return path.decode().replace('\n', '')
except (subprocess.CalledProcessError, OSError):
return "/lib/systemd/system"
class my_install(install):
_servicefiles = [
'foo/bar.service',
]
def run(self):
install.run(self)
if not self.dry_run:
bindir = self.install_scripts
if bindir.startswith(self.root):
bindir = bindir[len(self.root):]
systemddir = "%s%s" % (self.root, systemd_unit_path())
for servicefile in self._servicefiles:
service = os.path.split(servicefile)[1]
self.announce("Creating %s" % os.path.join(systemddir, service),
level=2)
with open(servicefile) as servicefd:
servicedata = servicefd.read()
with open(os.path.join(systemddir, service), "w") as servicefd:
servicefd.write(servicedata.replace("%BINDIR%", bindir))
Comments, suggestions and improvements, of course, welcome!