Refactor service deployment to use direct process execution

- Remove bash wrapper script
- Update systemd service configuration
- Improve process management for gunicorn
- Simplify shared storage cleanup logic
- Update documentation for deployment
This commit is contained in:
yangdx 2025-10-29 18:55:47 +08:00
parent 6489aaa7f0
commit d5bcd14c6f
8 changed files with 40 additions and 53 deletions

View file

@ -1,4 +0,0 @@
#!/bin/bash
source /home/netman/lightrag-xyj/venv/bin/activate
lightrag-server

View file

@ -1,5 +1,5 @@
[Unit]
Description=LightRAG XYJ Ollama Service
Description=LightRAG XYJ Service
After=network.target
[Service]
@ -8,10 +8,20 @@ User=netman
# Memory settings
MemoryHigh=8G
MemoryMax=12G
# Using virtual enviroment created by miniconda
Environment="PATH=/home/netman/miniconda3/bin:/home/netman/lightrag-xyj/venv/bin"
WorkingDirectory=/home/netman/lightrag-xyj
ExecStart=/home/netman/lightrag-xyj/lightrag-api
# ExecStart=/home/netman/lightrag-xyj/venv/bin/lightrag-server
ExecStart=/home/netman/lightrag-xyj/venv/bin/lightrag-gunicorn
# Kill mode require ExecStart must be gunicorn or unvicorn main process
KillMode=process
ExecStop=/bin/kill -s TERM $MAINPID
TimeoutStopSec=60
Restart=always
RestartSec=10
RestartSec=30
[Install]
WantedBy=multi-user.target

View file

@ -184,24 +184,16 @@ MAX_ASYNC=4
### 将 Lightrag 安装为 Linux 服务
从示例文件 `lightrag.service.example` 创建您的服务文件 `lightrag.service`。修改服务文件中的 WorkingDirectory 和 ExecStart
从示例文件 `lightrag.service.example` 创建您的服务文件 `lightrag.service`。修改服务文件中的服务启动定义
```text
Description=LightRAG Ollama Service
WorkingDirectory=<lightrag 安装目录>
ExecStart=<lightrag 安装目录>/lightrag/api/lightrag-api
```
修改您的服务启动脚本:`lightrag-api`。根据需要更改 python 虚拟环境激活命令:
```shell
#!/bin/bash
# 您的 python 虚拟环境激活命令
source /home/netman/lightrag-xyj/venv/bin/activate
# 启动 lightrag api 服务器
lightrag-server
# Set Enviroment to your Python virtual enviroment
Environment="PATH=/home/netman/lightrag-xyj/venv/bin"
WorkingDirectory=/home/netman/lightrag-xyj
# ExecStart=/home/netman/lightrag-xyj/venv/bin/lightrag-server
ExecStart=/home/netman/lightrag-xyj/venv/bin/lightrag-gunicorn
```
> ExecStart命令必须是 lightrag-gunicorn 或 lightrag-server 中的一个,不能使用其它脚本包裹它们。因为停止服务必须要求主进程必须是这两个进程。
安装 LightRAG 服务。如果您的系统是 Ubuntu以下命令将生效

View file

@ -188,24 +188,18 @@ MAX_ASYNC=4
### Install LightRAG as a Linux Service
Create your service file `lightrag.service` from the sample file: `lightrag.service.example`. Modify the `WorkingDirectory` and `ExecStart` in the service file:
Create your service file `lightrag.service` from the sample file: `lightrag.service.example`. Modify the start options the service file:
```text
Description=LightRAG Ollama Service
WorkingDirectory=<lightrag installed directory>
ExecStart=<lightrag installed directory>/lightrag/api/lightrag-api
# Set Enviroment to your Python virtual enviroment
Environment="PATH=/home/netman/lightrag-xyj/venv/bin"
WorkingDirectory=/home/netman/lightrag-xyj
# ExecStart=/home/netman/lightrag-xyj/venv/bin/lightrag-server
ExecStart=/home/netman/lightrag-xyj/venv/bin/lightrag-gunicorn
```
Modify your service startup script: `lightrag-api`. Change your Python virtual environment activation command as needed:
```shell
#!/bin/bash
# your python virtual environment activation
source /home/netman/lightrag-xyj/venv/bin/activate
# start lightrag api server
lightrag-server
```
> The ExecStart command must be either `lightrag-gunicorn` or `lightrag-server`; no wrapper scripts are allowed. This is because service termination requires the main process to be one of these two executables.
Install LightRAG service. If your system is Ubuntu, the following commands will work:

View file

@ -129,11 +129,13 @@ def on_exit(server):
print("=" * 80)
print("GUNICORN MASTER PROCESS: Shutting down")
print(f"Process ID: {os.getpid()}")
print("=" * 80)
# Release shared resources
print("Finalizing shared storage...")
finalize_share_data()
print("Gunicorn shutdown complete")
print("=" * 80)
print("=" * 80)
print("Gunicorn shutdown complete")
print("=" * 80)

View file

@ -326,15 +326,14 @@ def create_app(args):
# Clean up database connections
await rag.finalize_storages()
# In Gunicorn mode with preload_app=True, cleanup is handled by worker_exit/on_exit hooks
# Only perform cleanup in Uvicorn single-process mode
if "LIGHTRAG_GUNICORN_MODE" not in os.environ:
# Clean up shared data
logger.debug("Unvicorn Mode: finalize shared storage...")
# Only perform cleanup in Uvicorn single-process mode
logger.debug("Unvicorn Mode: finalizing shared storage...")
finalize_share_data()
else:
# In Gunicorn mode with preload_app=True, cleanup is handled by on_exit hooks
logger.debug(
"Gunicorn Mode: don not finalize shared storage in worker process"
"Gunicorn Mode: postpone shared storage finalization to master process"
)
# Initialize FastAPI

View file

@ -45,9 +45,7 @@ def main():
check_and_install_dependencies()
# Note: Signal handlers are NOT registered here because:
# - Worker cleanup is handled by gunicorn_config.worker_exit()
# - Master cleanup is handled by gunicorn_config.on_exit()
# This prevents race conditions when multiple processes try to finalize shared data
# - Master cleanup already handled by gunicorn_config.on_exit()
# Display startup information
display_splash_screen(global_args)

View file

@ -1444,7 +1444,7 @@ async def get_namespace_data(
return _shared_dicts[namespace]
def finalize_share_data(shutdown_manager: bool = True):
def finalize_share_data():
"""
Release shared resources and clean up.
@ -1453,10 +1453,6 @@ def finalize_share_data(shutdown_manager: bool = True):
In multi-process mode, it shuts down the Manager and releases all shared objects.
In single-process mode, it simply resets the global variables.
Args:
shutdown_manager: If True, shut down the multiprocessing Manager.
Should be True only for the main process, False for worker processes.
"""
global \
_manager, \
@ -1483,8 +1479,8 @@ def finalize_share_data(shutdown_manager: bool = True):
f"Process {os.getpid()} finalizing storage data (multiprocess={_is_multiprocess})"
)
# In multi-process mode, shut down the Manager only if requested
if _is_multiprocess and _manager is not None and shutdown_manager:
# In multi-process mode, shut down the Manager
if _is_multiprocess and _manager is not None:
try:
# Clear shared resources before shutting down Manager
if _shared_dicts is not None: