我想将登录密码存储在Django配置中当前用户帐户的文件中。我使用推荐的便携方式获取主文件夹,如:
os.path.expanduser("~")
这在所有环境中都有效,无论是在本地还是在服务器上以gunicorn -D config.wsgi
启动时都适用。
然而,我的问题是我引入了supervisord来控制gunicorn进程,现在这个函数不起作用,只返回/
。
这是supervisord.conf的相关部分
[program:kek_django]
command=.../venv/bin/gunicorn config.wsgi
directory=.../django
user=testuser
在此环境下,os.path.expanduser("〜")变为/
。
你能告诉我如何通过修复环境或用于检测主目录的函数来解决这个问题吗?
注意:操作系统是FreeBSD 10,如果相关的话
更新:os.environ在运行过程中报告以下内容:
'SUPERVISOR_SERVER_URL': 'unix:///var/run/supervisor/supervisor.sock',
'RC_PID': '84177',
'SERVER_SOFTWARE': 'gunicorn/19.3.0',
'SUPERVISOR_ENABLED': '1',
'SUPERVISOR_PROCESS_NAME': 'test_django',
'PWD': '/',
'DJANGO_SETTINGS_MODULE': 'config.settings.production',
'SUPERVISOR_GROUP_NAME': 'test_django',
'PATH': '/sbin:/bin:/usr/sbin:/usr/bin',
'HOME': '/'
答案 0 :(得分:2)
supervisord
的{{3}}文档说:
supervisord
运行子进程时没有执行shell,所以环境变量如USER
,PATH
,HOME
,SHELL
,{{ 1}}等不会更改其默认值或以其他方式重新分配。当您从LOGNAME
以root身份运行程序并且配置中包含supervisord
节时,这一点尤为重要。与user=
不同,cron
不会尝试神圣和覆盖“基本”环境变量,例如supervisord
,USER
,PATH
和HOME
它对LOGNAME
程序配置选项中定义的用户执行setuid
。如果需要为特定程序设置可能由特定用户的shell调用设置的特定程序的环境变量,则必须在user=
程序配置选项中明确执行。设置这些环境变量的示例如下所示。
environment=
所以,这是实际修复。 (如果你动态地构造[program:apache2]
command=/home/chrism/bin/httpd -c "ErrorLog /dev/stdout" -DFOREGROUND
user=chrism
environment=HOME="/home/chrism",USER="chrism"
文件并且需要知道如何动态地查看这些值,我可以解释一下,但这很容易,而且我认为你无论如何都不需要它。)
supervisord.conf
如果这对您没有意义,请考虑:
如果您以root身份运行[program:kek_django]
command=.../venv/bin/gunicorn config.wsgi
directory=.../django
user=testuser
environment=HOME="/home/testuser"
,则它没有supervisord
的{{1}}或其他任何内容。它所做的只是testuser
,它只是改变了它的用户ID;它没有为shell或系统的任何其他部分提供任何设置HOME
变量的机会。大多数类似的工具都有伪造它的解决方法,跟随着setuid(testuser)
工作原理的磨砺脚步,但testuser
故意选择不这样做。
或者,正如Subprocess Environment的文档所说:
在Unix上,如果设置了初始
cron
,则由环境变量HOME替换;否则,通过内置模块pwd在密码目录中查找当前用户的主目录。直接在密码目录中查找初始supervisord
。
快速查看expanduser
表明它以最明显的方式做到了这一点。
因此,您的代码中有三个明显的变通方法:
~
代替~user
(如果需要,您甚至可以通过用户名以编程方式生成)。~testuser
函数,该函数只执行~
而不检查expanduser
。pwd.getpwuid(os.getuid()).pw_dir
,则在启动时手动将HOME
设置为HOME
。