如何在supervisor、gunicorn和django(1.6)中使用环境变量

37

我希望配置supervisor以使用环境变量来控制在我的django 1.6项目中的gunicorn。

我在.bashrc文件中设置了我的秘钥,如下:

export SECRET_KEY=[my_secret_key] 

我有一个用于启动gunicorn的shell脚本:

NAME="myproject"
LOGFILE=/home/django/myproject/log/gunicorn.log
LOGDIR=$(dirname $LOGFILE)
NUM_WORKERS=3
DJANGO_WSGI_MODULE=myproject.wsgi

USER=django
GROUP=django
IP=0.0.0.0
PORT=8001

echo "Starting $NAME"

cd /home/django/myproject/myproject
source /home/django/.virtualenvs/myproject/bin/activate

test -d $LOGDIR || mkdir -p $LOGDIR

exec gunicorn ${DJANGO_WSGI_MODULE} \
 --name $NAME \
 --workers $NUM_WORKERS \
 --user=$USER --group=$GROUP \
 --log-level=debug \
 --bind=$IP:$PORT
 --log-file=$LOGFILE 2>>$LOGFILE

然后配置我的项目的gunicorn服务器在supervisor中:

[program:my_django_project]
directory=/home/django/my_django_project/my_django_project
command=/home/django/my_django_project/my_django_project/gunicorn.sh
user=django
autostart=true
autorestart=true
stdout_logfile=/home/django/my_django_project/log/supervisord.log
stderr_logfile=/home/django/my_django_project/log/supervisor_error.log

如果我使用自己的Shell脚本启动Gunicorn,它不会抛出任何错误,但是当我使用Supervisor启动时,它会失败,并且在日志中我看到它找不到我的SECRET_KEY。

如何正确配置Supervisor以读取我的Shell变量(我想将它们保留在我的.bashrc文件中,除非有更合适的方法)?


1
一个进程的环境对系统上的其他用户是可读的,因此这是完全不安全的。将密钥存储在只有进程运行的用户可读的文件中会更加安全。 - AutomatedMike
4个回答

28

好的,我想我明白了。

我曾经尝试包含

environment=SECRET_KEY="secret_key_with_non_alphanumeric_chars"

在 supervisor 的配置文件中,我想使用一个键,但是它不喜欢非字母数字字符,而且我也不想在配置文件中使用我的密钥,因为我已经将其放在了 git 中。

在查看 supervisor 的文档 后,我还尝试了以下方法:

HOME="/home/django", USER="django"

但之前没有起作用。

最后我尝试了这个,现在可以工作了!:

environment=HOME="/home/django", USER="django", SECRET_KEY=$SECRET_KEY

也许尽管它能够工作,但并不是最佳方案。我很乐意学习更多。

编辑:

最终,Ewan 让我看到使用 bash 设置环境变量并不是最佳选择。因此,如 #Ewan 所指出的一种解决方案是使用:

[program:my_project]
...
environment=SECRET_KEY="secret_key_avoiding_%_chars"

另一个解决方案是我发现,对于那些使用虚拟环境的人来说,可以在虚拟环境的"activate"脚本中导出环境变量,也就是编辑您的virtualenv/bin/activate文件并在末尾添加您的SECRET_KEY。

这样,您可以像Django密钥生成器生成的%字符一样,并且如果您不使用supervisor,则此方法有效。

我重启了服务器而没有登录以检查它是否正常工作。通过使用这个选项,我不必修改我的密钥,我可以保留我的配置文件,并且它适用于无论我使用supervisor、upstart还是其他任何东西(或者什么都不用,只是gunicorn)。

无论如何,我知道我没有发现任何新东西(好吧,@Ewan向supervisor提出了一个问题),但我正在学习东西,希望这对其他人有用。


澄清:我将我的conf文件进行版本控制,因为我使用的是Ubuntu软件包,该软件包将配置存储为位于/ etc / supervisor / conf.d /中的单独文件,并且我将在同一台机器上拥有各种项目及其各自的project.conf文件。 - equalium
3
我将我的环境变量放在../bin/activate虚拟环境脚本中,这对我有效。谢谢。 - Aaron Lelevier
1
这个environment=HOME="/home/django", USER="django", SECRET_KEY=$SECRET_KEY在更新的Supervisor版本中不起作用。来自他们的Github:Supervisor 3.2.0(2015年11月30日)支持在environment=_中使用 %(ENV_x)s扩展。 - BringBackCommodore64

11

如果您使用gunicorn配置文件:

gunicorn -c gunicorn.py myproject.wsgi

可以像这样在gunicorn.py文件中传递环境变量:

bind = "0.0.0.0:8001"
workers = 3
proc_name = "myproject"
user = "django"
group = "django"
loglevel = "debug"
errorlog = "/home/django/myproject/log/gunicorn.log"
raw_env = [
   'DATABASE_URL=postgres://user:password@host/dbname',
   'SECRET_KEY=mysecretkey',
]

这样做不会违背同时使用supervisor和gunicorn的初衷吗?Supervisor不是会从一个gunicorn文件中生成不同的Django项目吗?如果是这种情况,那么您提出的解决方案只适用于一个项目。 - BringBackCommodore64
1
@MadisonTrash 我知道这已经有点过时了,但你试过那个吗?我现在正在尝试,但我没有看到任何我设置的 raw_env 传递到 gunicorn 进程的 /proc/<pid>/environ 中(无论是根进程还是生成的进程)。 - Samuel Harmer

6
您的.bashrc只对交互式shell起作用,因此在以您的用户身份运行shell脚本时可以使用,但是在后台运行的supervisor将无法传递这些值。相反,在您的supervsior .ini文件中设置环境变量(更多信息请参见文档)。例如:
[program:my_django_project]
environment=SECRET_KEY="my_secret_key"

经过一番试错,我发现监管员的.ini文件不喜欢在环境变量部分中有%(即使您使用引号引用它...)。根据您在评论中的示例,我已尝试使用通过pip安装的supervisor==3.0并且它有效:

environment=SECRET_KEY="*wi4h$kqxp84f3w6uh8w@l$0(+@x$3cr&)z^lmg+pqw^6wkyi"

只有一个不同,我已经移除了%符号。(我尝试使用\%进行转义,但仍然无法正常工作。)
编辑2:
提出了问题#291来解决这个错误。
编辑3:
如上面的问题中所指出的,如果您的密钥中存在%,则必须按照Python风格进行转义:%%

谢谢Ewan,我找到并发布了一个使用我的.bashrc文件的解决方案。你知道我做的是否在概念上有误吗? - equalium
@equalium - 如果您的服务器在未登录情况下重新启动,则可能会出现问题。它可能不会读取您的.bashrc文件,因此无法设置您的$ SECRET_KEY,从而导致应用程序失败。为了澄清,请阅读此文。 您还可以尝试在Nginx级别上设置环境变量(恐怕我不知道您的非字母数字值是什么,因此无法进行测试)。 - Ewan
有道理!我应该设置一个防弹系统。我的秘钥类型是“*wi4h$kqxp84f3w6uh8w@l$0(+@x$3cr&)z^lmg+pqw^6w%kyi”。如果我执行sudo supervisorctl reread,我会得到:无法重新读取:环境变量的格式字符串'SECRET_KEY="..."'格式不正确。 - equalium
再次感谢@Ewan,干得好。我对supervisor还很陌生,但我正在快速学习。我应该将conf文件排除在版本控制之外,并使用“环境部分”设置我的环境变量,避免使用%字符。 - equalium

1

您可以通过添加另一个 % 字符来转义 % 字符。

否则,引用值是可选的但建议使用。要转义百分号字符,只需使用两个百分号字符。(例如:URI="/first%%20name")

摘自这里:http://supervisord.org/configuration.html


1
这篇文档条目是在上面回答中提到的错误报告的结果。 - weltensturm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接