Capistrano:我可以为整个 cap 会话设置一个环境变量吗?

Posted

技术标签:

【中文标题】Capistrano:我可以为整个 cap 会话设置一个环境变量吗?【英文标题】:Capistrano: Can I set an environment variable for the whole cap session? 【发布时间】:2011-11-27 23:43:23 【问题描述】:

我有一个安装了标准 Ruby 和 Ruby Enterprise 的登台服务器。由于标准 Ruby 拒绝安装关键 gem,我需要设置 $PATH 以便 ruby​​/gem/rake/etc.始终参考 REE 版本。由于我使用 Capistrano 部署到我们的机器上,因此我需要在 Capistrano 中进行部署。

如何设置一次环境变量,并让它在 Capistrano 会话中持续存在?

1) 在 bashrc 文件中很容易做到,但 Capistrano 不读取 bashrc 文件。

2) 我会使用 Capistrano 的

default_environment['PATH'] = 'Whatever'

但 Capistrano 使用这些环境变量,例如

env PATH=Whatever command arg ...

并且每当在传递给 env 的可执行文件中启动另一个 shell 时,它们就会丢失。就像你使用 sudo 时一样。哪一点很重要:

[holt@Michaela trunk]$ env VAR=hello ruby -e "puts ENV['VAR']"
hello
[holt@Michaela trunk]$ env VAR=hello sudo ruby -e "puts ENV['VAR']"
nil

3) 我不能使用 bash 导出命令,因为这些命令也丢失了 - Capistrano 似乎为每个命令(或类似的命令)启动了一个新的 shell,这也丢失了:

cap> export MYVAR=12
[establishing connection(s) to xxx.xxx.xxx.xxx]
cap> echo $MYVAR
 ** [out :: xxx.xxx.xxx.xxx] 
cap> 

4) 我也尝试过使用 Capistrano 的 :shell 和 :pty 选项(并与其他方法结合使用),但也没有运气。

那么 - 这样做的正确方法是什么? 这似乎是一项基本任务,应该有一个非常简单的方法来完成它,但我没有想法。有人吗?

提前致谢!

【问题讨论】:

【参考方案1】:

我有完全相同的问题,但我认为这个解决方案更好:

set :default_environment,  
  'env_var1' => 'value1',
  'env_var2' => 'value2'

这对我来说就像一个魅力。

【讨论】:

嗯,不适合我看***.com/questions/16889642/… 在 Capistrano 3 中是set :default_env, ... 愚蠢的问题,但我正在尝试同样的事情,但它不起作用。无论如何要调试它? 如何将这些放在 .env 文件中?【参考方案2】:

如果您需要在远程主机上设置 PATH 以外的变量,您应该知道出于安全原因,sshd 默认只允许某些/etc/profile~/.bashrc 环境变量。正如楼所说,您可以使用cap shell 并使用cap> printenv 命令,也可以在一个命令中使用cap COMMAND=printenv invoke

如果您在正常 ssh 进入远程 shell 时看到该变量,但在 cap printenv 命令中看不到它,这是一种解决方案:

    在远程服务器的/etc/ssh/sshd_config文件中设置PermitUserEnvironment yes,然后重启sshd 为您正在 ssh 的远程用户编辑 ~/.ssh/environment 文件,并将您的变量作为 VARIABLE=value 放在那里

现在这些应该会在您执行 cap COMMAND=printenv invoke 时出现

【讨论】:

这可能有效,但需要更改 root 权限设置。看我的回答。【参考方案3】:

我认为你实际上有两个问题:

1) 您想更改远程主机上的 PATH。

更改/设置远程主机上 .bashrc 中的路径并运行 cap> printenv,如果您的路径正确,请转到 #2,否则尝试将 export BASH_ENV=~/.bashrc 添加到您的 /etc/profile(小心, ~/.bashrc 将为所有用户的所有非交互式 shell 运行)

2) 您希望 sudo 保留您的 PATH

在远程主机上运行 visudo 并添加:

Defaults        exempt_group = "<your_user>"

【讨论】:

好电话 - 我不知道 sudo 掩盖了本地环境。看起来只是添加 -E 选项可以解决大多数情况,但 $PATH 是特殊的(reference)。我会玩这个多一点,然后回复你。干杯!【参考方案4】:

我需要为特定任务设置一个环境变量才能工作。 “运行”命令允许您传递包括 :env:

在内的选项
run "cmd", :env =>  'name' => 'value' 

就我而言,我想将环境变量添加到我没有编写的任务中,所以我使用了所有 run 调用都使用的 default_run_options。我将此添加到我的 Capfile 的顶部:

default_run_options[:env] =  'name' => 'value' 

【讨论】:

我在其他地方看到过这个解决方案,但我无法让它为我工作 - 我收到一个 NameError: undefined local variable or method default_run_options' for main:Object` 错误。我把那个赋值语句放在我的Capfile 的顶部,在第一个namespace :deploy do 块之前。我可以做些什么不同的事情? 你是如何运行任务的?如果你运行 cap 任务,它应该在加载过程中定义 default_run_options 以便在它到达你的 Capfile 时可用。即使只有一行 Capfile 只是说 default_run_options[:x] = 'y' => 'z' ,我也可以运行 cap shell。【参考方案5】:

我尝试使用@brian-deterling 的技术未成功,该技术在讨论过此问题的其他人中非常常用......也许我做错了什么,但同时我找到了dotenv-rails gem,它非常有效很好地从我的项目根目录中的.env 文件中加载值。

Github repo 上的说明非常简单。我将Dotenv.load 添加到我的config/application.rb

【讨论】:

以上是关于Capistrano:我可以为整个 cap 会话设置一个环境变量吗?的主要内容,如果未能解决你的问题,请参考以下文章

如何从 Capistrano 运行 rake 任务?

Capistrano - 清理旧版本

Capistrano 和几个 SSH 密钥

如何在 Ubuntu 中使用 gem?

为“capistrano-maintenance”gem 配置维护模板路径

如何将 shell 设置为 bash 以在 Capistrano 中运行?