背景:
在没有使用 GitLab 和 Jenkins 进行自动化部署的情况下,采用 webhook 自动触发 Git 拉取并重新启动项目。
- 实现方式:
- 使用 FastAPI 定义 webhook 接口,接收来自 GitLab 的推送
- 当 webhook 接收到通知时,使用 subprocess 模块执行命令,拉取代码并结束原有进程,重新启动新的进程
- 在使用
subprocess.run
运行命令启动项目时,由于是在子进程中运行,导致项目无法获取服务器环境变量。然而在服务器使用 Python3 终端获取时却能够正常访问。
- 原因
- 在运行项目时,使用
subprocess.run
方法运行,会有新建一个子进程,然而进程之间有隔离机制所以导致子进程运行的项目无法获取到环境变量,需要在运行项目时传递环境变量 - 进程隔离是操作系统为了保障安全性和稳定性而采取的一种机制。即使在同一台 Linux 服务器上运行,不同的进程之间仍然会受到操作系统的进程隔离。这种隔离确保了各个进程在运行时相互独立、互不干扰,并且提高了系统的安全性和可靠性。
- 在运行项目时,使用
由于每个进程都有自己独立的内存空间和环境变量,因此当使用 subprocess.run
启动一个新的子进程时,该子进程将无法直接访问父进程(即主进程)中设置的环境变量。这是出于安全和隔离的考虑,以防止不同进程之间对环境变量的意外修改及信息泄漏。
为了在子进程中获取父进程的环境变量,需要显式地将环境变量传递给子进程。这样可以保持进程隔离的安全特性,同时允许父子进程之间共享必要的环境信息。
-
解决办法:
为了在子进程中获取父进程的环境变量,需要显式地将环境变量传递给子进程。以下是一个示例代码:
import os
import subprocess
# 在父进程中获取环境变量
env = {'private_path': os.environ.get('private_path'),
'public_path': os.environ.get('public_path')}
# 将父进程中的环境变量的值传递给子进程
subprocess.run("nohup python3 run.py > /usr/local/output.log 2>&1 &", shell=True,
cwd="/usr/local/aggregationservices/interfaceServices", capture_output=True,
text=True, env=env)
# 在Linux终端中设置环境变量
export KEY_PATH=/path/to/your/key
# 使用Python读取环境变量
import os
key_path = os.environ.get('KEY_PATH')
print(key_path)