1

サーバーのセットアップを次のように定義しています。

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/gems/ruby-2.0.0-p0/gems/capistrano-2.14.2/lib/capistrano/configuration/namespaces.rb:193:in method_missing': undefined local variable or methodlog_location' for # (NameError)

  1. その変数にアクセスするにはどうすればよいですか?
  2. このカスタム変数を設定するよりスマートで簡単な方法はありますか?
4

3 に答える 3

1

あなたがそれを読むことができないと言って申し訳ありません。渡されたブロックtask()はサーバー コンテキストでは実行されないため、実際のブロックは、どのサーバー上で動作しているかわかりません。

これに対する長年にわたる古典的な回避策は、次のような構成ファイルをアップロードすることでした。

---
  hostname1:
    log_file_location: "/var/log/hostname1/foo/bar"
  hostname2:
    log_file_location: "/var/log/hostname2/foo/bar"

(または同様のもの) を使用し、構成をロードするときにマシンのホスト名を使用します。

私はこれが素晴らしい回避策ではないことを知っています。そのため、カピストラーノの次のバージョン (Github の v3 ブランチを参照) には、次のような機能があります。

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 ) - SSHKitCapistrano の新しいバックエンド ドライバーです。

v3 ブランチはおそらくまだプライム タイムの準備ができていません。内部的には多くの成功を収めていますが、ドキュメントはまったく存在しませ。しかし、このコードは文字通り桁違いに印象的ではなく、非常に読みやすいと思います。

于 2013-03-26T09:13:14.303 に答える
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
于 2013-03-26T10:45:06.757 に答える
0

実際、変数を引き出すことはできましたがlog_location、1 つの制限がある解決策になりました。

ログの場所を 1 つの環境でのみ使用しています。一度に 1 つのロールに対して 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

これはもっとエレガントにできると確信していますが、私にとってはうまくいきます

于 2013-04-02T20:00:17.670 に答える