[英]Using setup.py to install python project as a systemd service
我有一個 python 項目,我希望能夠使用python setup.py install
類的東西安裝它,以便安裝自動創建一個 systemd 服務。
我遇到了一些麻煩,很可能是正確設置了路徑或導入。
我的環境:
- Ubuntu 15.04
- Python 2.7(盡管讓它也能在 py3 中工作會很棒)。
項目結構:
+ top-folder
+ super_project
+ folder1
__init__.py
file1.py
+ folder2
__init__.py
file2.py
__init__.py
main.py
setup.py
setup.cfg
設置.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}
)
主文件
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()
設置文件
[bdist_wheel]
universal=1
create_service.sh(或多或少):
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
超級項目.服務
[Unit]
Description=Super Description
[Service]
Type=simple
ExecStart=/usr/local/bin/super-service
Restart=always
[Install]
WantedBy=multi-user.target
安裝包會生成以下輸出:
$ 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'
在 /usr/local/bin 中創建super-project
文件:
#!/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')()
)
安裝似乎成功了,雖然:
$ systemctl status super-project.service
● super-project.service
Loaded: not-found (Reason: No such file or directory)
Active: inactive (dead)
我可以在 /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.
可以看出,找不到模塊main
。 這是主要問題。
更改代碼/配置時,我刪除了超級項目/服務,如下所示:
$ 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
另一方面:
/usr/local/bin/
執行$ super-project
,腳本會正確啟動(沒有導入異常),但無法讀取配置文件(很可能是因為相對/絕對路徑問題)。top-folder
(包含項目代碼/文件的文件夾)執行$ super-project
腳本運行完美我錯過了什么? 我花了很多時間搜索可能是什么問題。 似乎在dist-packages
目錄中正確設置了dist-packages
並且一旦執行設置,所有服務文件都已正確創建。
我已經閱讀了有關使用from __future__ import absolute_import
,但我不確定是否必須將其添加到我的 main.py(它不起作用)或我的項目中的所有文件中。
你得到一個ImportError
,因為有問題的模塊不在sys.path
或不可訪問,因為某些文件系統權限。
這是檢查給定分發、組和名稱的文件系統權限的腳本。
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)))
測試;
$ 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
確保您的應用程序可以從其他目錄執行,這似乎是一個經典案例,您假設當前目錄是啟動腳本所在的位置。
它與 systemd 無關。 還嘗試從登錄 shell 外部執行 start 命令(服務未加載您的 .profile)。
對我的所有項目使用不同的方法,我能做的就是簡要說明我是如何做到的。
警告:我專門在linux上工作,我對裝有玻璃或圓形水果的牆壁上的開口一無所知...... :)
創建一個類似的腳本
文件:腳本/超project.bash_completion
eval "$(register-python-argcomplete super-project)"
然后在MANIFEST.in中添加一個include
include scripts/super-project.bash_completion
通常,“超級項目”文件(沒有ext)是這樣的入口點:
file:bin / super-project
#!/usr/bin/env python2.7
from super_project.main import main
if __name__ == '__main__':
main()
else:
raise NotImplementedError
我想這個bin / super-project可以用來加載入口點。
問候。
您需要在super-project.service
文件中設置工作目錄:
WorkingDirectory=/PATH/TO/YOUR/super_project
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.