2013-03-25 40 views
1

訪問serverDefinition選項我定義我的服務器設置是這樣的:Capistrano的如何在代碼

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 

這是擁抱傳統enterpricey系統的所有複雜性。

現在,從一項任務,我想讀log_location

任務例如:

namespace :log do 
    desc "list all log files" 
    task :list do 
    run %(ls -1 #{log_location}/*/*.log) 
    end 
end 

的問題是,可變log_location是未定義的。

/.rvm/gems/ruby-2.0.0-p0/gems/capistrano-2.14.2/lib/capistrano/configuration/namespaces.rb:193:in method_missing': undefined local variable or method log_location」 爲 #( NameError)

  1. 如何訪問該變量?
  2. 是否有更智能/更簡單的方法來設置這個自定義變量?
+0

http://stackoverflow.com/問題/ 2339987 /你如何溝通耙 - 任務可能會有所幫助?或者這太粗糙了? – olleolleolle 2013-03-26 08:49:14

回答

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 '[email protected]' 
host2 = SSHKit::Host.new '[email protected]' 

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, "[email protected]#{host.hostname}", target 
end 

SSHKit Examples) - SSHKit是Capistrano的新後端驅動程序。

v3分支可能還沒有準備好黃金時間,但我們在內部取得了很多成功,但文檔很漂亮ahem不存在。然而,代碼的字面意義不大,而且我認爲你會發現它很可讀。

0

其實RB

task :show_stage do 
    puts(stage) 
end 

測試,我能夠拉出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 

然後,我的任務:登錄名稱空間,我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名稱空間中):

現在

,每個任務可以使用特定的日誌位置是這樣的:

desc "list all log files" 
    task :list do 
    set_log_location 
    run %(ls -l #{log_location}) 
    end 

我相信這是可以做到更優雅,但它爲我工作