script run python ubuntu setup.py systemd

run - python script as a linux service



Usar setup.py para instalar el proyecto python como un servicio systemd (2)

Asegúrese de que su aplicación se pueda ejecutar desde otros directorios, esto parece un caso clásico en el que se supone que el directorio actual es donde existe el script de inicio.

No tiene nada que ver con systemd. También intente ejecutar el comando de inicio desde fuera de su shell de inicio de sesión (los servicios no cargan su perfil).

Tengo un proyecto de python y quiero poder instalarlo usando algo como python setup.py install para que la instalación cree automáticamente un servicio systemd.

Estoy teniendo problemas, lo más probable es que establezca las rutas o las importaciones correctamente.

Mi entorno:

  • Ubuntu 15.04
  • Python 2.7 (aunque sería genial hacerlo funcionar en py3 también).

Estructura del proyecto:

+ top-folder + super_project + folder1 __init__.py file1.py + folder2 __init__.py file2.py __init__.py main.py setup.py setup.cfg

setup.py:

from setuptools.command.install import install from setuptools import setup, find_packages import subprocess import os class CustomInstallCommand(install): def run(self): install.run(self) current_dir_path = os.path.dirname(os.path.realpath(__file__)) create_service_script_path = os.path.join(current_dir_path, ''super_project'', ''install_scripts'', ''create_service.sh'') subprocess.check_output([create_service_script_path]) setup( name=''super-project'', author=''Myself'', version=''0.0.1'', description=''My Description'', packages=find_packages(exclude=[''contrib'', ''docs'']), # this will create the /usr/local/bin/super-project entrypoint script entry_points={ ''console_scripts'': [ ''super-project = super_project.main:main'' ] }, cmdclass={''install'': CustomInstallCommand} )

main.py

from super_project.folder1.file1 import Class1 from super_project.folder2.file2 import Class2 import logging def main(): logging.info(''Executing super-project...'') (...) logging.info(''super-project execution finished.'') if __name__ == ''__main__'': main()

setup.cfg

[bdist_wheel] universal=1

create_service.sh (más o menos):

SYSTEMD_SCRIPT_DIR=$( cd $(dirname "${BASH_SOURCE:=$0}") && pwd) cp -f "$SYSTEMD_SCRIPT_DIR/super-project.service" /lib/systemd/system chown root:root /lib/systemd/system/super-project.service systemctl daemon-reload systemctl enable super-project.service

super-proyecto.servicio

[Unit] Description=Super Description [Service] Type=simple ExecStart=/usr/local/bin/super-service Restart=always [Install] WantedBy=multi-user.target

La instalación del paquete genera el siguiente resultado:

$ sudo python setup.py install --record files.txt running install running build running build_py copying super_project/main.py - build/lib.linux-x86_64-2.7/super_project running install_lib copying build/lib.linux-x86_64-2.7/super_project/__init__.py - /usr/local/lib/python2.7/dist-packages/super_project copying build/lib.linux-x86_64-2.7/super_project/main.py - /usr/local/lib/python2.7/dist-packages/super_project copying build/lib.linux-x86_64-2.7/super_project/db/__init__.py - /usr/local/lib/python2.7/dist-packages/super_project/db copying build/lib.linux-x86_64-2.7/super_project/db/db_gateway.py - /usr/local/lib/python2.7/dist-packages/super_project/db (...) byte-compiling /usr/local/lib/python2.7/dist-packages/super_project/__init__.py to __init__.pyc byte-compiling /usr/local/lib/python2.7/dist-packages/super_project/main.py to main.pyc byte-compiling /usr/local/lib/python2.7/dist-packages/super_project/db/__init__.py to __init__.pyc byte-compiling /usr/local/lib/python2.7/dist-packages/super_project/db/db_gateway.py to db_gateway.pyc (...) running install_egg_info running egg_info writing requirements to super_project.egg-info/requires.txt writing super_project.egg-info/PKG-INFO writing top-level names to super_project.egg-info/top_level.txt writing dependency_links to super_project.egg-info/dependency_links.txt writing entry points to super_project.egg-info/entry_points.txt reading manifest file ''super_project.egg-info/SOURCES.txt'' writing manifest file ''super_project.egg-info/SOURCES.txt'' Copying super_project.egg-info to /usr/local/lib/python2.7/dist-packages/super_project-0.0.1.egg-info running install_scripts Installing ai-scenario-qa script to /usr/local/bin writing list of installed files to ''files.txt''

El archivo de super-project se crea en / usr / local / bin:

#!/usr/bin/python # EASY-INSTALL-ENTRY-SCRIPT: ''super-project==0.0.1'',''console_scripts'',''super-project'' __requires__ = ''super-project==0.0.1'' import sys from pkg_resources import load_entry_point if __name__ == ''__main__'': sys.exit( load_entry_point(''super-project==0.0.1'', ''console_scripts'', ''super-project'')() )

La instalación parece exitosa, aunque:

$ systemctl status super-project.service ● super-project.service Loaded: not-found (Reason: No such file or directory) Active: inactive (dead)

El error que puedo ver en / var / log / syslog:

Feb 16 20:48:34 systemd[1]: Starting Super Description... Feb 16 20:48:34 super-project[22517]: Traceback (most recent call last): Feb 16 20:48:34 super-project[22517]: File "/usr/local/bin/super-project", line 9, in <module Feb 16 20:48:34 super-project[22517]: load_entry_point(''super-project==0.0.1'', ''console_scripts'', ''super-project'')() Feb 16 20:48:34 super-project[22517]: File "/usr/lib/python2.7/dist-packages/pkg_resources/__init__.py", line 521, in load_entry_point Feb 16 20:48:34 super-project[22517]: return get_distribution(dist).load_entry_point(group, name) Feb 16 20:48:34 super-project[22517]: File "/usr/lib/python2.7/dist-packages/pkg_resources/__init__.py", line 2632, in load_entry_point Feb 16 20:48:34 super-project[22517]: return ep.load() Feb 16 20:48:34 super-project[22517]: File "/usr/lib/python2.7/dist-packages/pkg_resources/__init__.py", line 2312, in load Feb 16 20:48:34 super-project[22517]: return self.resolve() Feb 16 20:48:34 super-project[22517]: File "/usr/lib/python2.7/dist-packages/pkg_resources/__init__.py", line 2318, in resolve Feb 16 20:48:34 super-project[22517]: module = __import__(self.module_name, fromlist=[''__name__''], level=0) Feb 16 20:48:34 super-project[22517]: ImportError: No module named main Feb 16 20:48:34 systemd[1]: super-project.service: main process exited, code=exited, status=1/FLURE Feb 16 20:48:34 systemd[1]: Unit super-project.service entered fled state. Feb 16 20:48:34 systemd[1]: super-project.service failed. Feb 16 20:48:34 systemd[1]: super-project.service holdoff time over, scheduling restart. Feb 16 20:48:34 systemd[1]: start request repeated too quickly for super-project.service Feb 16 20:48:34 systemd[1]: Failed to start Super Description. Feb 16 20:48:34 systemd[1]: Unit super-project.service entered fled state. Feb 16 20:48:34 systemd[1]: super-project.service failed.

Como se puede ver, el módulo main no se puede encontrar . Este es el problema principal.

Al cambiar el código / conf, elimino el superproyecto / servicio de la siguiente manera:

$ sudo systemctl disable super-project.service $ sudo rm -f /lib/systemd/system/super-project.service $ sudo systemctl daemon-reload $ su # cat files.txt | xargs rm -r

Por otra parte:

  • Si ejecuto $ super-project desde /usr/local/bin/ , la secuencia de comandos se inicia correctamente (sin excepción de importación) pero los archivos de configuración no se pueden leer (muy probablemente debido a problemas de ruta relativa / absoluta).
  • Si ejecuto $ super-project desde top-folder (carpeta que contiene el código / archivos del proyecto), el script se ejecuta perfectamente

¿Qué me estoy perdiendo? He pasado mucho tiempo buscando cuál podría ser el problema. Parece que el paquete está configurado correctamente en el directorio dist-packages y todos los archivos de servicio se crean correctamente una vez que se ejecuta la instalación.

He leído cosas sobre el uso from __future__ import absolute_import , pero no estoy seguro si tengo que agregar eso a mi main.py (no funciona) o a todos los archivos en mi proyecto.


Obtiene un ImportError porque el módulo en cuestión no está en sys.path o no es accesible debido a algunos permisos del sistema de archivos.
Aquí hay un script para verificar los permisos del sistema de archivos de una distribución, grupo y nombre dados.

chk_perm.py

from pkg_resources import get_distribution import os import sys dist, group, name = sys.argv[1:] dist = get_distribution(dist) location = dist.location einfo = dist.get_entry_info(group, name) if not einfo: print(''No such group "{}" or name "{}"''.format(group, name)) sys.exit(1) m_name = einfo.module_name path = format(os.path.join(location, *m_name.split(''.''))) path = path if os.access(path, os.F_OK) else ''{}.py''.format(path) print(''If path "{}" exists: {}''.format(path, os.access(path, os.F_OK) if path.endswith(''.py'') else True)) print(''If path "{}" readable: {}''.format(path, os.access(path, os.R_OK)))

Prueba;

$ python chk_perm.py setuptools console_scripts easy_install If path "lib/python2.7/site-packages/setuptools/command/easy_install.py" exists: True If path "lib/python2.7/site-packages/setuptools/command/easy_install.py" readable: True $ foo Traceback (most recent call last): File "bin/foo", line 9, in <module> load_entry_point(''mypkg==0.0.4'', ''console_scripts'', ''foo'')() File "lib/python2.7/site-packages/pkg_resources/__init__.py", line 549, in load_entry_point return get_distribution(dist).load_entry_point(group, name) File "lib/python2.7/site-packages/pkg_resources/__init__.py", line 2542, in load_entry_point return ep.load() File "lib/python2.7/site-packages/pkg_resources/__init__.py", line 2202, in load return self.resolve() File "lib/python2.7/site-packages/pkg_resources/__init__.py", line 2208, in resolve module = __import__(self.module_name, fromlist=[''__name__''], level=0) ImportError: No module named main $ python chk_perm.py mypkg console_scripts foo If path "lib/python2.7/site-packages/pkg/main.py" exists: True If path "lib/python2.7/site-packages/pkg/main.py" readable: False $ ls -l lib/python2.7/site-packages/pkg/main.py -rw-rw---- 1 root root 104 Mar 6 22:52 lib/python2.7/site-packages/pkg/main.py $ sudo chmod o+r lib/python2.7/site-packages/pkg/main.py $ ls -l lib/python2.7/site-packages/pkg/main.py -rw-rw-r-- 1 root root 104 Mar 6 22:52 lib/python2.7/site-packages/pkg/main.py $ python chk_perm.py mypkg console_scripts foo If path "lib/python2.7/site-packages/pkg/main.py" exists: True If path "lib/python2.7/site-packages/pkg/main.py" readable: True $ foo App is running