问题描述
我试图建立一个类似于heroku的系统,在该系统中我将密钥存储在环境变量中,然后从我的rails应用程序中访问它们,如下所示:
secret = ENV['EMAIL_PASSWORD']
我知道heroku可以让您执行heroku config:add EMAIL_PASSWORD=secret
,并且我想为自己的运行nginx和Passenger的ubuntu框做类似的事情。
是否应该在.bashrc
或.bash_login
中将这些变量添加为export
,以便在系统重启时自动设置这些变量?
我不确定何时读入这些文件中的每个文件。
最佳方案
您可以使用dotenv gem加载.env文件作为环境变量。您可以为不同的环境生成.env文件,因此不必将其检入到存储库中。
次佳方案
请记住,nginx可能不在与您相同的环境下运行,通常(通过”Apache”发音)我们通过SetEnv在服务器配置文件中添加env-vars。但是,我认为nginx没有这样的功能……也不需要它。
sudo -E /usr/local/sbin/nginx
在运行nginx时要注意您自己的用户环境变量。
或者,签出env
命令(see here):
env EMAIL_PASSWORD=secret
要回答您的问题,是的,您应该在 shell 程序配置文件中使用export
语句。
第三种方案
This is documented in nginx。运行工作程序时,它将除去TZ
以外的所有环境变量。如果要添加环境变量,请在nginx配置的顶部添加以下内容:
# The top of the configuration usually has things like:
user user-name;
pid pid-file-name;
# Add to this:
env VAR1=value1;
env VAR2=value2;
# OR simply add:
env VAR1;
# To inherit the VAR1 from whatever you set in bash
由于初始化脚本的编写方式,普通的export
或您在bash中执行的任何操作都不能保证传递给nginx(我们不知道它们是否在干净的环境中使用sudo等)。因此,我宁愿将它们放在nginx配置文件本身中,而不要依赖于shell来执行此操作。
编辑:修复链接
第四种方案
(这可能是一个过大的杀伤力,但也许会有用)
注意事项:
环境变量在某种程度上是公共的,并且可以被其他进程轻易地看到,就像在ps(1)
命令中添加了一个选项(如bash中的ps e $$
)或查看/proc/*/environ
一样,尽管现代环境中它们至少都限于同一用户(或root)系统。如果您还有另一个相当简单的选择,请不要依赖于它们是秘密的。
~/.bashrc
是环境变量的错误位置,因为它们可以在登录时一次在~/.bash_login
,〜/.bash_profile或~/.profile
中进行计算,具体取决于您的使用情况,并向下传递给所有后代shell。相反,~/.bashrc
操作倾向于在每次shell调用时重新计算(除非明确禁用)。
将bash代码放入~/.profile
可能会使尝试读取该文件的其他sh依赖的shell和非shell工具混淆,因此让bash特定的~/.bash_login
或-_profile包含bash特定的内容,并使用. ~/.profile
进行更一般的操作(LESS,EDITOR,VISUAL,LC_COLLATE,LS_COLORS等)比其他工具更友好。
~/.profile
中的环境变量应采用旧的伯恩壳格式(VAR=value ; export VAR
)。在Linux上,这通常并不重要,尽管在其他Unixen上,当较旧版本的”sh”尝试读取它们时,这可能是一个大问题。
某些X会话只会读取~/.profile
,而不会读取~/.bash_login
或上述其他会话。有些人会寻找一个需要修改的~/.xsession
文件,以使其具有. $HOME/.profile
(如果还没有)。
可以将System-wide设置放到类似/etc/profile.d/similar-to-heroku.sh
的位置。请注意,仅存在”.sh”,因为该文件将与”.”或”source”一起使用-Shell脚本在任何形式的Unix /Linux中都不应具有command-name扩展名。
ybakos指出,当一个sudo
植根时,大多数环境变量都会消失。类似的问题也会出现在crontab,作业等中。如果有疑问,添加env | sort > /tmp/envvars
或类似的可疑脚本可以真正帮助调试。
请注意,有些发行版具有shell启动脚本,因此它们被扭曲实际上最终违反了bash(1)手册页中给出的顺序。每当您找到默认用户~/.profile
检查$ BASH或$ BASH_VERSION时,您可能就处于以下环境之一,嗯… “interesting”环境中,并且可能必须通读它们以找出控制流向何处去(它们应该是使用bash-specific ~/.bash_profile
或~/.bash_login
,通过引用包含更通用的~/.profile
,从而使bash可执行文件可以工作,而不必在 shell 程序代码中编写$ BASH检查。
~/.bash_profile
(或~/.bash_login
)当然可以包含. ~/.bashrc
,但是环境变量属于~/.bash_profile
(如果为bash-specific)或~/.profile
包含在其中(如果您使用了此方法,那么只要声明了),只要您使用了此功能,就可以了请记住在.bash_profile的. ~/.profile
和其他环境变量之后放置. ~/.bashrc
,以便登录和~/.bashrc
的所有其他调用都可以依赖于已设置的envvar。一个示例~/.bash_profile
:
# .bash_profile
[ -r ~/.profile ] && . ~/.profile # envvars
[ -r ~/.bashrc ] && . ~/.bashrc # functions, per-tty settings, etc.
#---eof
[ -r ... ] && ...
可在任何Bourne Shell后代中使用,并且如果缺少.profile,则不会导致错误/中止(我个人也有~/.profile.d/*.sh
设置,但这完全是可选的练习)。
请注意,bash仅读取找到的这三个文件中的第一个文件:
~/.bash_profile
~/.bash_login
~/.profile
…因此,从bash的角度来看,一旦拥有了一个,其他两个的使用完全在用户的控制之下。
第五种方案
我在/usr/local/bin
文件夹中有一个脚本,该脚本设置了一些环境变量,然后执行Ruby。我在我的(Apache,不是Nginx)conf文件中定义了Ruby的路径,并在/usr/local/bin
中定义了该文件的路径。
例:
#!/bin/sh
# setup env vars here
export FOO=bar
export PATH_TO_FOO=/bar/bin
export PATH=$PATH:PATH_TO_FOO
# and execute Ruby with any arguments passed to this script
exec "/usr/bin/ruby" "$@"
第六种方案
我使用passenger_env_var
命令将它们放在我的Nginx配置中,特别是在应用程序的服务器定义中:
server {
server_name www.foo.com;
root /webapps/foo/public;
passenger_enabled on;
passenger_env_var DATABASE_USERNAME foo_db;
passenger_env_var DATABASE_PASSWORD secret;
passenger_env_var SECRET_KEY_BASE the_secret_keybase;
}
这对我有用。有关更多信息,请参阅轻客乘客docs。