如何将shell环境变量传递给Supervisor程序?

时间:2017-08-27 08:27:53

标签: django ansible environment-variables supervisord secret-key

我有一个在Gunicorn上运行的Django应用程序,由SuperibleD管理,由Ansible管理。

我希望Django从环境中读取DJANGO_SECRET_KEY变量,因为我不想将我的密钥存储在配置文件或VCS中。为此,我在settings.py

中读取了环境中的密钥
SECRET_KEY = os.environ['DJANGO_SECRET_KEY']

Supervisor docs它说:

  

注意,子进程将继承用于启动“supervisord”的shell的环境变量,除了在此处重写的那些。请参阅子流程环境。

这是我的supervisor.conf

[program:gunicorn]
command=/.../.virtualenvs/homepage/bin/gunicorn homepage.wsgi -w 1 --bind localhost:8001 --pid /tmp/gunicorn.pid
directory=/.../http/homepage

当我设置变量并从shell运行Gunicorn命令时,它启动就好了:

$ DJANGO_SECRET_KEY=XXX /.../.virtualenvs/homepage/bin/gunicorn homepage.wsgi -w 1 --bind localhost:8001 --pid /tmp/gunicorn.pid

但是,当我在shell中设置变量并重新启动Supervisor服务时,我的应用程序无法启动,找不到有关找不到变量的错误:

$ DJANGO_SECRET_KEY=XXX supervisorctl restart gunicorn
gunicorn: ERROR (not running)
gunicorn: ERROR (spawn error)

查看Supervisor错误日志:

  File "/.../http/homepage/homepage/settings.py", line 21, in <module>
    SECRET_KEY = os.environ['DJANGO_SECRET_KEY']
  File "/.../.virtualenvs/homepage/lib/python2.7/UserDict.py", line 40, in __getitem__
    raise KeyError(key)
KeyError: 'DJANGO_SECRET_KEY'
[2017-08-27 08:22:09 +0000] [19353] [INFO] Worker exiting (pid: 19353)
[2017-08-27 08:22:09 +0000] [19349] [INFO] Shutting down: Master
[2017-08-27 08:22:09 +0000] [19349] [INFO] Reason: Worker failed to boot.

我也尝试重新启动主管服务,但发生了同样的错误:

$ DJANGO_SECRET_KEY=XXX systemctl restart supervisor
...
INFO exited: gunicorn (exit status 3; not expected)

我的问题是如何让Supervisor将环境变量“传递”给它的子进程?

2 个答案:

答案 0 :(得分:0)

创建与此类似的可执行文件并尝试手动启动它。 即在/home/user/start_django.sh

下创建文件和副本脚本

您需要填写DJANGODIR并根据您的情况进行其他调整。此外,您可能需要相应地调整权限。

#!/bin/bash

DJANGODIR=/.../.../..
ENVBIN=/.../.virtualenvs/homepage/bin/bin

# Activate the virtual environment
cd $DJANGODIR
source $ENVBIN/activate

DJANGO_SECRET_KEY=XXX
#define other env variables if you need

# Start your Django
exec gunicorn homepage.wsgi -w 1 --bind localhost:8001 --pid /tmp/gunicorn.pid

如果它手动启动,那么只需在你的conf中使用这个文件。

[program:django_project]
command = /home/user/start_django.sh
user = {your user}
stdout_logfile = /var/log/django.log
redirect_stderr = true
# you can also try to define enviroment variables in this conf
environment=LANG=en_US.UTF-8,LC_ALL=en_US.UTF-8,DJANGO_SECRET_KEY=XXX

可能有帮助的参考,

答案 1 :(得分:0)

好吧我自己弄清楚了。原来ansible有一个名为Vault的功能,它正好用于这类工作 - 加密密钥。

现在我将已保存的密钥添加到ansible的host_vars中,请参阅: Vault: single encrypted variableInventory: Splitting out host and group specific data

我在ansible playbook中添加了一个任务,将密钥文件从ansible vault复制到服务器:

<Style TargetType="ListViewItem">
    <Setter Property="Foreground" Value ="HotPink"/>
</Style>

让Django从该文件中读取秘密:

@Retryable(
    value = { Exception.class },
        maxAttempts = 2,
        backoff=@Backoff(delay = 2000))
@Async
@EventListener

如果有人有更简单/更好的解决方案,请发布,我会接受它作为答案。