我正在定义我的服务器设置:
task :test do
role(:frontend) {[server1,server2,server3, {:user=> "frontend-user", :options => {:log_location=>"HOW DO I READ THIS??"}}]}
role(:backend) {...}
role(:db) {...}
role(:mq) {...}
end
task :staging do
role(:frontend) {[server1,server2,server3, {:user=> "frontend-user", :options => {:log_location=>"HOW DO I READ THIS??"}}]}
role(:backend) {...}
role(:db) {...}
role(:mq) {...}
end
task :prod do
role(:frontend) {[server1,server2,server3, {:user=> "frontend-user", :options => {:log_location=>"HOW DO I READ THIS??"}}]}
role(:backend) {...}
role(:db) {...}
role(:mq) {...}
end
这是为了接受传统企业系统的所有复杂性。
现在,从任务开始,我想阅读log_location
。
任务示例:
namespace :log do
desc "list all log files"
task :list do
run %(ls -1 #{log_location}/*/*.log)
end
end
问题是变量log_location
未定义。
。/ RVM /宝石/红宝石2.0.0-P0 /宝石/ Capistrano的-2.14.2 / LIB / Capistrano的/配置/ namespaces.rb:193:在
method_missing': undefined local variable or method
log_location” 对于 #(NameError)
答案 0 :(得分:1)
我很遗憾地说你看不懂。传递给task()
的块不会在服务器上下文中执行,因此该块实际上不知道它在哪个服务器上运行。
多年来经典的解决方法是上传一个如下所示的配置文件:
---
hostname1:
log_file_location: "/var/log/hostname1/foo/bar"
hostname2:
log_file_location: "/var/log/hostname2/foo/bar"
(或类似)并在加载配置时使用计算机主机名。
我知道这不是一个很好的解决方法,因此在即将到来的(参见Github的v3分支)版本的Capistrano中有一个看起来像这样的功能:
host1 = SSHKit::Host.new 'user@example.com'
host2 = SSHKit::Host.new 'user@example.org'
host1.properties = {log_file_location: "/foo/bar"}
host2.properties.log_file_location = "/bar/baz"
on hosts do |host|
target = "/var/www/sites/"
if host.hostname =~ /org/
target += "dotorg"
else
target += "dotcom"
end
execute! :head, '-n 20', host.properties.log_file_location
execute! :git, :clone, "git@git.#{host.hostname}", target
end
(SSHKit Examples) - SSHKit
是Capistrano的新后端驱动程序。
v3分支可能尚未准备好迎接黄金时段,我们在内部取得了很多成功,但文档非常 ahem 不存在。然而,代码实际上是一个不那么强大的代码,我认为你会发现它非常易读。
答案 1 :(得分:0)
你需要这个:https://github.com/capistrano/capistrano/wiki/2.x-Multistage-Extension
这意味着您可以在舞台上命名的单独文件中隔离特定于舞台的代码。如果要在共享deploy.rb中测试阶段名称,也可以这样做:
将它放在deploy.rb
中task :show_stage do
puts(stage)
end
从命令行测试
$ cap staging show_stage
staging
答案 2 :(得分:0)
实际上,我能够提取log_location
变量,但最终得到了一个有一个限制的解决方案:
我只在一个环境中使用日志位置。这在我当前的项目中没有问题,因为我一次只针对一个角色运行capistrano任务。
为了测试此设置,我完成了这项任务:
namespace :support do
desc "Test if the log location variable is correctly fetched from configuration"
task :test_log_location do
find_servers_for_task(current_task).each do |server|
# puts server.host
# puts server.port
# puts server.user
# puts server.options
result = "LOG LOCATION: #{server.options[:log_location]}"
#puts result
logger.info result
end
end
end
然后,对于我在:log命名空间中的任务,我使用set :log_location
定义了变量,并定义了:current_role
变量:
namespace :log do
def set_log_location
#set_log_location
#puts fetch(:log_location)
log_location = nil
options = nil
find_servers_for_task(current_task).each do |server|
# puts server.host
# puts server.port
# puts server.user
# puts server.options
options = server.options
log_location = server.options[:log_location]
#log_location = server.options[:current_role]
end
msg1="FATAL: you need to specify 'ROLES=frontend,backend,mq' (or one of them) from command line"
msg2="FATAL: Could not get log_location from environment/server options. I can only see these options: #{options}"
raise msg1 if ENV['ROLES'].nil?
raise msg2 if log_location.nil?
set :log_location, log_location
set :current_role, ENV['ROLES'].split(',').first
logger.info %(CURRENT_ROLE #{fetch(:current_role)})
logger.info %(THE LOG LOCATION IS: #{fetch(:log_location)})
end
end
最后,我使用了一个单独的方法来完全限定日志路径(我的设置需要 - 也在:log
命名空间中):
def log_location
log_names = {
:frontend => "*/play.log",
:backend => "*Weblogic*/*.{log,out}"
}
loc = "#{fetch(:log_location)}/#{log_names[fetch(:current_role).to_sym]}"
logger.info "using the log location of '#{loc}'"
loc
end
现在,每个任务都可以使用特定的日志位置,如下所示:
desc "list all log files"
task :list do
set_log_location
run %(ls -l #{log_location})
end
我相信这可以做得更优雅,但它适用于我