mirror of
https://github.com/capistrano/capistrano
synced 2023-03-27 23:21:18 -04:00
Don't use Jekyll plugins
This commit is contained in:
parent
0d09d38e70
commit
260eba996c
47 changed files with 1617 additions and 1743 deletions
|
@ -1,5 +1,7 @@
|
|||
name: Capistrano
|
||||
pygments: true
|
||||
safe: true
|
||||
lsi: false
|
||||
markdown: redcarpet
|
||||
redcarpet:
|
||||
extensions: ["no_intra_emphasis", "fenced_code_blocks", "autolink", "tables", "with_toc_data"]
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
<link rel="stylesheet" href="/css/capistrano.css">
|
||||
<link rel="stylesheet" href="/css/social_foundicons.css" />
|
||||
<link rel="stylesheet" href="/css/okaidia.css">
|
||||
<link rel="stylesheet" href="/css/syntax.css">
|
||||
<script src="/js/vendor/custom.modernizr.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
require 'git'
|
||||
|
||||
module Jekyll
|
||||
class GitActivityTag < Liquid::Tag
|
||||
|
||||
def initialize(tag_name, text, tokens)
|
||||
super
|
||||
end
|
||||
|
||||
def render(context)
|
||||
result = ""
|
||||
g = Git.open(File.join(Dir.getwd, ".."))
|
||||
|
||||
index = 0
|
||||
g.log.each do |log|
|
||||
if(index < 10)
|
||||
result << "<li>"
|
||||
result << log.date.strftime("%d %b")
|
||||
result << " - <a href='https://github.com/capistrano/capistrano-documentation/commit/"
|
||||
result << log.sha
|
||||
result << "/'>"
|
||||
result << log.message
|
||||
result << "</a></li>"
|
||||
index += 1
|
||||
end
|
||||
end
|
||||
"<ul>#{result}</ul>"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Liquid::Template.register_tag('gitactivity', Jekyll::GitActivityTag)
|
|
@ -1,49 +0,0 @@
|
|||
require 'unindent'
|
||||
|
||||
module Jekyll
|
||||
|
||||
class PrismBlock < Liquid::Block
|
||||
include Liquid::StandardFilters
|
||||
|
||||
OPTIONS_SYNTAX = %r{^([a-zA-Z0-9.+#-]+)((\s+\w+(=[0-9,-]+)?)*)$}
|
||||
|
||||
def initialize(tag_name, markup, tokens)
|
||||
super
|
||||
if markup.strip =~ OPTIONS_SYNTAX
|
||||
@lang = $1
|
||||
if defined?($2) && $2 != ''
|
||||
tmp_options = {}
|
||||
$2.split.each do |opt|
|
||||
key, value = opt.split('=')
|
||||
if value.nil?
|
||||
value = true
|
||||
end
|
||||
tmp_options[key] = value
|
||||
end
|
||||
@options = tmp_options
|
||||
else
|
||||
@options = { "linenos" => "" }
|
||||
end
|
||||
else
|
||||
raise SyntaxError.new("Syntax Error in 'prism' - Valid syntax: prism <lang> [linenos(='1-5')]")
|
||||
end
|
||||
end
|
||||
|
||||
def render(context)
|
||||
code = h(super.unindent!).strip
|
||||
|
||||
if @options["linenos"] == true
|
||||
@options["linenos"] = "1-#{code.lines.count}"
|
||||
end
|
||||
|
||||
<<-HTML
|
||||
<div>
|
||||
<pre data-line='#{@options["linenos"]}'><code class='language-#{@lang}'>#{code}</code></pre>
|
||||
</div>
|
||||
HTML
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
Liquid::Template.register_tag('prism', Jekyll::PrismBlock)
|
|
@ -1,30 +0,0 @@
|
|||
require 'git'
|
||||
|
||||
module Jekyll
|
||||
class TableOfContentsTag < Liquid::Tag
|
||||
def initialize(tag_name, text, tokens)
|
||||
super
|
||||
end
|
||||
def render(context)
|
||||
result = ""
|
||||
g = Git.open(File.join(Dir.getwd, ".."))
|
||||
|
||||
index = 0
|
||||
g.log.each do |log|
|
||||
if(index < 10)
|
||||
result << "<li>"
|
||||
result << log.date.strftime("%d %b")
|
||||
result << " - <a href='https://github.com/capistrano/capistrano-documentation/commit/"
|
||||
result << log.sha
|
||||
result << "/'>"
|
||||
result << log.message
|
||||
result << "</a></li>"
|
||||
index += 1
|
||||
end
|
||||
end
|
||||
"<ul>#{result}</ul>"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Liquid::Template.register_tag('table_of_contents', Jekyll::TableOfContentsTag)
|
|
@ -111,7 +111,7 @@ acompanying documentation if you want to explore that any further.
|
|||
The guiding principle is dependency resolution, and interoperability with
|
||||
other tools, for example:
|
||||
|
||||
{% prism ruby %}
|
||||
{% highlight ruby %}
|
||||
# Capistrano 3.0.x
|
||||
task :notify do
|
||||
this_release_tag = sh("git describe --abbrev=0 --tags")
|
||||
|
@ -126,7 +126,7 @@ other tools, for example:
|
|||
namespace :deploy
|
||||
task default: :notify
|
||||
end
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
The last three lines rely on Rake's additive task declaration, by redefining the
|
||||
`deploy:default` task by adding another dependency. Rake will automatically
|
||||
|
@ -148,9 +148,9 @@ conventions established in the examples we created for you.
|
|||
To create different stages at installation time, simply set the `STAGES`
|
||||
environmental variable to a comma separated list of stages:
|
||||
|
||||
{% prism bash %}
|
||||
{% highlight bash %}
|
||||
$ cap install STAGES=staging,production,ci,qa
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
#### Parallelism
|
||||
|
||||
|
@ -158,7 +158,7 @@ In former versions of Capistrano there was a *parallel* option to run
|
|||
different tasks differently on groups of servers, it looked something like
|
||||
this:
|
||||
|
||||
{% prism ruby %}
|
||||
{% highlight ruby %}
|
||||
# Capistrano 2.0.x
|
||||
task :restart do
|
||||
parallel do |session|
|
||||
|
@ -167,7 +167,7 @@ this:
|
|||
session.else "echo nothing to do"
|
||||
end
|
||||
end
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
This always felt a little unclean, and indeed it's a hack that was originally
|
||||
implemeted to facilitate rolling deployments at a large German firm by a
|
||||
|
@ -176,7 +176,7 @@ went on to found Travis-CI!)
|
|||
|
||||
The equivalent code in under Capistrano v3 would look like this:
|
||||
|
||||
{% prism ruby %}
|
||||
{% highlight ruby %}
|
||||
# Capistrano 3.0.x
|
||||
task :restart do
|
||||
on :all, in: :parallel do |host|
|
||||
|
@ -190,7 +190,7 @@ The equivalent code in under Capistrano v3 would look like this:
|
|||
end
|
||||
end
|
||||
end
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
The second block of code, that representing the new Rake derived DSL and
|
||||
demonstrating how to use the parallel execution mode is a little longer, but I
|
||||
|
@ -200,7 +200,7 @@ built-in logging subsystem, keep reading to learn more.
|
|||
|
||||
Other modes for parallelism include:
|
||||
|
||||
{% prism ruby %}
|
||||
{% highlight ruby %}
|
||||
# Capistrano 3.0.x
|
||||
on :all, in: :groups, max: 3, wait: 5 do
|
||||
# Take all servers, in groups of three which execute in parallel
|
||||
|
@ -220,7 +220,7 @@ Other modes for parallelism include:
|
|||
# the block in parallel on all servers. This might be perfect for kicking
|
||||
# off something like a Git checkout or similar.
|
||||
end
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
The internal tasks, for standard deploy recipes make use of all of these as is
|
||||
appropriate for the normal case, no need to be afraid of scary slow deploys
|
||||
|
@ -276,7 +276,7 @@ both connections.
|
|||
This cleanup routine can now be better implemented as follows (which is
|
||||
actually more or less the actual implementation in the the new Gem):
|
||||
|
||||
{% prism ruby %}
|
||||
{% highlight ruby %}
|
||||
# Capistrano 3.0.x
|
||||
desc "Cleanup all old releases (keeps #{fetch(:releases_to_keep_on_cleanup)}
|
||||
old releases"
|
||||
|
@ -288,7 +288,7 @@ actually more or less the actual implementation in the the new Gem):
|
|||
execute :rm, fetch(:releases_directory).join(r)
|
||||
end
|
||||
end
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
Some handy things to note here are that both server one and server two in our
|
||||
contrived example will both evaluate that independently, and when both servers
|
||||
|
@ -315,16 +315,16 @@ your application.
|
|||
|
||||
An example of it's usage might be:
|
||||
|
||||
{% prism ruby %}
|
||||
{% highlight ruby %}
|
||||
h = SSHKit::Host.new 'example.com'
|
||||
h.properties.roles ||= %i{wep app}
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
#### More Expressive Command Language
|
||||
|
||||
In Capistrano v2, it wasn't uncommon to find commands such as:
|
||||
|
||||
{% prism ruby %}
|
||||
{% highlight ruby %}
|
||||
# Capistrano 2.0.x
|
||||
task :precompile, :roles => lambda { assets_role }, :except => { :no_release => true } do
|
||||
run <<-CMD.compact
|
||||
|
@ -332,11 +332,11 @@ In Capistrano v2, it wasn't uncommon to find commands such as:
|
|||
RAILS_ENV=#{rails_env.to_s.shellescape} #{asset_env} #{rake} assets:precompile
|
||||
CMD
|
||||
end
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
In Capistrano v3 this looks more like this:
|
||||
|
||||
{% prism ruby %}
|
||||
{% highlight ruby %}
|
||||
# Capistrano 3.0.x
|
||||
task :precompile do
|
||||
on :sprockets_asset_host, reject: lambda { |h| h.properties.no_release } do
|
||||
|
@ -347,7 +347,7 @@ In Capistrano v3 this looks more like this:
|
|||
end
|
||||
end
|
||||
end
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
Again, with other examples this format is a little longer, but much more
|
||||
expressive, and all the nightmare of shell escaping is handled interally for
|
||||
|
@ -393,14 +393,14 @@ from Capistrano.
|
|||
SSHkit is ideal for use if you need to just connect to a machine and run some
|
||||
arbitrary command, for example:
|
||||
|
||||
{% prism ruby %}
|
||||
{% highlight ruby %}
|
||||
# Rakefile (even without Capistrano loaded)
|
||||
require 'sshkit'
|
||||
desc "Check the uptime of example.com"
|
||||
task :uptime do |h|
|
||||
execute :uptime
|
||||
end
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
There is much more than can be done with SSHKit, and we have quite an
|
||||
extensive [list of
|
||||
|
@ -416,10 +416,10 @@ from preceedings, there is a so-called command map for commands.
|
|||
|
||||
When executing something like:
|
||||
|
||||
{% prism ruby %}
|
||||
{% highlight ruby %}
|
||||
# Capistrano 2.0.x
|
||||
execute "git clone ........ ......."
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
The command is passed through to the remote server *completely unchanged*.
|
||||
This includes the options which might be set, such as user, directory, and
|
||||
|
@ -428,7 +428,7 @@ allow people to write non-trivial commands in
|
|||
[heredocs](https://en.wikipedia.org/wiki/Here_document) when the need arises,
|
||||
for example:
|
||||
|
||||
{% prism ruby %}
|
||||
{% highlight ruby %}
|
||||
# Capistrano 3.0.x
|
||||
execute <<-EOBLOCK
|
||||
# All of this block is interpreted as Bash script
|
||||
|
@ -437,27 +437,27 @@ for example:
|
|||
chmod 0644 /tmp/somefile
|
||||
end
|
||||
EOBLOCK
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
**Caveat:** The SSHKit multiline command sanitizing logic will remove line feeds and add an `;` after each line to separate the commands. So make sure you are not putting a newline between `then` and the following command.
|
||||
|
||||
The idiomatic way to write that command in Capistrano v3 is to use the
|
||||
separated variadaric method to specify the command:
|
||||
|
||||
{% prism ruby %}
|
||||
{% highlight ruby %}
|
||||
# Capistrano 3.0.x
|
||||
execute :git, :clone, "........", "......."
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
... or for the larger example
|
||||
|
||||
{% prism ruby %}
|
||||
{% highlight ruby %}
|
||||
# Capistrano 3.0.x
|
||||
file = '/tmp/somefile'
|
||||
unless test("-e #{file}")
|
||||
execute :touch, file
|
||||
end
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
In this way the *command map* is consulted, the command map maps all unknown
|
||||
commands (which in this case is `git`, the rest of the line are *arguments* to
|
||||
|
@ -469,14 +469,14 @@ indirectly) to determine which `git` to run.
|
|||
Commands such as `rake` and `rails` are often better prefixed by `bundle
|
||||
exec`, and in this case could be mapped to:
|
||||
|
||||
{% prism ruby %}
|
||||
{% highlight ruby %}
|
||||
SSHKit.config.command_map[:rake] = "bundle exec rake"
|
||||
SSHKit.config.command_map[:rails] = "bundle exec rails"
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
There can also be a `lambda` or `Proc` applied in place of the mapping like so:
|
||||
|
||||
{% prism ruby %}
|
||||
{% highlight ruby %}
|
||||
SSHKit.config.command_map = Hash.new do |hash, key|
|
||||
if %i{rails rake bundle clockwork heroku}.include?(key.to_sym)
|
||||
hash[key] = "/usr/bin/env bundle exec #{key}"
|
||||
|
@ -484,7 +484,7 @@ There can also be a `lambda` or `Proc` applied in place of the mapping like so:
|
|||
hash[key] = "/usr/bin/env #{key}"
|
||||
end
|
||||
end
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
Between these two options there should be quite powerful options to map
|
||||
commands in your environment without having to override internal tasks from
|
||||
|
@ -493,7 +493,7 @@ Capistrano just because a path is different, or a binary has a different name.
|
|||
This can also be *slightly* abused in environments where *shim* executables
|
||||
are used, for example `rbenv` *wrappers*:
|
||||
|
||||
{% prism ruby %}
|
||||
{% highlight ruby %}
|
||||
SSHKit.config.command_map = Hash.new do |hash, key|
|
||||
if %i{rails rake bundle clockwork heroku}.include?(key.to_sym)
|
||||
hash[key] = "/usr/bin/env myproject_bundle exec myproject_#{key}"
|
||||
|
@ -501,7 +501,7 @@ are used, for example `rbenv` *wrappers*:
|
|||
hash[key] = "/usr/bin/env #{key}"
|
||||
end
|
||||
end
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
The above assumes that you have done something like `rbenv wrapper default
|
||||
myproject` which creates wrapper binaries which correctly set up the Ruby
|
||||
|
@ -534,7 +534,7 @@ Capistrano exposes the methods `debug()`, `info()`, `warn()`, `error()` and
|
|||
`fatal()` inside of `on()` blocks which can be used to log using the existing
|
||||
logging infrastructure and streaming IO formatters:
|
||||
|
||||
{% prism ruby %}
|
||||
{% highlight ruby %}
|
||||
# Capistrano 3.0.x
|
||||
on hosts do |host|
|
||||
f = '/some/file'
|
||||
|
@ -544,7 +544,7 @@ logging infrastructure and streaming IO formatters:
|
|||
info "#{f} already exists on #{host}!"
|
||||
end
|
||||
end
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
### Upgrading
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
<link rel="stylesheet" href="/css/capistrano.css">
|
||||
<link rel="stylesheet" href="/css/social_foundicons.css" />
|
||||
<link rel="stylesheet" href="/css/okaidia.css">
|
||||
<link rel="stylesheet" href="/css/syntax.css">
|
||||
<script src="/js/vendor/custom.modernizr.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
@ -232,22 +233,21 @@ acompanying documentation if you want to explore that any further.</p>
|
|||
<p>The guiding principle is dependency resolution, and interoperability with
|
||||
other tools, for example:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'># Capistrano 3.0.x
|
||||
task :notify do
|
||||
this_release_tag = sh("git describe --abbrev=0 --tags")
|
||||
last_ten_commits = sh("git log #{this_release_tag}~10..#{this_release_tag}")
|
||||
Mail.deliver do
|
||||
to "team@example.com"
|
||||
subject "Releasing #{this_release_tag} Now!"
|
||||
body last_ten_commits
|
||||
end
|
||||
end
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="c1"># Capistrano 3.0.x</span>
|
||||
<span class="n">task</span> <span class="ss">:notify</span> <span class="k">do</span>
|
||||
<span class="n">this_release_tag</span> <span class="o">=</span> <span class="n">sh</span><span class="p">(</span><span class="s2">"git describe --abbrev=0 --tags"</span><span class="p">)</span>
|
||||
<span class="n">last_ten_commits</span> <span class="o">=</span> <span class="n">sh</span><span class="p">(</span><span class="s2">"git log </span><span class="si">#{</span><span class="n">this_release_tag</span><span class="si">}</span><span class="s2">~10..</span><span class="si">#{</span><span class="n">this_release_tag</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
||||
<span class="no">Mail</span><span class="o">.</span><span class="n">deliver</span> <span class="k">do</span>
|
||||
<span class="n">to</span> <span class="s2">"team@example.com"</span>
|
||||
<span class="n">subject</span> <span class="s2">"Releasing </span><span class="si">#{</span><span class="n">this_release_tag</span><span class="si">}</span><span class="s2"> Now!"</span>
|
||||
<span class="n">body</span> <span class="n">last_ten_commits</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
|
||||
namespace :deploy
|
||||
task default: :notify
|
||||
end</code></pre>
|
||||
</div>
|
||||
<span class="n">namespace</span> <span class="ss">:deploy</span>
|
||||
<span class="n">task</span> <span class="ss">default</span><span class="p">:</span> <span class="ss">:notify</span>
|
||||
<span class="k">end</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>The last three lines rely on Rake's additive task declaration, by redefining the
|
||||
<code>deploy:default</code> task by adding another dependency. Rake will automatically
|
||||
|
@ -269,9 +269,8 @@ conventions established in the examples we created for you.</p>
|
|||
<p>To create different stages at installation time, simply set the <code>STAGES</code>
|
||||
environmental variable to a comma separated list of stages:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>$ cap install STAGES=staging,production,ci,qa</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> <span class="nv">$ </span>cap install <span class="nv">STAGES</span><span class="o">=</span>staging,production,ci,qa
|
||||
</code></pre></div>
|
||||
|
||||
<h4 id="toc_5">Parallelism</h4>
|
||||
|
||||
|
@ -279,16 +278,15 @@ environmental variable to a comma separated list of stages:</p>
|
|||
different tasks differently on groups of servers, it looked something like
|
||||
this:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'># Capistrano 2.0.x
|
||||
task :restart do
|
||||
parallel do |session|
|
||||
session.when "in?(:app)", "/u/apps/social/script/restart-mongrel"
|
||||
session.when "in?(:web)", "/u/apps/social/script/restart-apache"
|
||||
session.else "echo nothing to do"
|
||||
end
|
||||
end</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="c1"># Capistrano 2.0.x</span>
|
||||
<span class="n">task</span> <span class="ss">:restart</span> <span class="k">do</span>
|
||||
<span class="n">parallel</span> <span class="k">do</span> <span class="o">|</span><span class="n">session</span><span class="o">|</span>
|
||||
<span class="n">session</span><span class="o">.</span><span class="n">when</span> <span class="s2">"in?(:app)"</span><span class="p">,</span> <span class="s2">"/u/apps/social/script/restart-mongrel"</span>
|
||||
<span class="n">session</span><span class="o">.</span><span class="n">when</span> <span class="s2">"in?(:web)"</span><span class="p">,</span> <span class="s2">"/u/apps/social/script/restart-apache"</span>
|
||||
<span class="n">session</span><span class="o">.</span><span class="n">else</span> <span class="s2">"echo nothing to do"</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>This always felt a little unclean, and indeed it's a hack that was originally
|
||||
implemeted to facilitate rolling deployments at a large German firm by a
|
||||
|
@ -297,21 +295,20 @@ went on to found Travis-CI!)</p>
|
|||
|
||||
<p>The equivalent code in under Capistrano v3 would look like this:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'># Capistrano 3.0.x
|
||||
task :restart do
|
||||
on :all, in: :parallel do |host|
|
||||
if host.roles.include?(:app)
|
||||
execute "/u/apps/social/script/restart-mongrel"
|
||||
elsif host.roles.include?(:web)
|
||||
execute "/u/apps/social/script/restart-web"
|
||||
else
|
||||
info sprintf("Nothing to do for %s with roles %s", host,
|
||||
host.properties.roles)
|
||||
end
|
||||
end
|
||||
end</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="c1"># Capistrano 3.0.x</span>
|
||||
<span class="n">task</span> <span class="ss">:restart</span> <span class="k">do</span>
|
||||
<span class="n">on</span> <span class="ss">:all</span><span class="p">,</span> <span class="k">in</span><span class="p">:</span> <span class="ss">:parallel</span> <span class="k">do</span> <span class="o">|</span><span class="n">host</span><span class="o">|</span>
|
||||
<span class="k">if</span> <span class="n">host</span><span class="o">.</span><span class="n">roles</span><span class="o">.</span><span class="n">include?</span><span class="p">(</span><span class="ss">:app</span><span class="p">)</span>
|
||||
<span class="n">execute</span> <span class="s2">"/u/apps/social/script/restart-mongrel"</span>
|
||||
<span class="k">elsif</span> <span class="n">host</span><span class="o">.</span><span class="n">roles</span><span class="o">.</span><span class="n">include?</span><span class="p">(</span><span class="ss">:web</span><span class="p">)</span>
|
||||
<span class="n">execute</span> <span class="s2">"/u/apps/social/script/restart-web"</span>
|
||||
<span class="k">else</span>
|
||||
<span class="n">info</span> <span class="nb">sprintf</span><span class="p">(</span><span class="s2">"Nothing to do for %s with roles %s"</span><span class="p">,</span> <span class="n">host</span><span class="p">,</span>
|
||||
<span class="n">host</span><span class="o">.</span><span class="n">properties</span><span class="o">.</span><span class="n">roles</span><span class="p">)</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>The second block of code, that representing the new Rake derived DSL and
|
||||
demonstrating how to use the parallel execution mode is a little longer, but I
|
||||
|
@ -321,27 +318,26 @@ built-in logging subsystem, keep reading to learn more.</p>
|
|||
|
||||
<p>Other modes for parallelism include:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'># Capistrano 3.0.x
|
||||
on :all, in: :groups, max: 3, wait: 5 do
|
||||
# Take all servers, in groups of three which execute in parallel
|
||||
# wait five seconds between groups of servers.
|
||||
# This is perfect for rolling restarts
|
||||
end
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="c1"># Capistrano 3.0.x</span>
|
||||
<span class="n">on</span> <span class="ss">:all</span><span class="p">,</span> <span class="k">in</span><span class="p">:</span> <span class="ss">:groups</span><span class="p">,</span> <span class="ss">max</span><span class="p">:</span> <span class="mi">3</span><span class="p">,</span> <span class="ss">wait</span><span class="p">:</span> <span class="mi">5</span> <span class="k">do</span>
|
||||
<span class="c1"># Take all servers, in groups of three which execute in parallel</span>
|
||||
<span class="c1"># wait five seconds between groups of servers.</span>
|
||||
<span class="c1"># This is perfect for rolling restarts</span>
|
||||
<span class="k">end</span>
|
||||
|
||||
on :all, in: :sequence, wait: 15 do
|
||||
# This takes all servers, in sequence and waits 15 seconds between
|
||||
# each server, this might be perfect if you are afraid about
|
||||
# overloading a shared resource, or want to defer the asset compilation
|
||||
# over your cluster owing to worries about load
|
||||
end
|
||||
<span class="n">on</span> <span class="ss">:all</span><span class="p">,</span> <span class="k">in</span><span class="p">:</span> <span class="ss">:sequence</span><span class="p">,</span> <span class="ss">wait</span><span class="p">:</span> <span class="mi">15</span> <span class="k">do</span>
|
||||
<span class="c1"># This takes all servers, in sequence and waits 15 seconds between</span>
|
||||
<span class="c1"># each server, this might be perfect if you are afraid about</span>
|
||||
<span class="c1"># overloading a shared resource, or want to defer the asset compilation</span>
|
||||
<span class="c1"># over your cluster owing to worries about load</span>
|
||||
<span class="k">end</span>
|
||||
|
||||
on :all, in: :parallel do
|
||||
# This will simply try and execute the commands contained within
|
||||
# the block in parallel on all servers. This might be perfect for kicking
|
||||
# off something like a Git checkout or similar.
|
||||
end</code></pre>
|
||||
</div>
|
||||
<span class="n">on</span> <span class="ss">:all</span><span class="p">,</span> <span class="k">in</span><span class="p">:</span> <span class="ss">:parallel</span> <span class="k">do</span>
|
||||
<span class="c1"># This will simply try and execute the commands contained within</span>
|
||||
<span class="c1"># the block in parallel on all servers. This might be perfect for kicking</span>
|
||||
<span class="c1"># off something like a Git checkout or similar.</span>
|
||||
<span class="k">end</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>The internal tasks, for standard deploy recipes make use of all of these as is
|
||||
appropriate for the normal case, no need to be afraid of scary slow deploys
|
||||
|
@ -399,19 +395,18 @@ both connections.</p>
|
|||
<p>This cleanup routine can now be better implemented as follows (which is
|
||||
actually more or less the actual implementation in the the new Gem):</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'># Capistrano 3.0.x
|
||||
desc "Cleanup all old releases (keeps #{fetch(:releases_to_keep_on_cleanup)}
|
||||
old releases"
|
||||
task :cleanup do
|
||||
keep_releases = fetch(:releases_to_keep_on_cleanup)
|
||||
releases = capture(:ls, fetch(:releases_directory))
|
||||
release_to_delete = releases.sort_by { |r| rn.to_i }.slice(1..-(keep_releases + 1))
|
||||
releases_to_delete.each do |r|
|
||||
execute :rm, fetch(:releases_directory).join(r)
|
||||
end
|
||||
end</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="c1"># Capistrano 3.0.x</span>
|
||||
<span class="n">desc</span> <span class="s2">"Cleanup all old releases (keeps </span><span class="si">#{</span><span class="n">fetch</span><span class="p">(</span><span class="ss">:releases_to_keep_on_cleanup</span><span class="p">)</span><span class="si">}</span><span class="s2"></span>
|
||||
<span class="s2"> old releases"</span>
|
||||
<span class="n">task</span> <span class="ss">:cleanup</span> <span class="k">do</span>
|
||||
<span class="n">keep_releases</span> <span class="o">=</span> <span class="n">fetch</span><span class="p">(</span><span class="ss">:releases_to_keep_on_cleanup</span><span class="p">)</span>
|
||||
<span class="n">releases</span> <span class="o">=</span> <span class="n">capture</span><span class="p">(</span><span class="ss">:ls</span><span class="p">,</span> <span class="n">fetch</span><span class="p">(</span><span class="ss">:releases_directory</span><span class="p">))</span>
|
||||
<span class="n">release_to_delete</span> <span class="o">=</span> <span class="n">releases</span><span class="o">.</span><span class="n">sort_by</span> <span class="p">{</span> <span class="o">|</span><span class="n">r</span><span class="o">|</span> <span class="n">rn</span><span class="o">.</span><span class="n">to_i</span> <span class="p">}</span><span class="o">.</span><span class="n">slice</span><span class="p">(</span><span class="mi">1</span><span class="o">.</span><span class="n">.</span><span class="o">-</span><span class="p">(</span><span class="n">keep_releases</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span>
|
||||
<span class="n">releases_to_delete</span><span class="o">.</span><span class="n">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">r</span><span class="o">|</span>
|
||||
<span class="n">execute</span> <span class="ss">:rm</span><span class="p">,</span> <span class="n">fetch</span><span class="p">(</span><span class="ss">:releases_directory</span><span class="p">)</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">r</span><span class="p">)</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>Some handy things to note here are that both server one and server two in our
|
||||
contrived example will both evaluate that independently, and when both servers
|
||||
|
@ -438,39 +433,36 @@ your application.</p>
|
|||
|
||||
<p>An example of it's usage might be:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>h = SSHKit::Host.new 'example.com'
|
||||
h.properties.roles ||= %i{wep app}</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="n">h</span> <span class="o">=</span> <span class="no">SSHKit</span><span class="o">::</span><span class="no">Host</span><span class="o">.</span><span class="n">new</span> <span class="s1">'example.com'</span>
|
||||
<span class="n">h</span><span class="o">.</span><span class="n">properties</span><span class="o">.</span><span class="n">roles</span> <span class="o">||=</span> <span class="o">%</span><span class="n">i</span><span class="p">{</span><span class="n">wep</span> <span class="n">app</span><span class="p">}</span>
|
||||
</code></pre></div>
|
||||
|
||||
<h4 id="toc_9">More Expressive Command Language</h4>
|
||||
|
||||
<p>In Capistrano v2, it wasn't uncommon to find commands such as:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'># Capistrano 2.0.x
|
||||
task :precompile, :roles => lambda { assets_role }, :except => { :no_release => true } do
|
||||
run <<-CMD.compact
|
||||
cd -- #{latest_release} &&
|
||||
RAILS_ENV=#{rails_env.to_s.shellescape} #{asset_env} #{rake} assets:precompile
|
||||
CMD
|
||||
end</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="c1"># Capistrano 2.0.x</span>
|
||||
<span class="n">task</span> <span class="ss">:precompile</span><span class="p">,</span> <span class="ss">:roles</span> <span class="o">=></span> <span class="nb">lambda</span> <span class="p">{</span> <span class="n">assets_role</span> <span class="p">},</span> <span class="ss">:except</span> <span class="o">=></span> <span class="p">{</span> <span class="ss">:no_release</span> <span class="o">=></span> <span class="kp">true</span> <span class="p">}</span> <span class="k">do</span>
|
||||
<span class="n">run</span> <span class="o"><<-</span><span class="no">CMD</span><span class="o">.</span><span class="n">compact</span>
|
||||
<span class="sh"> cd -- #{latest_release} &&</span>
|
||||
<span class="sh"> RAILS_ENV=#{rails_env.to_s.shellescape} #{asset_env} #{rake} assets:precompile</span>
|
||||
<span class="no"> CMD</span>
|
||||
<span class="k">end</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>In Capistrano v3 this looks more like this:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'># Capistrano 3.0.x
|
||||
task :precompile do
|
||||
on :sprockets_asset_host, reject: lambda { |h| h.properties.no_release } do
|
||||
within fetch(:latest_release_directory)
|
||||
with rails_env: fetch(:rails_env) do
|
||||
execute :rake, 'assets:precompile'
|
||||
end
|
||||
end
|
||||
end
|
||||
end</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="c1"># Capistrano 3.0.x</span>
|
||||
<span class="n">task</span> <span class="ss">:precompile</span> <span class="k">do</span>
|
||||
<span class="n">on</span> <span class="ss">:sprockets_asset_host</span><span class="p">,</span> <span class="ss">reject</span><span class="p">:</span> <span class="nb">lambda</span> <span class="p">{</span> <span class="o">|</span><span class="n">h</span><span class="o">|</span> <span class="n">h</span><span class="o">.</span><span class="n">properties</span><span class="o">.</span><span class="n">no_release</span> <span class="p">}</span> <span class="k">do</span>
|
||||
<span class="n">within</span> <span class="n">fetch</span><span class="p">(</span><span class="ss">:latest_release_directory</span><span class="p">)</span>
|
||||
<span class="n">with</span> <span class="n">rails_env</span><span class="p">:</span> <span class="n">fetch</span><span class="p">(</span><span class="ss">:rails_env</span><span class="p">)</span> <span class="k">do</span>
|
||||
<span class="n">execute</span> <span class="ss">:rake</span><span class="p">,</span> <span class="s1">'assets:precompile'</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>Again, with other examples this format is a little longer, but much more
|
||||
expressive, and all the nightmare of shell escaping is handled interally for
|
||||
|
@ -516,14 +508,13 @@ from Capistrano.</p>
|
|||
<p>SSHkit is ideal for use if you need to just connect to a machine and run some
|
||||
arbitrary command, for example:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'># Rakefile (even without Capistrano loaded)
|
||||
require 'sshkit'
|
||||
desc "Check the uptime of example.com"
|
||||
task :uptime do |h|
|
||||
execute :uptime
|
||||
end</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="c1"># Rakefile (even without Capistrano loaded)</span>
|
||||
<span class="nb">require</span> <span class="s1">'sshkit'</span>
|
||||
<span class="n">desc</span> <span class="s2">"Check the uptime of example.com"</span>
|
||||
<span class="n">task</span> <span class="ss">:uptime</span> <span class="k">do</span> <span class="o">|</span><span class="n">h</span><span class="o">|</span>
|
||||
<span class="n">execute</span> <span class="ss">:uptime</span>
|
||||
<span class="k">end</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>There is much more than can be done with SSHKit, and we have quite an
|
||||
extensive <a href="https://github.com/leehambley/sshkit/blob/master/EXAMPLES.md">list of
|
||||
|
@ -539,10 +530,9 @@ from preceedings, there is a so-called command map for commands.</p>
|
|||
|
||||
<p>When executing something like:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'># Capistrano 2.0.x
|
||||
execute "git clone ........ ......."</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="c1"># Capistrano 2.0.x</span>
|
||||
<span class="n">execute</span> <span class="s2">"git clone ........ ......."</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>The command is passed through to the remote server <em>completely unchanged</em>.
|
||||
This includes the options which might be set, such as user, directory, and
|
||||
|
@ -551,36 +541,33 @@ allow people to write non-trivial commands in
|
|||
<a href="https://en.wikipedia.org/wiki/Here_document">heredocs</a> when the need arises,
|
||||
for example:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'># Capistrano 3.0.x
|
||||
execute <<-EOBLOCK
|
||||
# All of this block is interpreted as Bash script
|
||||
if ! [ -e /tmp/somefile ]
|
||||
then touch /tmp/somefile
|
||||
chmod 0644 /tmp/somefile
|
||||
end
|
||||
EOBLOCK</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="c1"># Capistrano 3.0.x</span>
|
||||
<span class="n">execute</span> <span class="o"><<-</span><span class="no">EOBLOCK</span>
|
||||
<span class="sh"> # All of this block is interpreted as Bash script</span>
|
||||
<span class="sh"> if ! [ -e /tmp/somefile ]</span>
|
||||
<span class="sh"> then touch /tmp/somefile</span>
|
||||
<span class="sh"> chmod 0644 /tmp/somefile</span>
|
||||
<span class="sh"> end</span>
|
||||
<span class="no"> EOBLOCK</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p><strong>Caveat:</strong> The SSHKit multiline command sanitizing logic will remove line feeds and add an <code>;</code> after each line to separate the commands. So make sure you are not putting a newline between <code>then</code> and the following command.</p>
|
||||
|
||||
<p>The idiomatic way to write that command in Capistrano v3 is to use the
|
||||
separated variadaric method to specify the command:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'># Capistrano 3.0.x
|
||||
execute :git, :clone, "........", "......."</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="c1"># Capistrano 3.0.x</span>
|
||||
<span class="n">execute</span> <span class="ss">:git</span><span class="p">,</span> <span class="ss">:clone</span><span class="p">,</span> <span class="s2">"........"</span><span class="p">,</span> <span class="s2">"......."</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>... or for the larger example</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'># Capistrano 3.0.x
|
||||
file = '/tmp/somefile'
|
||||
unless test("-e #{file}")
|
||||
execute :touch, file
|
||||
end</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="c1"># Capistrano 3.0.x</span>
|
||||
<span class="n">file</span> <span class="o">=</span> <span class="s1">'/tmp/somefile'</span>
|
||||
<span class="k">unless</span> <span class="nb">test</span><span class="p">(</span><span class="s2">"-e </span><span class="si">#{</span><span class="n">file</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
||||
<span class="n">execute</span> <span class="ss">:touch</span><span class="p">,</span> <span class="n">file</span>
|
||||
<span class="k">end</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>In this way the <em>command map</em> is consulted, the command map maps all unknown
|
||||
commands (which in this case is <code>git</code>, the rest of the line are <em>arguments</em> to
|
||||
|
@ -592,22 +579,20 @@ indirectly) to determine which <code>git</code> to run.</p>
|
|||
<p>Commands such as <code>rake</code> and <code>rails</code> are often better prefixed by <code>bundle
|
||||
exec</code>, and in this case could be mapped to:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>SSHKit.config.command_map[:rake] = "bundle exec rake"
|
||||
SSHKit.config.command_map[:rails] = "bundle exec rails"</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="no">SSHKit</span><span class="o">.</span><span class="n">config</span><span class="o">.</span><span class="n">command_map</span><span class="o">[</span><span class="ss">:rake</span><span class="o">]</span> <span class="o">=</span> <span class="s2">"bundle exec rake"</span>
|
||||
<span class="no">SSHKit</span><span class="o">.</span><span class="n">config</span><span class="o">.</span><span class="n">command_map</span><span class="o">[</span><span class="ss">:rails</span><span class="o">]</span> <span class="o">=</span> <span class="s2">"bundle exec rails"</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>There can also be a <code>lambda</code> or <code>Proc</code> applied in place of the mapping like so:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>SSHKit.config.command_map = Hash.new do |hash, key|
|
||||
if %i{rails rake bundle clockwork heroku}.include?(key.to_sym)
|
||||
hash[key] = "/usr/bin/env bundle exec #{key}"
|
||||
else
|
||||
hash[key] = "/usr/bin/env #{key}"
|
||||
end
|
||||
end</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="no">SSHKit</span><span class="o">.</span><span class="n">config</span><span class="o">.</span><span class="n">command_map</span> <span class="o">=</span> <span class="no">Hash</span><span class="o">.</span><span class="n">new</span> <span class="k">do</span> <span class="o">|</span><span class="nb">hash</span><span class="p">,</span> <span class="n">key</span><span class="o">|</span>
|
||||
<span class="k">if</span> <span class="o">%</span><span class="n">i</span><span class="p">{</span><span class="n">rails</span> <span class="n">rake</span> <span class="n">bundle</span> <span class="n">clockwork</span> <span class="n">heroku</span><span class="p">}</span><span class="o">.</span><span class="n">include?</span><span class="p">(</span><span class="n">key</span><span class="o">.</span><span class="n">to_sym</span><span class="p">)</span>
|
||||
<span class="nb">hash</span><span class="o">[</span><span class="n">key</span><span class="o">]</span> <span class="o">=</span> <span class="s2">"/usr/bin/env bundle exec </span><span class="si">#{</span><span class="n">key</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nb">hash</span><span class="o">[</span><span class="n">key</span><span class="o">]</span> <span class="o">=</span> <span class="s2">"/usr/bin/env </span><span class="si">#{</span><span class="n">key</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>Between these two options there should be quite powerful options to map
|
||||
commands in your environment without having to override internal tasks from
|
||||
|
@ -616,15 +601,14 @@ Capistrano just because a path is different, or a binary has a different name.</
|
|||
<p>This can also be <em>slightly</em> abused in environments where <em>shim</em> executables
|
||||
are used, for example <code>rbenv</code> <em>wrappers</em>:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>SSHKit.config.command_map = Hash.new do |hash, key|
|
||||
if %i{rails rake bundle clockwork heroku}.include?(key.to_sym)
|
||||
hash[key] = "/usr/bin/env myproject_bundle exec myproject_#{key}"
|
||||
else
|
||||
hash[key] = "/usr/bin/env #{key}"
|
||||
end
|
||||
end</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="no">SSHKit</span><span class="o">.</span><span class="n">config</span><span class="o">.</span><span class="n">command_map</span> <span class="o">=</span> <span class="no">Hash</span><span class="o">.</span><span class="n">new</span> <span class="k">do</span> <span class="o">|</span><span class="nb">hash</span><span class="p">,</span> <span class="n">key</span><span class="o">|</span>
|
||||
<span class="k">if</span> <span class="o">%</span><span class="n">i</span><span class="p">{</span><span class="n">rails</span> <span class="n">rake</span> <span class="n">bundle</span> <span class="n">clockwork</span> <span class="n">heroku</span><span class="p">}</span><span class="o">.</span><span class="n">include?</span><span class="p">(</span><span class="n">key</span><span class="o">.</span><span class="n">to_sym</span><span class="p">)</span>
|
||||
<span class="nb">hash</span><span class="o">[</span><span class="n">key</span><span class="o">]</span> <span class="o">=</span> <span class="s2">"/usr/bin/env myproject_bundle exec myproject_</span><span class="si">#{</span><span class="n">key</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nb">hash</span><span class="o">[</span><span class="n">key</span><span class="o">]</span> <span class="o">=</span> <span class="s2">"/usr/bin/env </span><span class="si">#{</span><span class="n">key</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>The above assumes that you have done something like <code>rbenv wrapper default
|
||||
myproject</code> which creates wrapper binaries which correctly set up the Ruby
|
||||
|
@ -657,17 +641,16 @@ made, or not made as expected.</p>
|
|||
<code>fatal()</code> inside of <code>on()</code> blocks which can be used to log using the existing
|
||||
logging infrastructure and streaming IO formatters:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'># Capistrano 3.0.x
|
||||
on hosts do |host|
|
||||
f = '/some/file'
|
||||
if test("[ -d #{f} ]")
|
||||
execute :touch, f
|
||||
else
|
||||
info "#{f} already exists on #{host}!"
|
||||
end
|
||||
end</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="c1"># Capistrano 3.0.x</span>
|
||||
<span class="n">on</span> <span class="n">hosts</span> <span class="k">do</span> <span class="o">|</span><span class="n">host</span><span class="o">|</span>
|
||||
<span class="n">f</span> <span class="o">=</span> <span class="s1">'/some/file'</span>
|
||||
<span class="k">if</span> <span class="nb">test</span><span class="p">(</span><span class="s2">"[ -d </span><span class="si">#{</span><span class="n">f</span><span class="si">}</span><span class="s2"> ]"</span><span class="p">)</span>
|
||||
<span class="n">execute</span> <span class="ss">:touch</span><span class="p">,</span> <span class="n">f</span>
|
||||
<span class="k">else</span>
|
||||
<span class="n">info</span> <span class="s2">"</span><span class="si">#{</span><span class="n">f</span><span class="si">}</span><span class="s2"> already exists on </span><span class="si">#{</span><span class="n">host</span><span class="si">}</span><span class="s2">!"</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
</code></pre></div>
|
||||
|
||||
<h3 id="toc_15"> Upgrading</h3>
|
||||
|
||||
|
@ -822,22 +805,21 @@ acompanying documentation if you want to explore that any further.</p>
|
|||
<p>The guiding principle is dependency resolution, and interoperability with
|
||||
other tools, for example:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'># Capistrano 3.0.x
|
||||
task :notify do
|
||||
this_release_tag = sh("git describe --abbrev=0 --tags")
|
||||
last_ten_commits = sh("git log #{this_release_tag}~10..#{this_release_tag}")
|
||||
Mail.deliver do
|
||||
to "team@example.com"
|
||||
subject "Releasing #{this_release_tag} Now!"
|
||||
body last_ten_commits
|
||||
end
|
||||
end
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="c1"># Capistrano 3.0.x</span>
|
||||
<span class="n">task</span> <span class="ss">:notify</span> <span class="k">do</span>
|
||||
<span class="n">this_release_tag</span> <span class="o">=</span> <span class="n">sh</span><span class="p">(</span><span class="s2">"git describe --abbrev=0 --tags"</span><span class="p">)</span>
|
||||
<span class="n">last_ten_commits</span> <span class="o">=</span> <span class="n">sh</span><span class="p">(</span><span class="s2">"git log </span><span class="si">#{</span><span class="n">this_release_tag</span><span class="si">}</span><span class="s2">~10..</span><span class="si">#{</span><span class="n">this_release_tag</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
||||
<span class="no">Mail</span><span class="o">.</span><span class="n">deliver</span> <span class="k">do</span>
|
||||
<span class="n">to</span> <span class="s2">"team@example.com"</span>
|
||||
<span class="n">subject</span> <span class="s2">"Releasing </span><span class="si">#{</span><span class="n">this_release_tag</span><span class="si">}</span><span class="s2"> Now!"</span>
|
||||
<span class="n">body</span> <span class="n">last_ten_commits</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
|
||||
namespace :deploy
|
||||
task default: :notify
|
||||
end</code></pre>
|
||||
</div>
|
||||
<span class="n">namespace</span> <span class="ss">:deploy</span>
|
||||
<span class="n">task</span> <span class="ss">default</span><span class="p">:</span> <span class="ss">:notify</span>
|
||||
<span class="k">end</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>The last three lines rely on Rake's additive task declaration, by redefining the
|
||||
<code>deploy:default</code> task by adding another dependency. Rake will automatically
|
||||
|
@ -859,9 +841,8 @@ conventions established in the examples we created for you.</p>
|
|||
<p>To create different stages at installation time, simply set the <code>STAGES</code>
|
||||
environmental variable to a comma separated list of stages:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>$ cap install STAGES=staging,production,ci,qa</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> <span class="nv">$ </span>cap install <span class="nv">STAGES</span><span class="o">=</span>staging,production,ci,qa
|
||||
</code></pre></div>
|
||||
|
||||
<h4 id="toc_5">Parallelism</h4>
|
||||
|
||||
|
@ -869,16 +850,15 @@ environmental variable to a comma separated list of stages:</p>
|
|||
different tasks differently on groups of servers, it looked something like
|
||||
this:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'># Capistrano 2.0.x
|
||||
task :restart do
|
||||
parallel do |session|
|
||||
session.when "in?(:app)", "/u/apps/social/script/restart-mongrel"
|
||||
session.when "in?(:web)", "/u/apps/social/script/restart-apache"
|
||||
session.else "echo nothing to do"
|
||||
end
|
||||
end</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="c1"># Capistrano 2.0.x</span>
|
||||
<span class="n">task</span> <span class="ss">:restart</span> <span class="k">do</span>
|
||||
<span class="n">parallel</span> <span class="k">do</span> <span class="o">|</span><span class="n">session</span><span class="o">|</span>
|
||||
<span class="n">session</span><span class="o">.</span><span class="n">when</span> <span class="s2">"in?(:app)"</span><span class="p">,</span> <span class="s2">"/u/apps/social/script/restart-mongrel"</span>
|
||||
<span class="n">session</span><span class="o">.</span><span class="n">when</span> <span class="s2">"in?(:web)"</span><span class="p">,</span> <span class="s2">"/u/apps/social/script/restart-apache"</span>
|
||||
<span class="n">session</span><span class="o">.</span><span class="n">else</span> <span class="s2">"echo nothing to do"</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>This always felt a little unclean, and indeed it's a hack that was originally
|
||||
implemeted to facilitate rolling deployments at a large German firm by a
|
||||
|
@ -887,21 +867,20 @@ went on to found Travis-CI!)</p>
|
|||
|
||||
<p>The equivalent code in under Capistrano v3 would look like this:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'># Capistrano 3.0.x
|
||||
task :restart do
|
||||
on :all, in: :parallel do |host|
|
||||
if host.roles.include?(:app)
|
||||
execute "/u/apps/social/script/restart-mongrel"
|
||||
elsif host.roles.include?(:web)
|
||||
execute "/u/apps/social/script/restart-web"
|
||||
else
|
||||
info sprintf("Nothing to do for %s with roles %s", host,
|
||||
host.properties.roles)
|
||||
end
|
||||
end
|
||||
end</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="c1"># Capistrano 3.0.x</span>
|
||||
<span class="n">task</span> <span class="ss">:restart</span> <span class="k">do</span>
|
||||
<span class="n">on</span> <span class="ss">:all</span><span class="p">,</span> <span class="k">in</span><span class="p">:</span> <span class="ss">:parallel</span> <span class="k">do</span> <span class="o">|</span><span class="n">host</span><span class="o">|</span>
|
||||
<span class="k">if</span> <span class="n">host</span><span class="o">.</span><span class="n">roles</span><span class="o">.</span><span class="n">include?</span><span class="p">(</span><span class="ss">:app</span><span class="p">)</span>
|
||||
<span class="n">execute</span> <span class="s2">"/u/apps/social/script/restart-mongrel"</span>
|
||||
<span class="k">elsif</span> <span class="n">host</span><span class="o">.</span><span class="n">roles</span><span class="o">.</span><span class="n">include?</span><span class="p">(</span><span class="ss">:web</span><span class="p">)</span>
|
||||
<span class="n">execute</span> <span class="s2">"/u/apps/social/script/restart-web"</span>
|
||||
<span class="k">else</span>
|
||||
<span class="n">info</span> <span class="nb">sprintf</span><span class="p">(</span><span class="s2">"Nothing to do for %s with roles %s"</span><span class="p">,</span> <span class="n">host</span><span class="p">,</span>
|
||||
<span class="n">host</span><span class="o">.</span><span class="n">properties</span><span class="o">.</span><span class="n">roles</span><span class="p">)</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>The second block of code, that representing the new Rake derived DSL and
|
||||
demonstrating how to use the parallel execution mode is a little longer, but I
|
||||
|
@ -911,27 +890,26 @@ built-in logging subsystem, keep reading to learn more.</p>
|
|||
|
||||
<p>Other modes for parallelism include:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'># Capistrano 3.0.x
|
||||
on :all, in: :groups, max: 3, wait: 5 do
|
||||
# Take all servers, in groups of three which execute in parallel
|
||||
# wait five seconds between groups of servers.
|
||||
# This is perfect for rolling restarts
|
||||
end
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="c1"># Capistrano 3.0.x</span>
|
||||
<span class="n">on</span> <span class="ss">:all</span><span class="p">,</span> <span class="k">in</span><span class="p">:</span> <span class="ss">:groups</span><span class="p">,</span> <span class="ss">max</span><span class="p">:</span> <span class="mi">3</span><span class="p">,</span> <span class="ss">wait</span><span class="p">:</span> <span class="mi">5</span> <span class="k">do</span>
|
||||
<span class="c1"># Take all servers, in groups of three which execute in parallel</span>
|
||||
<span class="c1"># wait five seconds between groups of servers.</span>
|
||||
<span class="c1"># This is perfect for rolling restarts</span>
|
||||
<span class="k">end</span>
|
||||
|
||||
on :all, in: :sequence, wait: 15 do
|
||||
# This takes all servers, in sequence and waits 15 seconds between
|
||||
# each server, this might be perfect if you are afraid about
|
||||
# overloading a shared resource, or want to defer the asset compilation
|
||||
# over your cluster owing to worries about load
|
||||
end
|
||||
<span class="n">on</span> <span class="ss">:all</span><span class="p">,</span> <span class="k">in</span><span class="p">:</span> <span class="ss">:sequence</span><span class="p">,</span> <span class="ss">wait</span><span class="p">:</span> <span class="mi">15</span> <span class="k">do</span>
|
||||
<span class="c1"># This takes all servers, in sequence and waits 15 seconds between</span>
|
||||
<span class="c1"># each server, this might be perfect if you are afraid about</span>
|
||||
<span class="c1"># overloading a shared resource, or want to defer the asset compilation</span>
|
||||
<span class="c1"># over your cluster owing to worries about load</span>
|
||||
<span class="k">end</span>
|
||||
|
||||
on :all, in: :parallel do
|
||||
# This will simply try and execute the commands contained within
|
||||
# the block in parallel on all servers. This might be perfect for kicking
|
||||
# off something like a Git checkout or similar.
|
||||
end</code></pre>
|
||||
</div>
|
||||
<span class="n">on</span> <span class="ss">:all</span><span class="p">,</span> <span class="k">in</span><span class="p">:</span> <span class="ss">:parallel</span> <span class="k">do</span>
|
||||
<span class="c1"># This will simply try and execute the commands contained within</span>
|
||||
<span class="c1"># the block in parallel on all servers. This might be perfect for kicking</span>
|
||||
<span class="c1"># off something like a Git checkout or similar.</span>
|
||||
<span class="k">end</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>The internal tasks, for standard deploy recipes make use of all of these as is
|
||||
appropriate for the normal case, no need to be afraid of scary slow deploys
|
||||
|
@ -989,19 +967,18 @@ both connections.</p>
|
|||
<p>This cleanup routine can now be better implemented as follows (which is
|
||||
actually more or less the actual implementation in the the new Gem):</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'># Capistrano 3.0.x
|
||||
desc "Cleanup all old releases (keeps #{fetch(:releases_to_keep_on_cleanup)}
|
||||
old releases"
|
||||
task :cleanup do
|
||||
keep_releases = fetch(:releases_to_keep_on_cleanup)
|
||||
releases = capture(:ls, fetch(:releases_directory))
|
||||
release_to_delete = releases.sort_by { |r| rn.to_i }.slice(1..-(keep_releases + 1))
|
||||
releases_to_delete.each do |r|
|
||||
execute :rm, fetch(:releases_directory).join(r)
|
||||
end
|
||||
end</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="c1"># Capistrano 3.0.x</span>
|
||||
<span class="n">desc</span> <span class="s2">"Cleanup all old releases (keeps </span><span class="si">#{</span><span class="n">fetch</span><span class="p">(</span><span class="ss">:releases_to_keep_on_cleanup</span><span class="p">)</span><span class="si">}</span><span class="s2"></span>
|
||||
<span class="s2"> old releases"</span>
|
||||
<span class="n">task</span> <span class="ss">:cleanup</span> <span class="k">do</span>
|
||||
<span class="n">keep_releases</span> <span class="o">=</span> <span class="n">fetch</span><span class="p">(</span><span class="ss">:releases_to_keep_on_cleanup</span><span class="p">)</span>
|
||||
<span class="n">releases</span> <span class="o">=</span> <span class="n">capture</span><span class="p">(</span><span class="ss">:ls</span><span class="p">,</span> <span class="n">fetch</span><span class="p">(</span><span class="ss">:releases_directory</span><span class="p">))</span>
|
||||
<span class="n">release_to_delete</span> <span class="o">=</span> <span class="n">releases</span><span class="o">.</span><span class="n">sort_by</span> <span class="p">{</span> <span class="o">|</span><span class="n">r</span><span class="o">|</span> <span class="n">rn</span><span class="o">.</span><span class="n">to_i</span> <span class="p">}</span><span class="o">.</span><span class="n">slice</span><span class="p">(</span><span class="mi">1</span><span class="o">.</span><span class="n">.</span><span class="o">-</span><span class="p">(</span><span class="n">keep_releases</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span>
|
||||
<span class="n">releases_to_delete</span><span class="o">.</span><span class="n">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">r</span><span class="o">|</span>
|
||||
<span class="n">execute</span> <span class="ss">:rm</span><span class="p">,</span> <span class="n">fetch</span><span class="p">(</span><span class="ss">:releases_directory</span><span class="p">)</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">r</span><span class="p">)</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>Some handy things to note here are that both server one and server two in our
|
||||
contrived example will both evaluate that independently, and when both servers
|
||||
|
@ -1028,39 +1005,36 @@ your application.</p>
|
|||
|
||||
<p>An example of it's usage might be:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>h = SSHKit::Host.new 'example.com'
|
||||
h.properties.roles ||= %i{wep app}</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="n">h</span> <span class="o">=</span> <span class="no">SSHKit</span><span class="o">::</span><span class="no">Host</span><span class="o">.</span><span class="n">new</span> <span class="s1">'example.com'</span>
|
||||
<span class="n">h</span><span class="o">.</span><span class="n">properties</span><span class="o">.</span><span class="n">roles</span> <span class="o">||=</span> <span class="o">%</span><span class="n">i</span><span class="p">{</span><span class="n">wep</span> <span class="n">app</span><span class="p">}</span>
|
||||
</code></pre></div>
|
||||
|
||||
<h4 id="toc_9">More Expressive Command Language</h4>
|
||||
|
||||
<p>In Capistrano v2, it wasn't uncommon to find commands such as:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'># Capistrano 2.0.x
|
||||
task :precompile, :roles => lambda { assets_role }, :except => { :no_release => true } do
|
||||
run <<-CMD.compact
|
||||
cd -- #{latest_release} &&
|
||||
RAILS_ENV=#{rails_env.to_s.shellescape} #{asset_env} #{rake} assets:precompile
|
||||
CMD
|
||||
end</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="c1"># Capistrano 2.0.x</span>
|
||||
<span class="n">task</span> <span class="ss">:precompile</span><span class="p">,</span> <span class="ss">:roles</span> <span class="o">=></span> <span class="nb">lambda</span> <span class="p">{</span> <span class="n">assets_role</span> <span class="p">},</span> <span class="ss">:except</span> <span class="o">=></span> <span class="p">{</span> <span class="ss">:no_release</span> <span class="o">=></span> <span class="kp">true</span> <span class="p">}</span> <span class="k">do</span>
|
||||
<span class="n">run</span> <span class="o"><<-</span><span class="no">CMD</span><span class="o">.</span><span class="n">compact</span>
|
||||
<span class="sh"> cd -- #{latest_release} &&</span>
|
||||
<span class="sh"> RAILS_ENV=#{rails_env.to_s.shellescape} #{asset_env} #{rake} assets:precompile</span>
|
||||
<span class="no"> CMD</span>
|
||||
<span class="k">end</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>In Capistrano v3 this looks more like this:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'># Capistrano 3.0.x
|
||||
task :precompile do
|
||||
on :sprockets_asset_host, reject: lambda { |h| h.properties.no_release } do
|
||||
within fetch(:latest_release_directory)
|
||||
with rails_env: fetch(:rails_env) do
|
||||
execute :rake, 'assets:precompile'
|
||||
end
|
||||
end
|
||||
end
|
||||
end</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="c1"># Capistrano 3.0.x</span>
|
||||
<span class="n">task</span> <span class="ss">:precompile</span> <span class="k">do</span>
|
||||
<span class="n">on</span> <span class="ss">:sprockets_asset_host</span><span class="p">,</span> <span class="ss">reject</span><span class="p">:</span> <span class="nb">lambda</span> <span class="p">{</span> <span class="o">|</span><span class="n">h</span><span class="o">|</span> <span class="n">h</span><span class="o">.</span><span class="n">properties</span><span class="o">.</span><span class="n">no_release</span> <span class="p">}</span> <span class="k">do</span>
|
||||
<span class="n">within</span> <span class="n">fetch</span><span class="p">(</span><span class="ss">:latest_release_directory</span><span class="p">)</span>
|
||||
<span class="n">with</span> <span class="n">rails_env</span><span class="p">:</span> <span class="n">fetch</span><span class="p">(</span><span class="ss">:rails_env</span><span class="p">)</span> <span class="k">do</span>
|
||||
<span class="n">execute</span> <span class="ss">:rake</span><span class="p">,</span> <span class="s1">'assets:precompile'</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>Again, with other examples this format is a little longer, but much more
|
||||
expressive, and all the nightmare of shell escaping is handled interally for
|
||||
|
@ -1106,14 +1080,13 @@ from Capistrano.</p>
|
|||
<p>SSHkit is ideal for use if you need to just connect to a machine and run some
|
||||
arbitrary command, for example:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'># Rakefile (even without Capistrano loaded)
|
||||
require 'sshkit'
|
||||
desc "Check the uptime of example.com"
|
||||
task :uptime do |h|
|
||||
execute :uptime
|
||||
end</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="c1"># Rakefile (even without Capistrano loaded)</span>
|
||||
<span class="nb">require</span> <span class="s1">'sshkit'</span>
|
||||
<span class="n">desc</span> <span class="s2">"Check the uptime of example.com"</span>
|
||||
<span class="n">task</span> <span class="ss">:uptime</span> <span class="k">do</span> <span class="o">|</span><span class="n">h</span><span class="o">|</span>
|
||||
<span class="n">execute</span> <span class="ss">:uptime</span>
|
||||
<span class="k">end</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>There is much more than can be done with SSHKit, and we have quite an
|
||||
extensive <a href="https://github.com/leehambley/sshkit/blob/master/EXAMPLES.md">list of
|
||||
|
@ -1129,10 +1102,9 @@ from preceedings, there is a so-called command map for commands.</p>
|
|||
|
||||
<p>When executing something like:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'># Capistrano 2.0.x
|
||||
execute "git clone ........ ......."</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="c1"># Capistrano 2.0.x</span>
|
||||
<span class="n">execute</span> <span class="s2">"git clone ........ ......."</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>The command is passed through to the remote server <em>completely unchanged</em>.
|
||||
This includes the options which might be set, such as user, directory, and
|
||||
|
@ -1141,36 +1113,33 @@ allow people to write non-trivial commands in
|
|||
<a href="https://en.wikipedia.org/wiki/Here_document">heredocs</a> when the need arises,
|
||||
for example:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'># Capistrano 3.0.x
|
||||
execute <<-EOBLOCK
|
||||
# All of this block is interpreted as Bash script
|
||||
if ! [ -e /tmp/somefile ]
|
||||
then touch /tmp/somefile
|
||||
chmod 0644 /tmp/somefile
|
||||
end
|
||||
EOBLOCK</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="c1"># Capistrano 3.0.x</span>
|
||||
<span class="n">execute</span> <span class="o"><<-</span><span class="no">EOBLOCK</span>
|
||||
<span class="sh"> # All of this block is interpreted as Bash script</span>
|
||||
<span class="sh"> if ! [ -e /tmp/somefile ]</span>
|
||||
<span class="sh"> then touch /tmp/somefile</span>
|
||||
<span class="sh"> chmod 0644 /tmp/somefile</span>
|
||||
<span class="sh"> end</span>
|
||||
<span class="no"> EOBLOCK</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p><strong>Caveat:</strong> The SSHKit multiline command sanitizing logic will remove line feeds and add an <code>;</code> after each line to separate the commands. So make sure you are not putting a newline between <code>then</code> and the following command.</p>
|
||||
|
||||
<p>The idiomatic way to write that command in Capistrano v3 is to use the
|
||||
separated variadaric method to specify the command:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'># Capistrano 3.0.x
|
||||
execute :git, :clone, "........", "......."</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="c1"># Capistrano 3.0.x</span>
|
||||
<span class="n">execute</span> <span class="ss">:git</span><span class="p">,</span> <span class="ss">:clone</span><span class="p">,</span> <span class="s2">"........"</span><span class="p">,</span> <span class="s2">"......."</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>... or for the larger example</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'># Capistrano 3.0.x
|
||||
file = '/tmp/somefile'
|
||||
unless test("-e #{file}")
|
||||
execute :touch, file
|
||||
end</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="c1"># Capistrano 3.0.x</span>
|
||||
<span class="n">file</span> <span class="o">=</span> <span class="s1">'/tmp/somefile'</span>
|
||||
<span class="k">unless</span> <span class="nb">test</span><span class="p">(</span><span class="s2">"-e </span><span class="si">#{</span><span class="n">file</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
||||
<span class="n">execute</span> <span class="ss">:touch</span><span class="p">,</span> <span class="n">file</span>
|
||||
<span class="k">end</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>In this way the <em>command map</em> is consulted, the command map maps all unknown
|
||||
commands (which in this case is <code>git</code>, the rest of the line are <em>arguments</em> to
|
||||
|
@ -1182,22 +1151,20 @@ indirectly) to determine which <code>git</code> to run.</p>
|
|||
<p>Commands such as <code>rake</code> and <code>rails</code> are often better prefixed by <code>bundle
|
||||
exec</code>, and in this case could be mapped to:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>SSHKit.config.command_map[:rake] = "bundle exec rake"
|
||||
SSHKit.config.command_map[:rails] = "bundle exec rails"</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="no">SSHKit</span><span class="o">.</span><span class="n">config</span><span class="o">.</span><span class="n">command_map</span><span class="o">[</span><span class="ss">:rake</span><span class="o">]</span> <span class="o">=</span> <span class="s2">"bundle exec rake"</span>
|
||||
<span class="no">SSHKit</span><span class="o">.</span><span class="n">config</span><span class="o">.</span><span class="n">command_map</span><span class="o">[</span><span class="ss">:rails</span><span class="o">]</span> <span class="o">=</span> <span class="s2">"bundle exec rails"</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>There can also be a <code>lambda</code> or <code>Proc</code> applied in place of the mapping like so:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>SSHKit.config.command_map = Hash.new do |hash, key|
|
||||
if %i{rails rake bundle clockwork heroku}.include?(key.to_sym)
|
||||
hash[key] = "/usr/bin/env bundle exec #{key}"
|
||||
else
|
||||
hash[key] = "/usr/bin/env #{key}"
|
||||
end
|
||||
end</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="no">SSHKit</span><span class="o">.</span><span class="n">config</span><span class="o">.</span><span class="n">command_map</span> <span class="o">=</span> <span class="no">Hash</span><span class="o">.</span><span class="n">new</span> <span class="k">do</span> <span class="o">|</span><span class="nb">hash</span><span class="p">,</span> <span class="n">key</span><span class="o">|</span>
|
||||
<span class="k">if</span> <span class="o">%</span><span class="n">i</span><span class="p">{</span><span class="n">rails</span> <span class="n">rake</span> <span class="n">bundle</span> <span class="n">clockwork</span> <span class="n">heroku</span><span class="p">}</span><span class="o">.</span><span class="n">include?</span><span class="p">(</span><span class="n">key</span><span class="o">.</span><span class="n">to_sym</span><span class="p">)</span>
|
||||
<span class="nb">hash</span><span class="o">[</span><span class="n">key</span><span class="o">]</span> <span class="o">=</span> <span class="s2">"/usr/bin/env bundle exec </span><span class="si">#{</span><span class="n">key</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nb">hash</span><span class="o">[</span><span class="n">key</span><span class="o">]</span> <span class="o">=</span> <span class="s2">"/usr/bin/env </span><span class="si">#{</span><span class="n">key</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>Between these two options there should be quite powerful options to map
|
||||
commands in your environment without having to override internal tasks from
|
||||
|
@ -1206,15 +1173,14 @@ Capistrano just because a path is different, or a binary has a different name.</
|
|||
<p>This can also be <em>slightly</em> abused in environments where <em>shim</em> executables
|
||||
are used, for example <code>rbenv</code> <em>wrappers</em>:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>SSHKit.config.command_map = Hash.new do |hash, key|
|
||||
if %i{rails rake bundle clockwork heroku}.include?(key.to_sym)
|
||||
hash[key] = "/usr/bin/env myproject_bundle exec myproject_#{key}"
|
||||
else
|
||||
hash[key] = "/usr/bin/env #{key}"
|
||||
end
|
||||
end</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="no">SSHKit</span><span class="o">.</span><span class="n">config</span><span class="o">.</span><span class="n">command_map</span> <span class="o">=</span> <span class="no">Hash</span><span class="o">.</span><span class="n">new</span> <span class="k">do</span> <span class="o">|</span><span class="nb">hash</span><span class="p">,</span> <span class="n">key</span><span class="o">|</span>
|
||||
<span class="k">if</span> <span class="o">%</span><span class="n">i</span><span class="p">{</span><span class="n">rails</span> <span class="n">rake</span> <span class="n">bundle</span> <span class="n">clockwork</span> <span class="n">heroku</span><span class="p">}</span><span class="o">.</span><span class="n">include?</span><span class="p">(</span><span class="n">key</span><span class="o">.</span><span class="n">to_sym</span><span class="p">)</span>
|
||||
<span class="nb">hash</span><span class="o">[</span><span class="n">key</span><span class="o">]</span> <span class="o">=</span> <span class="s2">"/usr/bin/env myproject_bundle exec myproject_</span><span class="si">#{</span><span class="n">key</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nb">hash</span><span class="o">[</span><span class="n">key</span><span class="o">]</span> <span class="o">=</span> <span class="s2">"/usr/bin/env </span><span class="si">#{</span><span class="n">key</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>The above assumes that you have done something like <code>rbenv wrapper default
|
||||
myproject</code> which creates wrapper binaries which correctly set up the Ruby
|
||||
|
@ -1247,17 +1213,16 @@ made, or not made as expected.</p>
|
|||
<code>fatal()</code> inside of <code>on()</code> blocks which can be used to log using the existing
|
||||
logging infrastructure and streaming IO formatters:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'># Capistrano 3.0.x
|
||||
on hosts do |host|
|
||||
f = '/some/file'
|
||||
if test("[ -d #{f} ]")
|
||||
execute :touch, f
|
||||
else
|
||||
info "#{f} already exists on #{host}!"
|
||||
end
|
||||
end</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="c1"># Capistrano 3.0.x</span>
|
||||
<span class="n">on</span> <span class="n">hosts</span> <span class="k">do</span> <span class="o">|</span><span class="n">host</span><span class="o">|</span>
|
||||
<span class="n">f</span> <span class="o">=</span> <span class="s1">'/some/file'</span>
|
||||
<span class="k">if</span> <span class="nb">test</span><span class="p">(</span><span class="s2">"[ -d </span><span class="si">#{</span><span class="n">f</span><span class="si">}</span><span class="s2"> ]"</span><span class="p">)</span>
|
||||
<span class="n">execute</span> <span class="ss">:touch</span><span class="p">,</span> <span class="n">f</span>
|
||||
<span class="k">else</span>
|
||||
<span class="n">info</span> <span class="s2">"</span><span class="si">#{</span><span class="n">f</span><span class="si">}</span><span class="s2"> already exists on </span><span class="si">#{</span><span class="n">host</span><span class="si">}</span><span class="s2">!"</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
</code></pre></div>
|
||||
|
||||
<h3 id="toc_15"> Upgrading</h3>
|
||||
|
||||
|
|
|
@ -3,5 +3,5 @@ source "https://rubygems.org"
|
|||
gem "jekyll"
|
||||
gem "redcarpet"
|
||||
gem "unindent"
|
||||
gem 'github-pages', github: 'github/pages-gem'
|
||||
# gem 'github-pages', github: 'github/pages-gem'
|
||||
gem "git"
|
||||
|
|
|
@ -1,20 +1,6 @@
|
|||
GIT
|
||||
remote: git://github.com/github/pages-gem.git
|
||||
revision: a73cbe4d6b683e0ef1bbeefc01e10daac1498a65
|
||||
specs:
|
||||
github-pages (12)
|
||||
RedCloth (= 4.2.9)
|
||||
jekyll (= 1.4.2)
|
||||
kramdown (= 1.2.0)
|
||||
liquid (= 2.5.4)
|
||||
maruku (= 0.7.0)
|
||||
rdiscount (= 2.1.7)
|
||||
redcarpet (= 2.3.0)
|
||||
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
RedCloth (4.2.9)
|
||||
blankslate (2.1.2.4)
|
||||
classifier (1.3.4)
|
||||
fast-stemmer (>= 1.0.0)
|
||||
|
@ -36,7 +22,6 @@ GEM
|
|||
redcarpet (~> 2.3.0)
|
||||
safe_yaml (~> 0.9.7)
|
||||
toml (~> 0.1.0)
|
||||
kramdown (1.2.0)
|
||||
liquid (2.5.4)
|
||||
listen (1.3.1)
|
||||
rb-fsevent (>= 0.9.3)
|
||||
|
@ -54,7 +39,6 @@ GEM
|
|||
ffi (>= 0.5.0)
|
||||
rb-kqueue (0.2.0)
|
||||
ffi (>= 0.5.0)
|
||||
rdiscount (2.1.7)
|
||||
redcarpet (2.3.0)
|
||||
safe_yaml (0.9.7)
|
||||
toml (0.1.0)
|
||||
|
@ -67,7 +51,6 @@ PLATFORMS
|
|||
|
||||
DEPENDENCIES
|
||||
git
|
||||
github-pages!
|
||||
jekyll
|
||||
redcarpet
|
||||
unindent
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
<link rel="stylesheet" href="/css/capistrano.css">
|
||||
<link rel="stylesheet" href="/css/social_foundicons.css" />
|
||||
<link rel="stylesheet" href="/css/okaidia.css">
|
||||
<link rel="stylesheet" href="/css/syntax.css">
|
||||
<script src="/js/vendor/custom.modernizr.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
|
|
@ -14,14 +14,14 @@ h1, h2, h3, h4, h5, h6 {
|
|||
font-family: 'Enriqueta', serif;
|
||||
}
|
||||
|
||||
p code, li code {
|
||||
/*p code, li code {
|
||||
padding: 3px;
|
||||
background-color: #E6E6E6;
|
||||
font-family: "droid-sans-mono", Consolas, Monaco, 'Andale Mono', monospace;
|
||||
font-size: 0.9em;
|
||||
color: #222;
|
||||
border-radius: 3px;
|
||||
}
|
||||
}*/
|
||||
|
||||
footer {
|
||||
padding: 1em;
|
||||
|
@ -52,6 +52,6 @@ footer ul.social.icons li {
|
|||
height: 44px !important;
|
||||
}
|
||||
|
||||
pre code {
|
||||
/*pre code {
|
||||
color: #fff;
|
||||
}
|
||||
}*/
|
||||
|
|
60
_site/css/syntax.css
Normal file
60
_site/css/syntax.css
Normal file
|
@ -0,0 +1,60 @@
|
|||
.highlight { background: #ffffff; padding: 10px; }
|
||||
.highlight .c { color: #999988; font-style: italic } /* Comment */
|
||||
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
|
||||
.highlight .k { font-weight: bold } /* Keyword */
|
||||
.highlight .o { font-weight: bold } /* Operator */
|
||||
.highlight .cm { color: #999988; font-style: italic } /* Comment.Multiline */
|
||||
.highlight .cp { color: #999999; font-weight: bold } /* Comment.Preproc */
|
||||
.highlight .c1 { color: #999988; font-style: italic } /* Comment.Single */
|
||||
.highlight .cs { color: #999999; font-weight: bold; font-style: italic } /* Comment.Special */
|
||||
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
|
||||
.highlight .gd .x { color: #000000; background-color: #ffaaaa } /* Generic.Deleted.Specific */
|
||||
.highlight .ge { font-style: italic } /* Generic.Emph */
|
||||
.highlight .gr { color: #aa0000 } /* Generic.Error */
|
||||
.highlight .gh { color: #999999 } /* Generic.Heading */
|
||||
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
|
||||
.highlight .gi .x { color: #000000; background-color: #aaffaa } /* Generic.Inserted.Specific */
|
||||
.highlight .go { color: #888888 } /* Generic.Output */
|
||||
.highlight .gp { color: #555555 } /* Generic.Prompt */
|
||||
.highlight .gs { font-weight: bold } /* Generic.Strong */
|
||||
.highlight .gu { color: #aaaaaa } /* Generic.Subheading */
|
||||
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
|
||||
.highlight .kc { font-weight: bold } /* Keyword.Constant */
|
||||
.highlight .kd { font-weight: bold } /* Keyword.Declaration */
|
||||
.highlight .kp { font-weight: bold } /* Keyword.Pseudo */
|
||||
.highlight .kr { font-weight: bold } /* Keyword.Reserved */
|
||||
.highlight .kt { color: #445588; font-weight: bold } /* Keyword.Type */
|
||||
.highlight .m { color: #009999 } /* Literal.Number */
|
||||
.highlight .s { color: #d14 } /* Literal.String */
|
||||
.highlight .na { color: #008080 } /* Name.Attribute */
|
||||
.highlight .nb { color: #0086B3 } /* Name.Builtin */
|
||||
.highlight .nc { color: #445588; font-weight: bold } /* Name.Class */
|
||||
.highlight .no { color: #008080 } /* Name.Constant */
|
||||
.highlight .ni { color: #800080 } /* Name.Entity */
|
||||
.highlight .ne { color: #990000; font-weight: bold } /* Name.Exception */
|
||||
.highlight .nf { color: #990000; font-weight: bold } /* Name.Function */
|
||||
.highlight .nn { color: #555555 } /* Name.Namespace */
|
||||
.highlight .nt { color: #000080 } /* Name.Tag */
|
||||
.highlight .nv { color: #008080 } /* Name.Variable */
|
||||
.highlight .ow { font-weight: bold } /* Operator.Word */
|
||||
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
|
||||
.highlight .mf { color: #009999 } /* Literal.Number.Float */
|
||||
.highlight .mh { color: #009999 } /* Literal.Number.Hex */
|
||||
.highlight .mi { color: #009999 } /* Literal.Number.Integer */
|
||||
.highlight .mo { color: #009999 } /* Literal.Number.Oct */
|
||||
.highlight .sb { color: #d14 } /* Literal.String.Backtick */
|
||||
.highlight .sc { color: #d14 } /* Literal.String.Char */
|
||||
.highlight .sd { color: #d14 } /* Literal.String.Doc */
|
||||
.highlight .s2 { color: #d14 } /* Literal.String.Double */
|
||||
.highlight .se { color: #d14 } /* Literal.String.Escape */
|
||||
.highlight .sh { color: #d14 } /* Literal.String.Heredoc */
|
||||
.highlight .si { color: #d14 } /* Literal.String.Interpol */
|
||||
.highlight .sx { color: #d14 } /* Literal.String.Other */
|
||||
.highlight .sr { color: #009926 } /* Literal.String.Regex */
|
||||
.highlight .s1 { color: #d14 } /* Literal.String.Single */
|
||||
.highlight .ss { color: #990073 } /* Literal.String.Symbol */
|
||||
.highlight .bp { color: #999999 } /* Name.Builtin.Pseudo */
|
||||
.highlight .vc { color: #008080 } /* Name.Variable.Class */
|
||||
.highlight .vg { color: #008080 } /* Name.Variable.Global */
|
||||
.highlight .vi { color: #008080 } /* Name.Variable.Instance */
|
||||
.highlight .il { color: #009999 } /* Literal.Number.Integer.Long */
|
|
@ -12,6 +12,7 @@
|
|||
<link rel="stylesheet" href="/css/capistrano.css">
|
||||
<link rel="stylesheet" href="/css/social_foundicons.css" />
|
||||
<link rel="stylesheet" href="/css/okaidia.css">
|
||||
<link rel="stylesheet" href="/css/syntax.css">
|
||||
<script src="/js/vendor/custom.modernizr.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
@ -118,24 +119,24 @@
|
|||
<div class="large-8 column">
|
||||
<div class="content">
|
||||
<h2>Capistrano in ruby script</h2>
|
||||
<p>Instead of building a config folder and deploy, you may want to programmatically set everything in a single ruby script. This could be done as follows:
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>require 'capistrano/all'</p>
|
||||
<p>Instead of building a config folder and deploy, you may want to programmatically set everything in a single ruby script. This could be done as follows:</p>
|
||||
|
||||
<p>stages = "production"
|
||||
set :application, 'my_app_name'
|
||||
set :repo_url, '<a href="mailto:git@github.com">git@github.com</a>:capistrano/capistrano.git'
|
||||
set :deploy_to, '/var/www/'
|
||||
set :stage, :production
|
||||
role :app, %w{}</p>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="nb">require</span> <span class="s1">'capistrano/all'</span>
|
||||
|
||||
<p>require 'capistrano/setup'
|
||||
require 'capistrano/deploy'
|
||||
Dir.glob('capistrano/tasks/*.cap').each { |r| import r }</p>
|
||||
<span class="n">stages</span> <span class="o">=</span> <span class="s2">"production"</span>
|
||||
<span class="n">set</span> <span class="ss">:application</span><span class="p">,</span> <span class="s1">'my_app_name'</span>
|
||||
<span class="n">set</span> <span class="ss">:repo_url</span><span class="p">,</span> <span class="s1">'git@github.com:capistrano/capistrano.git'</span>
|
||||
<span class="n">set</span> <span class="ss">:deploy_to</span><span class="p">,</span> <span class="s1">'/var/www/'</span>
|
||||
<span class="n">set</span> <span class="ss">:stage</span><span class="p">,</span> <span class="ss">:production</span>
|
||||
<span class="n">role</span> <span class="ss">:app</span><span class="p">,</span> <span class="sx">%w{}</span>
|
||||
|
||||
<p>Capistrano::Application.invoke("production")
|
||||
Capistrano::Application.invoke("deploy")</code></pre>
|
||||
</div></p>
|
||||
<span class="nb">require</span> <span class="s1">'capistrano/setup'</span>
|
||||
<span class="nb">require</span> <span class="s1">'capistrano/deploy'</span>
|
||||
<span class="no">Dir</span><span class="o">.</span><span class="n">glob</span><span class="p">(</span><span class="s1">'capistrano/tasks/*.cap'</span><span class="p">)</span><span class="o">.</span><span class="n">each</span> <span class="p">{</span> <span class="o">|</span><span class="n">r</span><span class="o">|</span> <span class="n">import</span> <span class="n">r</span> <span class="p">}</span>
|
||||
|
||||
<span class="no">Capistrano</span><span class="o">::</span><span class="no">Application</span><span class="o">.</span><span class="n">invoke</span><span class="p">(</span><span class="s2">"production"</span><span class="p">)</span>
|
||||
<span class="no">Capistrano</span><span class="o">::</span><span class="no">Application</span><span class="o">.</span><span class="n">invoke</span><span class="p">(</span><span class="s2">"deploy"</span><span class="p">)</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>Note that the require order is important as the stage needs to be set before you load setup and deploy.</p>
|
||||
|
||||
|
@ -148,24 +149,24 @@ Capistrano::Application.invoke("deploy")</code></pre>
|
|||
<!-- <a class="extra" href="/">home</a> -->
|
||||
<!-- </div> -->
|
||||
|
||||
<!-- <p>Instead of building a config folder and deploy, you may want to programmatically set everything in a single ruby script. This could be done as follows:
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>require 'capistrano/all'</p>
|
||||
<!-- <p>Instead of building a config folder and deploy, you may want to programmatically set everything in a single ruby script. This could be done as follows:</p>
|
||||
|
||||
<p>stages = "production"
|
||||
set :application, 'my_app_name'
|
||||
set :repo_url, '<a href="mailto:git@github.com">git@github.com</a>:capistrano/capistrano.git'
|
||||
set :deploy_to, '/var/www/'
|
||||
set :stage, :production
|
||||
role :app, %w{}</p>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="nb">require</span> <span class="s1">'capistrano/all'</span>
|
||||
|
||||
<p>require 'capistrano/setup'
|
||||
require 'capistrano/deploy'
|
||||
Dir.glob('capistrano/tasks/*.cap').each { |r| import r }</p>
|
||||
<span class="n">stages</span> <span class="o">=</span> <span class="s2">"production"</span>
|
||||
<span class="n">set</span> <span class="ss">:application</span><span class="p">,</span> <span class="s1">'my_app_name'</span>
|
||||
<span class="n">set</span> <span class="ss">:repo_url</span><span class="p">,</span> <span class="s1">'git@github.com:capistrano/capistrano.git'</span>
|
||||
<span class="n">set</span> <span class="ss">:deploy_to</span><span class="p">,</span> <span class="s1">'/var/www/'</span>
|
||||
<span class="n">set</span> <span class="ss">:stage</span><span class="p">,</span> <span class="ss">:production</span>
|
||||
<span class="n">role</span> <span class="ss">:app</span><span class="p">,</span> <span class="sx">%w{}</span>
|
||||
|
||||
<p>Capistrano::Application.invoke("production")
|
||||
Capistrano::Application.invoke("deploy")</code></pre>
|
||||
</div></p>
|
||||
<span class="nb">require</span> <span class="s1">'capistrano/setup'</span>
|
||||
<span class="nb">require</span> <span class="s1">'capistrano/deploy'</span>
|
||||
<span class="no">Dir</span><span class="o">.</span><span class="n">glob</span><span class="p">(</span><span class="s1">'capistrano/tasks/*.cap'</span><span class="p">)</span><span class="o">.</span><span class="n">each</span> <span class="p">{</span> <span class="o">|</span><span class="n">r</span><span class="o">|</span> <span class="n">import</span> <span class="n">r</span> <span class="p">}</span>
|
||||
|
||||
<span class="no">Capistrano</span><span class="o">::</span><span class="no">Application</span><span class="o">.</span><span class="n">invoke</span><span class="p">(</span><span class="s2">"production"</span><span class="p">)</span>
|
||||
<span class="no">Capistrano</span><span class="o">::</span><span class="no">Application</span><span class="o">.</span><span class="n">invoke</span><span class="p">(</span><span class="s2">"deploy"</span><span class="p">)</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>Note that the require order is important as the stage needs to be set before you load setup and deploy.</p>
|
||||
-->
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
<link rel="stylesheet" href="/css/capistrano.css">
|
||||
<link rel="stylesheet" href="/css/social_foundicons.css" />
|
||||
<link rel="stylesheet" href="/css/okaidia.css">
|
||||
<link rel="stylesheet" href="/css/syntax.css">
|
||||
<script src="/js/vendor/custom.modernizr.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
@ -128,14 +129,14 @@ that match a given set of hostnames.</p>
|
|||
|
||||
<p>If the filter matches no servers, no actions will be taken.</p>
|
||||
|
||||
<p>If you specify a filter, it will match servers that have the listed hostnames,
|
||||
<p>If you specify a filter, it will match servers that have the listed hostnames,
|
||||
and it will run <em>all</em> the roles for each server. In other words, it only affects
|
||||
the servers the task runs on, not what tasks are run on a server. </p>
|
||||
the servers the task runs on, not what tasks are run on a server.</p>
|
||||
|
||||
<p>You can limit by role and by host; if you do this, the role filtering will
|
||||
apply first. For example, lets say you filtered by the role <code>app</code>, then by
|
||||
the hostnames <code>server1</code> and <code>server2</code>. Capistrano would first filter the
|
||||
available servers to only those with the role <code>app</code>, then filter them
|
||||
available servers to only those with the role <code>app</code>, then filter them
|
||||
to look for servers with the hostname <code>server1</code> or <code>server2</code>. If only <code>server2</code>
|
||||
had the role <code>app</code> (<code>server1</code> has some other role), then in this situation your
|
||||
task would only run on <code>server2</code>.</p>
|
||||
|
@ -149,9 +150,8 @@ task would only run on <code>server2</code>.</p>
|
|||
<p>Capistrano will read the host filter from the environment variable <code>HOSTS</code>
|
||||
if it is set. You can set it inline:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>HOSTS=server1,server2 cap production deploy</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> <span class="nv">HOSTS</span><span class="o">=</span>server1,server2 cap production deploy
|
||||
</code></pre></div>
|
||||
|
||||
<p>Specify multiple hosts by separating them with a comma.</p>
|
||||
|
||||
|
@ -160,9 +160,8 @@ if it is set. You can set it inline:</p>
|
|||
<p>You can set the host filter inside your deploy configuration. For example,
|
||||
you can set the following inside <code>config/deploy.rb</code>:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>set :filter, :hosts => %w{server1 server2}</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="n">set</span> <span class="ss">:filter</span><span class="p">,</span> <span class="ss">:hosts</span> <span class="o">=></span> <span class="sx">%w{server1 server2}</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>Note that you specify the filter as an array rather than as a comma-separated
|
||||
list of servers when using this method.</p>
|
||||
|
@ -172,11 +171,10 @@ list of servers when using this method.</p>
|
|||
<p>In a similar way to using the environment variable, you can set the role
|
||||
filter by specifying it as a command line argument to <code>cap</code>:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>cap --hosts=server1,server2 production deploy</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> cap --hosts<span class="o">=</span>server1,server2 production deploy
|
||||
</code></pre></div>
|
||||
|
||||
<p>Like the environment variable method, specify multiple servers by separating
|
||||
<p>Like the environment variable method, specify multiple servers by separating
|
||||
them with a comma.</p>
|
||||
|
||||
</div>
|
||||
|
@ -198,14 +196,14 @@ that match a given set of hostnames.</p>
|
|||
|
||||
<p>If the filter matches no servers, no actions will be taken.</p>
|
||||
|
||||
<p>If you specify a filter, it will match servers that have the listed hostnames,
|
||||
<p>If you specify a filter, it will match servers that have the listed hostnames,
|
||||
and it will run <em>all</em> the roles for each server. In other words, it only affects
|
||||
the servers the task runs on, not what tasks are run on a server. </p>
|
||||
the servers the task runs on, not what tasks are run on a server.</p>
|
||||
|
||||
<p>You can limit by role and by host; if you do this, the role filtering will
|
||||
apply first. For example, lets say you filtered by the role <code>app</code>, then by
|
||||
the hostnames <code>server1</code> and <code>server2</code>. Capistrano would first filter the
|
||||
available servers to only those with the role <code>app</code>, then filter them
|
||||
available servers to only those with the role <code>app</code>, then filter them
|
||||
to look for servers with the hostname <code>server1</code> or <code>server2</code>. If only <code>server2</code>
|
||||
had the role <code>app</code> (<code>server1</code> has some other role), then in this situation your
|
||||
task would only run on <code>server2</code>.</p>
|
||||
|
@ -219,9 +217,8 @@ task would only run on <code>server2</code>.</p>
|
|||
<p>Capistrano will read the host filter from the environment variable <code>HOSTS</code>
|
||||
if it is set. You can set it inline:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>HOSTS=server1,server2 cap production deploy</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> <span class="nv">HOSTS</span><span class="o">=</span>server1,server2 cap production deploy
|
||||
</code></pre></div>
|
||||
|
||||
<p>Specify multiple hosts by separating them with a comma.</p>
|
||||
|
||||
|
@ -230,9 +227,8 @@ if it is set. You can set it inline:</p>
|
|||
<p>You can set the host filter inside your deploy configuration. For example,
|
||||
you can set the following inside <code>config/deploy.rb</code>:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>set :filter, :hosts => %w{server1 server2}</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="n">set</span> <span class="ss">:filter</span><span class="p">,</span> <span class="ss">:hosts</span> <span class="o">=></span> <span class="sx">%w{server1 server2}</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>Note that you specify the filter as an array rather than as a comma-separated
|
||||
list of servers when using this method.</p>
|
||||
|
@ -242,11 +238,10 @@ list of servers when using this method.</p>
|
|||
<p>In a similar way to using the environment variable, you can set the role
|
||||
filter by specifying it as a command line argument to <code>cap</code>:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>cap --hosts=server1,server2 production deploy</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> cap --hosts<span class="o">=</span>server1,server2 production deploy
|
||||
</code></pre></div>
|
||||
|
||||
<p>Like the environment variable method, specify multiple servers by separating
|
||||
<p>Like the environment variable method, specify multiple servers by separating
|
||||
them with a comma.</p>
|
||||
-->
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
<link rel="stylesheet" href="/css/capistrano.css">
|
||||
<link rel="stylesheet" href="/css/social_foundicons.css" />
|
||||
<link rel="stylesheet" href="/css/okaidia.css">
|
||||
<link rel="stylesheet" href="/css/syntax.css">
|
||||
<script src="/js/vendor/custom.modernizr.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
@ -123,19 +124,18 @@
|
|||
<p>As as example, this task can be used to ensure that files to be linked exist
|
||||
before running the check:linked_files task:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>namespace :deploy do
|
||||
namespace :check do
|
||||
task :linked_files => 'config/newrelic.yml'
|
||||
end
|
||||
end
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="n">namespace</span> <span class="ss">:deploy</span> <span class="k">do</span>
|
||||
<span class="n">namespace</span> <span class="ss">:check</span> <span class="k">do</span>
|
||||
<span class="n">task</span> <span class="ss">:linked_files</span> <span class="o">=></span> <span class="s1">'config/newrelic.yml'</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
|
||||
remote_file 'config/newrelic.yml' => '/tmp/newrelic.yml', roles: :app
|
||||
<span class="n">remote_file</span> <span class="s1">'config/newrelic.yml'</span> <span class="o">=></span> <span class="s1">'/tmp/newrelic.yml'</span><span class="p">,</span> <span class="ss">roles</span><span class="p">:</span> <span class="ss">:app</span>
|
||||
|
||||
file '/tmp/newrelic.yml' do |t|
|
||||
sh "curl -o #{t.name} https://rpm.newrelic.com/accounts/xx/newrelic.yml"
|
||||
end</code></pre>
|
||||
</div>
|
||||
<span class="n">file</span> <span class="s1">'/tmp/newrelic.yml'</span> <span class="k">do</span> <span class="o">|</span><span class="n">t</span><span class="o">|</span>
|
||||
<span class="n">sh</span> <span class="s2">"curl -o </span><span class="si">#{</span><span class="n">t</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2"> https://rpm.newrelic.com/accounts/xx/newrelic.yml"</span>
|
||||
<span class="k">end</span>
|
||||
</code></pre></div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
@ -151,19 +151,18 @@ end</code></pre>
|
|||
<p>As as example, this task can be used to ensure that files to be linked exist
|
||||
before running the check:linked_files task:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>namespace :deploy do
|
||||
namespace :check do
|
||||
task :linked_files => 'config/newrelic.yml'
|
||||
end
|
||||
end
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="n">namespace</span> <span class="ss">:deploy</span> <span class="k">do</span>
|
||||
<span class="n">namespace</span> <span class="ss">:check</span> <span class="k">do</span>
|
||||
<span class="n">task</span> <span class="ss">:linked_files</span> <span class="o">=></span> <span class="s1">'config/newrelic.yml'</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
|
||||
remote_file 'config/newrelic.yml' => '/tmp/newrelic.yml', roles: :app
|
||||
<span class="n">remote_file</span> <span class="s1">'config/newrelic.yml'</span> <span class="o">=></span> <span class="s1">'/tmp/newrelic.yml'</span><span class="p">,</span> <span class="ss">roles</span><span class="p">:</span> <span class="ss">:app</span>
|
||||
|
||||
file '/tmp/newrelic.yml' do |t|
|
||||
sh "curl -o #{t.name} https://rpm.newrelic.com/accounts/xx/newrelic.yml"
|
||||
end</code></pre>
|
||||
</div>
|
||||
<span class="n">file</span> <span class="s1">'/tmp/newrelic.yml'</span> <span class="k">do</span> <span class="o">|</span><span class="n">t</span><span class="o">|</span>
|
||||
<span class="n">sh</span> <span class="s2">"curl -o </span><span class="si">#{</span><span class="n">t</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2"> https://rpm.newrelic.com/accounts/xx/newrelic.yml"</span>
|
||||
<span class="k">end</span>
|
||||
</code></pre></div>
|
||||
-->
|
||||
|
||||
<!--</div> [> /container <] -->
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
<link rel="stylesheet" href="/css/capistrano.css">
|
||||
<link rel="stylesheet" href="/css/social_foundicons.css" />
|
||||
<link rel="stylesheet" href="/css/okaidia.css">
|
||||
<link rel="stylesheet" href="/css/syntax.css">
|
||||
<script src="/js/vendor/custom.modernizr.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
@ -127,7 +128,7 @@ match a given role or roles.</p>
|
|||
|
||||
<p>If the filter matches no servers, no actions will be taken.</p>
|
||||
|
||||
<p>If you specify a filter, it will match any servers that have that role, but
|
||||
<p>If you specify a filter, it will match any servers that have that role, but
|
||||
it will <em>only</em> run the tasks for that role, not for any other roles that
|
||||
server may have. For example, if you filtered for servers with the <code>web</code> role,
|
||||
and a server had both the <code>web</code> and <code>db</code> role, only the <code>web</code> role would
|
||||
|
@ -142,9 +143,8 @@ be executed on it.</p>
|
|||
<p>Capistrano will read the role filter from the environment variable <code>ROLES</code>
|
||||
if it is set. You can set it inline:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>ROLES=app,web cap production deploy</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> <span class="nv">ROLES</span><span class="o">=</span>app,web cap production deploy
|
||||
</code></pre></div>
|
||||
|
||||
<p>Specify multiple roles by separating them with a comma.</p>
|
||||
|
||||
|
@ -153,9 +153,8 @@ if it is set. You can set it inline:</p>
|
|||
<p>You can set the role filter inside your deploy configuration. For example,
|
||||
you can set the following inside <code>config/deploy.rb</code>:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>set :filter, :roles => %w{app web}</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="n">set</span> <span class="ss">:filter</span><span class="p">,</span> <span class="ss">:roles</span> <span class="o">=></span> <span class="sx">%w{app web}</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>Note that you specify the filter as an array rather than as a comma-separated
|
||||
list of roles when using this method.</p>
|
||||
|
@ -165,9 +164,8 @@ list of roles when using this method.</p>
|
|||
<p>In a similar way to using the environment variable, you can set the role
|
||||
filter by specifying it as a command line argument to <code>cap</code>:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>cap --roles=app,web production deploy</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> cap --roles<span class="o">=</span>app,web production deploy
|
||||
</code></pre></div>
|
||||
|
||||
<p>Like the environment variable method, specify multiple roles by separating them
|
||||
with a comma.</p>
|
||||
|
@ -190,7 +188,7 @@ match a given role or roles.</p>
|
|||
|
||||
<p>If the filter matches no servers, no actions will be taken.</p>
|
||||
|
||||
<p>If you specify a filter, it will match any servers that have that role, but
|
||||
<p>If you specify a filter, it will match any servers that have that role, but
|
||||
it will <em>only</em> run the tasks for that role, not for any other roles that
|
||||
server may have. For example, if you filtered for servers with the <code>web</code> role,
|
||||
and a server had both the <code>web</code> and <code>db</code> role, only the <code>web</code> role would
|
||||
|
@ -205,9 +203,8 @@ be executed on it.</p>
|
|||
<p>Capistrano will read the role filter from the environment variable <code>ROLES</code>
|
||||
if it is set. You can set it inline:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>ROLES=app,web cap production deploy</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> <span class="nv">ROLES</span><span class="o">=</span>app,web cap production deploy
|
||||
</code></pre></div>
|
||||
|
||||
<p>Specify multiple roles by separating them with a comma.</p>
|
||||
|
||||
|
@ -216,9 +213,8 @@ if it is set. You can set it inline:</p>
|
|||
<p>You can set the role filter inside your deploy configuration. For example,
|
||||
you can set the following inside <code>config/deploy.rb</code>:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>set :filter, :roles => %w{app web}</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="n">set</span> <span class="ss">:filter</span><span class="p">,</span> <span class="ss">:roles</span> <span class="o">=></span> <span class="sx">%w{app web}</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>Note that you specify the filter as an array rather than as a comma-separated
|
||||
list of roles when using this method.</p>
|
||||
|
@ -228,9 +224,8 @@ list of roles when using this method.</p>
|
|||
<p>In a similar way to using the environment variable, you can set the role
|
||||
filter by specifying it as a command line argument to <code>cap</code>:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>cap --roles=app,web production deploy</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> cap --roles<span class="o">=</span>app,web production deploy
|
||||
</code></pre></div>
|
||||
|
||||
<p>Like the environment variable method, specify multiple roles by separating them
|
||||
with a comma.</p>
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
<link rel="stylesheet" href="/css/capistrano.css">
|
||||
<link rel="stylesheet" href="/css/social_foundicons.css" />
|
||||
<link rel="stylesheet" href="/css/okaidia.css">
|
||||
<link rel="stylesheet" href="/css/syntax.css">
|
||||
<script src="/js/vendor/custom.modernizr.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
@ -122,23 +123,22 @@
|
|||
|
||||
<p>An example setting a working directory, user and environment variable:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>on roles(:app), in: :sequence, wait: 5 do
|
||||
within "/opt/sites/example.com" do
|
||||
# commands in this block execute in the
|
||||
# directory: /opt/sites/example.com
|
||||
as :deploy do
|
||||
# commands in this block execute as the "deploy" user.
|
||||
with rails_env: :production do
|
||||
# commands in this block execute with the environment
|
||||
# variable RAILS_ENV=production
|
||||
rake "assets:precompile"
|
||||
runner "S3::Sync.notify"
|
||||
end
|
||||
end
|
||||
end
|
||||
end</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"><span class="n">on</span> <span class="n">roles</span><span class="p">(</span><span class="ss">:app</span><span class="p">),</span> <span class="k">in</span><span class="p">:</span> <span class="ss">:sequence</span><span class="p">,</span> <span class="ss">wait</span><span class="p">:</span> <span class="mi">5</span> <span class="k">do</span>
|
||||
<span class="n">within</span> <span class="s2">"/opt/sites/example.com"</span> <span class="k">do</span>
|
||||
<span class="c1"># commands in this block execute in the</span>
|
||||
<span class="c1"># directory: /opt/sites/example.com</span>
|
||||
<span class="n">as</span> <span class="ss">:deploy</span> <span class="k">do</span>
|
||||
<span class="c1"># commands in this block execute as the "deploy" user.</span>
|
||||
<span class="n">with</span> <span class="n">rails_env</span><span class="p">:</span> <span class="ss">:production</span> <span class="k">do</span>
|
||||
<span class="c1"># commands in this block execute with the environment</span>
|
||||
<span class="c1"># variable RAILS_ENV=production</span>
|
||||
<span class="n">rake</span> <span class="s2">"assets:precompile"</span>
|
||||
<span class="n">runner</span> <span class="s2">"S3::Sync.notify"</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>For more examples, see the EXAMPLES.md file in the <a href="https://github.com/capistrano/sshkit"><strong>SSHKit</strong></a> project:</p>
|
||||
|
||||
|
@ -157,23 +157,22 @@ end</code></pre>
|
|||
|
||||
<p>An example setting a working directory, user and environment variable:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>on roles(:app), in: :sequence, wait: 5 do
|
||||
within "/opt/sites/example.com" do
|
||||
# commands in this block execute in the
|
||||
# directory: /opt/sites/example.com
|
||||
as :deploy do
|
||||
# commands in this block execute as the "deploy" user.
|
||||
with rails_env: :production do
|
||||
# commands in this block execute with the environment
|
||||
# variable RAILS_ENV=production
|
||||
rake "assets:precompile"
|
||||
runner "S3::Sync.notify"
|
||||
end
|
||||
end
|
||||
end
|
||||
end</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"><span class="n">on</span> <span class="n">roles</span><span class="p">(</span><span class="ss">:app</span><span class="p">),</span> <span class="k">in</span><span class="p">:</span> <span class="ss">:sequence</span><span class="p">,</span> <span class="ss">wait</span><span class="p">:</span> <span class="mi">5</span> <span class="k">do</span>
|
||||
<span class="n">within</span> <span class="s2">"/opt/sites/example.com"</span> <span class="k">do</span>
|
||||
<span class="c1"># commands in this block execute in the</span>
|
||||
<span class="c1"># directory: /opt/sites/example.com</span>
|
||||
<span class="n">as</span> <span class="ss">:deploy</span> <span class="k">do</span>
|
||||
<span class="c1"># commands in this block execute as the "deploy" user.</span>
|
||||
<span class="n">with</span> <span class="n">rails_env</span><span class="p">:</span> <span class="ss">:production</span> <span class="k">do</span>
|
||||
<span class="c1"># commands in this block execute with the environment</span>
|
||||
<span class="c1"># variable RAILS_ENV=production</span>
|
||||
<span class="n">rake</span> <span class="s2">"assets:precompile"</span>
|
||||
<span class="n">runner</span> <span class="s2">"S3::Sync.notify"</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>For more examples, see the EXAMPLES.md file in the <a href="https://github.com/capistrano/sshkit"><strong>SSHKit</strong></a> project:</p>
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
<link rel="stylesheet" href="/css/capistrano.css">
|
||||
<link rel="stylesheet" href="/css/social_foundicons.css" />
|
||||
<link rel="stylesheet" href="/css/okaidia.css">
|
||||
<link rel="stylesheet" href="/css/syntax.css">
|
||||
<script src="/js/vendor/custom.modernizr.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
@ -177,23 +178,21 @@ figure this out!</p>
|
|||
<p>First, we'll try a <em>real</em> SSH session, logging in via our terminal, and seeing
|
||||
what happens:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ ssh me@remote
|
||||
me@remote $ [[ $- == *i* ]] && echo 'Interactive' || echo 'Not interactive'
|
||||
Interactive
|
||||
me@remote $ shopt -q login_shell && echo 'Login shell' || echo 'Not login shell'
|
||||
Login shell</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> me@localhost <span class="nv">$ </span>ssh me@remote
|
||||
me@remote <span class="nv">$ </span><span class="o">[[</span> <span class="nv">$-</span> <span class="o">==</span> *i* <span class="o">]]</span> <span class="o">&&</span> <span class="nb">echo</span> <span class="s1">'Interactive'</span> <span class="o">||</span> <span class="nb">echo</span> <span class="s1">'Not interactive'</span>
|
||||
Interactive
|
||||
me@remote <span class="nv">$ </span><span class="nb">shopt</span> -q login_shell <span class="o">&&</span> <span class="nb">echo</span> <span class="s1">'Login shell'</span> <span class="o">||</span> <span class="nb">echo</span> <span class="s1">'Not login shell'</span>
|
||||
Login shell
|
||||
</code></pre></div>
|
||||
|
||||
<p>Contrast that with what happens when we hand the command to run to the SSH
|
||||
command line without logging in first...</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ ssh me@remote "[[ $- == *i* ]] && echo 'Interactive' || echo 'Not interactive'"
|
||||
Interactive
|
||||
me@localhost $ ssh me@remote "shopt -q login_shell && echo 'Login shell' || echo 'Not login shell'"
|
||||
Not login shell</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> me@localhost <span class="nv">$ </span>ssh me@remote <span class="s2">"[[ $- == *i* ]] && echo 'Interactive' || echo 'Not interactive'"</span>
|
||||
Interactive
|
||||
me@localhost <span class="nv">$ </span>ssh me@remote <span class="s2">"shopt -q login_shell && echo 'Login shell' || echo 'Not login shell'"</span>
|
||||
Not login shell
|
||||
</code></pre></div>
|
||||
|
||||
<p>Here we can see that Bash is still starting in <strong>interactive</strong> mode when we're
|
||||
just running a single command, that's because the terminal we are using is
|
||||
|
@ -203,28 +202,26 @@ interactive, and SSH inherits that and passes that on to the remote server.</p>
|
|||
can have a very simple, Capfile, we don't even need to load the default
|
||||
recipes to test this:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'># Capistrano 3.0.x
|
||||
task :query_interactive do
|
||||
on 'me@remote' do
|
||||
info capture("[[ $- == *i* ]] && echo 'Interactive' || echo 'Not interactive'")
|
||||
end
|
||||
end
|
||||
task :query_login do
|
||||
on 'me@remote' do
|
||||
info capture("shopt -q login_shell && echo 'Login shell' || echo 'Not login shell'")
|
||||
end
|
||||
end</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="c1"># Capistrano 3.0.x</span>
|
||||
<span class="n">task</span> <span class="ss">:query_interactive</span> <span class="k">do</span>
|
||||
<span class="n">on</span> <span class="s1">'me@remote'</span> <span class="k">do</span>
|
||||
<span class="n">info</span> <span class="n">capture</span><span class="p">(</span><span class="s2">"[[ $- == *i* ]] && echo 'Interactive' || echo 'Not interactive'"</span><span class="p">)</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
<span class="n">task</span> <span class="ss">:query_login</span> <span class="k">do</span>
|
||||
<span class="n">on</span> <span class="s1">'me@remote'</span> <span class="k">do</span>
|
||||
<span class="n">info</span> <span class="n">capture</span><span class="p">(</span><span class="s2">"shopt -q login_shell && echo 'Login shell' || echo 'Not login shell'"</span><span class="p">)</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>Gives us the following:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ cap query_login
|
||||
INFO Not login shell
|
||||
me@localhost $ cap query_interactive
|
||||
INFO Not interactive</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> me@localhost <span class="nv">$ </span>cap query_login
|
||||
INFO Not login shell
|
||||
me@localhost <span class="nv">$ </span>cap query_interactive
|
||||
INFO Not interactive
|
||||
</code></pre></div>
|
||||
|
||||
<h2 id="toc_4"><a id="which_startup_files_loaded"></a>Which shell startup files do get loaded?</h2>
|
||||
|
||||
|
@ -305,23 +302,21 @@ figure this out!</p>
|
|||
<p>First, we'll try a <em>real</em> SSH session, logging in via our terminal, and seeing
|
||||
what happens:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ ssh me@remote
|
||||
me@remote $ [[ $- == *i* ]] && echo 'Interactive' || echo 'Not interactive'
|
||||
Interactive
|
||||
me@remote $ shopt -q login_shell && echo 'Login shell' || echo 'Not login shell'
|
||||
Login shell</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> me@localhost <span class="nv">$ </span>ssh me@remote
|
||||
me@remote <span class="nv">$ </span><span class="o">[[</span> <span class="nv">$-</span> <span class="o">==</span> *i* <span class="o">]]</span> <span class="o">&&</span> <span class="nb">echo</span> <span class="s1">'Interactive'</span> <span class="o">||</span> <span class="nb">echo</span> <span class="s1">'Not interactive'</span>
|
||||
Interactive
|
||||
me@remote <span class="nv">$ </span><span class="nb">shopt</span> -q login_shell <span class="o">&&</span> <span class="nb">echo</span> <span class="s1">'Login shell'</span> <span class="o">||</span> <span class="nb">echo</span> <span class="s1">'Not login shell'</span>
|
||||
Login shell
|
||||
</code></pre></div>
|
||||
|
||||
<p>Contrast that with what happens when we hand the command to run to the SSH
|
||||
command line without logging in first...</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ ssh me@remote "[[ $- == *i* ]] && echo 'Interactive' || echo 'Not interactive'"
|
||||
Interactive
|
||||
me@localhost $ ssh me@remote "shopt -q login_shell && echo 'Login shell' || echo 'Not login shell'"
|
||||
Not login shell</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> me@localhost <span class="nv">$ </span>ssh me@remote <span class="s2">"[[ $- == *i* ]] && echo 'Interactive' || echo 'Not interactive'"</span>
|
||||
Interactive
|
||||
me@localhost <span class="nv">$ </span>ssh me@remote <span class="s2">"shopt -q login_shell && echo 'Login shell' || echo 'Not login shell'"</span>
|
||||
Not login shell
|
||||
</code></pre></div>
|
||||
|
||||
<p>Here we can see that Bash is still starting in <strong>interactive</strong> mode when we're
|
||||
just running a single command, that's because the terminal we are using is
|
||||
|
@ -331,28 +326,26 @@ interactive, and SSH inherits that and passes that on to the remote server.</p>
|
|||
can have a very simple, Capfile, we don't even need to load the default
|
||||
recipes to test this:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'># Capistrano 3.0.x
|
||||
task :query_interactive do
|
||||
on 'me@remote' do
|
||||
info capture("[[ $- == *i* ]] && echo 'Interactive' || echo 'Not interactive'")
|
||||
end
|
||||
end
|
||||
task :query_login do
|
||||
on 'me@remote' do
|
||||
info capture("shopt -q login_shell && echo 'Login shell' || echo 'Not login shell'")
|
||||
end
|
||||
end</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="c1"># Capistrano 3.0.x</span>
|
||||
<span class="n">task</span> <span class="ss">:query_interactive</span> <span class="k">do</span>
|
||||
<span class="n">on</span> <span class="s1">'me@remote'</span> <span class="k">do</span>
|
||||
<span class="n">info</span> <span class="n">capture</span><span class="p">(</span><span class="s2">"[[ $- == *i* ]] && echo 'Interactive' || echo 'Not interactive'"</span><span class="p">)</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
<span class="n">task</span> <span class="ss">:query_login</span> <span class="k">do</span>
|
||||
<span class="n">on</span> <span class="s1">'me@remote'</span> <span class="k">do</span>
|
||||
<span class="n">info</span> <span class="n">capture</span><span class="p">(</span><span class="s2">"shopt -q login_shell && echo 'Login shell' || echo 'Not login shell'"</span><span class="p">)</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>Gives us the following:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ cap query_login
|
||||
INFO Not login shell
|
||||
me@localhost $ cap query_interactive
|
||||
INFO Not interactive</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> me@localhost <span class="nv">$ </span>cap query_login
|
||||
INFO Not login shell
|
||||
me@localhost <span class="nv">$ </span>cap query_interactive
|
||||
INFO Not interactive
|
||||
</code></pre></div>
|
||||
|
||||
<h2 id="toc_4"><a id="which_startup_files_loaded"></a>Which shell startup files do get loaded?</h2>
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
<link rel="stylesheet" href="/css/capistrano.css">
|
||||
<link rel="stylesheet" href="/css/social_foundicons.css" />
|
||||
<link rel="stylesheet" href="/css/okaidia.css">
|
||||
<link rel="stylesheet" href="/css/syntax.css">
|
||||
<script src="/js/vendor/custom.modernizr.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
<link rel="stylesheet" href="/css/capistrano.css">
|
||||
<link rel="stylesheet" href="/css/social_foundicons.css" />
|
||||
<link rel="stylesheet" href="/css/okaidia.css">
|
||||
<link rel="stylesheet" href="/css/syntax.css">
|
||||
<script src="/js/vendor/custom.modernizr.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
<link rel="stylesheet" href="/css/capistrano.css">
|
||||
<link rel="stylesheet" href="/css/social_foundicons.css" />
|
||||
<link rel="stylesheet" href="/css/okaidia.css">
|
||||
<link rel="stylesheet" href="/css/syntax.css">
|
||||
<script src="/js/vendor/custom.modernizr.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
<link rel="stylesheet" href="/css/capistrano.css">
|
||||
<link rel="stylesheet" href="/css/social_foundicons.css" />
|
||||
<link rel="stylesheet" href="/css/okaidia.css">
|
||||
<link rel="stylesheet" href="/css/syntax.css">
|
||||
<script src="/js/vendor/custom.modernizr.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
@ -127,10 +128,9 @@ to make this work reliably for unique logins across team members)</p>
|
|||
<p>To create this deploy user we'll assume something like the following has been
|
||||
done:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>root@remote $ adduser deploy
|
||||
root@remote $ passwd -l deploy</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> root@remote <span class="nv">$ </span>adduser deploy
|
||||
root@remote <span class="nv">$ </span>passwd -l deploy
|
||||
</code></pre></div>
|
||||
|
||||
<p>The first line creates a completely standard user, it has a home directory,
|
||||
which we'll need in a moment, and has a shell, so it may log in. This needs to
|
||||
|
@ -170,9 +170,8 @@ public key to the <code>deploy</code> user's <code>authorized_keys</code> fi
|
|||
quits or gets fired, you can remove their key from that file, and the rest of
|
||||
you can keep on shipping!</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ ssh-keygen -t rsa -C 'me@my_email_address.com'</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> me@localhost <span class="nv">$ </span>ssh-keygen -t rsa -C <span class="s1">'me@my_email_address.com'</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>You'll be prompted for a passphrase, that's fine. Type one and keep it safe.
|
||||
This passphrase ensures that if your computer is stolen, people still need a
|
||||
|
@ -188,17 +187,15 @@ minutes upwards.)</p>
|
|||
|
||||
<p>We can see which keys are loaded in the SSH agent by running <code>ssh-add -l</code></p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ ssh-add -l
|
||||
2048 af:ce:7e:c5:93:18:39:ff:54:20:7a:2d:ec:05:7c:a5 /Users/me/.ssh/id_rsa (RSA)</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> me@localhost <span class="nv">$ </span>ssh-add -l
|
||||
2048 af:ce:7e:c5:93:18:39:ff:54:20:7a:2d:ec:05:7c:a5 /Users/me/.ssh/id_rsa <span class="o">(</span>RSA<span class="o">)</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>If you don't see any keys listed, you can simply run <code>ssh-add</code>:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ ssh-add
|
||||
Identity added: /Users/me/.ssh/id_rsa (/Users/me/.ssh/id_rsa)</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> me@localhost <span class="nv">$ </span>ssh-add
|
||||
Identity added: /Users/me/.ssh/id_rsa <span class="o">(</span>/Users/me/.ssh/id_rsa<span class="o">)</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>Typically, ssh-add will ask you for the passphrase when you add a key.</p>
|
||||
|
||||
|
@ -214,10 +211,9 @@ additional identity.</p>
|
|||
<code>/home/users/deploy/.ssh/authorized_keys</code>, to get the contents of that file,
|
||||
we can ask our local key agent for the public parts of the keys it has loaded:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ ssh-add -L
|
||||
ssh-rsa jccXJ/JRfGxnkh/8iL........dbfCH/9cDiKa0Dw8XGAo01mU/w== /Users/me/.ssh/id_rsa</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> me@localhost <span class="nv">$ </span>ssh-add -L
|
||||
ssh-rsa jccXJ/JRfGxnkh/8iL........dbfCH/9cDiKa0Dw8XGAo01mU/w<span class="o">==</span> /Users/me/.ssh/id_rsa
|
||||
</code></pre></div>
|
||||
|
||||
<p>This will be a lot longer when you run it, I snipped the output because it
|
||||
looked bad.</p>
|
||||
|
@ -232,15 +228,14 @@ none, other none), in the <code>~/.ssh</code> directory which needs the permissi
|
|||
<a href="http://linux.die.net/man/1/ssh-copy-id"><code>ssh-copy-id</code></a> which streamlines this
|
||||
process, otherwise the workflow is something like:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ ssh root@remote
|
||||
root@remote $ su - deploy
|
||||
deploy@remote $ cd ~
|
||||
deploy@remote $ mkdir .ssh
|
||||
deploy@remote $ echo "ssh-rsa jccXJ/JRfGxnkh/8iL........dbfCH/9cDiKa0Dw8XGAo01mU/w== /Users/me/.ssh/id_rsa" >> .ssh/authorized_keys
|
||||
deploy@remote $ chmod 700 .ssh
|
||||
deploy@remote $ chmod 600 .ssh/authorized_keys</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> me@localhost <span class="nv">$ </span>ssh root@remote
|
||||
root@remote <span class="nv">$ </span>su - deploy
|
||||
deploy@remote <span class="nv">$ </span><span class="nb">cd</span> ~
|
||||
deploy@remote <span class="nv">$ </span>mkdir .ssh
|
||||
deploy@remote <span class="nv">$ </span><span class="nb">echo</span> <span class="s2">"ssh-rsa jccXJ/JRfGxnkh/8iL........dbfCH/9cDiKa0Dw8XGAo01mU/w== /Users/me/.ssh/id_rsa"</span> >> .ssh/authorized_keys
|
||||
deploy@remote <span class="nv">$ </span>chmod 700 .ssh
|
||||
deploy@remote <span class="nv">$ </span>chmod 600 .ssh/authorized_keys
|
||||
</code></pre></div>
|
||||
|
||||
<p><strong>Remember:</strong> This needs to be done on every server you want to use, you can
|
||||
use the same key for each one, but only one key per developer is recommended.
|
||||
|
@ -248,11 +243,10 @@ use the same key for each one, but only one key per developer is recommended.
|
|||
|
||||
<p>If we did all that correctly, we should now be able to do something like this:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ ssh deploy@one-of-my-servers.com 'hostname; uptime'
|
||||
one-of-my-servers.com
|
||||
19:23:32 up 62 days, 44 min, 1 user, load average: 0.00, 0.01, 0.05</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> me@localhost <span class="nv">$ </span>ssh deploy@one-of-my-servers.com <span class="s1">'hostname; uptime'</span>
|
||||
one-of-my-servers.com
|
||||
19:23:32 up 62 days, 44 min, 1 user, load average: 0.00, 0.01, 0.05
|
||||
</code></pre></div>
|
||||
|
||||
<p>That should happen without having to enter a passphrase for your SSH key, or
|
||||
prompting you for an SSH password (which the deploy user doesn't have anyway).</p>
|
||||
|
@ -283,18 +277,17 @@ charset="utf-8"></script>
|
|||
<p>If your server isn't accessible directly and you need to use the SSH
|
||||
ProxyCommand option, you should do</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>require 'net/ssh/proxy/command'
|
||||
<div class="highlight"><pre><code class="ruby"><span class="nb">require</span> <span class="s1">'net/ssh/proxy/command'</span>
|
||||
|
||||
set :ssh_options, proxy: Net::SSH::Proxy::Command.new('ssh mygateway.com -W %h:%p')
|
||||
<span class="n">set</span> <span class="ss">:ssh_options</span><span class="p">,</span> <span class="ss">proxy</span><span class="p">:</span> <span class="no">Net</span><span class="o">::</span><span class="no">SSH</span><span class="o">::</span><span class="no">Proxy</span><span class="o">::</span><span class="no">Command</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="s1">'ssh mygateway.com -W %h:%p'</span><span class="p">)</span>
|
||||
|
||||
# OR
|
||||
<span class="c1"># OR</span>
|
||||
|
||||
server 'internal-hostname',
|
||||
ssh_options: {
|
||||
proxy: Net::SSH::Proxy::Command.new('ssh mygateway.com -W %h:%p'),
|
||||
}</code></pre>
|
||||
</div>
|
||||
<span class="n">server</span> <span class="s1">'internal-hostname'</span><span class="p">,</span>
|
||||
<span class="n">ssh_options</span><span class="p">:</span> <span class="p">{</span>
|
||||
<span class="ss">proxy</span><span class="p">:</span> <span class="no">Net</span><span class="o">::</span><span class="no">SSH</span><span class="o">::</span><span class="no">Proxy</span><span class="o">::</span><span class="no">Command</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="s1">'ssh mygateway.com -W %h:%p'</span><span class="p">),</span>
|
||||
<span class="p">}</span>
|
||||
</code></pre></div>
|
||||
|
||||
<h4 id="toc_2">1.2 From our servers to the repository host</h4>
|
||||
|
||||
|
@ -311,10 +304,9 @@ Github.</p>
|
|||
|
||||
<p>Here's how we can check if that works, first get the URL of the repository:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ git config remote.origin.url
|
||||
git@github.com:capistrano/rails3-bootstrap-devise-cancan.git</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> me@localhost <span class="nv">$ </span>git config remote.origin.url
|
||||
git@github.com:capistrano/rails3-bootstrap-devise-cancan.git
|
||||
</code></pre></div>
|
||||
|
||||
<p>Here we're listing our private (for testing purposes) fork of the
|
||||
rails3-bootstrap-devise-cancan repository forked from the Rails Examples and
|
||||
|
@ -322,13 +314,12 @@ Tutorials project.</p>
|
|||
|
||||
<p>We can try to access the repository via our server by doing the following:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'># List SSH keys that are loaded into the agent
|
||||
me@localhost $ ssh-add -l
|
||||
# Make sure they key is loaded if 'ssh-add -l' didn't show anything
|
||||
me@localhost $ ssh-add
|
||||
me@localhost $ ssh -A deploy@one-of-my-servers.com 'git ls-remote git@github.com:capistrano/rails3-bootstrap-devise-cancan.git</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> <span class="c"># List SSH keys that are loaded into the agent</span>
|
||||
me@localhost <span class="nv">$ </span>ssh-add -l
|
||||
<span class="c"># Make sure they key is loaded if 'ssh-add -l' didn't show anything</span>
|
||||
me@localhost <span class="nv">$ </span>ssh-add
|
||||
me@localhost <span class="nv">$ </span>ssh -A deploy@one-of-my-servers.com <span class="err">'</span>git ls-remote git@github.com:capistrano/rails3-bootstrap-devise-cancan.git
|
||||
</code></pre></div>
|
||||
|
||||
<p>We first check that the agent has the keys loaded. If not we simply load it
|
||||
and enter the passphrase when prompted.</p>
|
||||
|
@ -344,17 +335,16 @@ to the list of known hosts.</p>
|
|||
|
||||
<p>From the SSH documentation:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>-A Enables forwarding of the authentication agent connection. This can also be
|
||||
specified on a per-host basis in a configuration file.
|
||||
<div class="highlight"><pre><code class="bash"> -A Enables forwarding of the authentication agent connection. This can also be
|
||||
specified on a per-host basis in a configuration file.
|
||||
|
||||
Agent forwarding should be enabled with caution. Users with the ability to
|
||||
bypass file permissions on the remote host (for the agent's UNIX-domain
|
||||
socket) can access the local agent through the forwarded connection. An
|
||||
attacker cannot obtain key material from the agent, however they can perform
|
||||
operations on the keys that enable them to authenticate using the identities
|
||||
loaded into the agent.</code></pre>
|
||||
</div>
|
||||
Agent forwarding should be enabled with caution. Users with the ability to
|
||||
bypass file permissions on the remote host <span class="o">(</span><span class="k">for </span>the agent<span class="err">'</span>s UNIX-domain
|
||||
socket<span class="o">)</span> can access the <span class="nb">local </span>agent through the forwarded connection. An
|
||||
attacker cannot obtain key material from the agent, however they can perform
|
||||
operations on the keys that <span class="nb">enable </span>them to authenticate using the identities
|
||||
loaded into the agent.
|
||||
</code></pre></div>
|
||||
|
||||
<p>In layman's terms, you shouldn't use SSH agent forwarding to machines where you
|
||||
don't trust the administrators, as they can can override the permissions on
|
||||
|
@ -373,11 +363,10 @@ Github, we'll be prompted for a username and password:</p>
|
|||
|
||||
<h5 id="toc_5">1.2.2.1 With a regular username/password</h5>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ git ls-remote https://github.com/capistrano/rails3-bootstrap-devise-cancan.git
|
||||
Username for 'https://github.com': myownusername
|
||||
Password for 'https://capistrano@github.com':</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> me@localhost <span class="nv">$ </span>git ls-remote https://github.com/capistrano/rails3-bootstrap-devise-cancan.git
|
||||
Username <span class="k">for</span> <span class="s1">'https://github.com'</span>: myownusername
|
||||
Password <span class="k">for</span> <span class="s1">'https://capistrano@github.com'</span>:
|
||||
</code></pre></div>
|
||||
|
||||
<p>This challenge response prompt doesn't work well for automating things, so
|
||||
there are two ways to get around this depending on your server's host
|
||||
|
@ -388,11 +377,10 @@ because the netrc is a global file that doesn't lend itself well to security
|
|||
HTTPS not plain ol' HTTP is to embed the username and password in the URL,
|
||||
note this won't work well if your password has special characters:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ git ls-remote https://capistrano:ourverysecretpassword@github.com/capistrano/rails3-bootstrap-devise-cancan.git
|
||||
3419812c9f146d9a84b44bcc2c3caef94da54758HEAD
|
||||
3419812c9f146d9a84b44bcc2c3caef94da54758HEADrefs/heads/master</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> me@localhost <span class="nv">$ </span>git ls-remote https://capistrano:ourverysecretpassword@github.com/capistrano/rails3-bootstrap-devise-cancan.git
|
||||
3419812c9f146d9a84b44bcc2c3caef94da54758HEAD
|
||||
3419812c9f146d9a84b44bcc2c3caef94da54758HEADrefs/heads/master
|
||||
</code></pre></div>
|
||||
|
||||
<p>The bigger problem with passwords, whether inlined into the URL, or entered
|
||||
into a <code>netrc</code> file, is that the password gives access to <strong>your entire Github
|
||||
|
@ -405,11 +393,10 @@ at Github, they recently rolled out a feature called <a href="https://github.com
|
|||
Tokens</a> which allow you to
|
||||
do something like this:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ git ls-remote https://.....................@github.com/capistrano/rails3-bootstrap-devise-cancan.git
|
||||
3419812c9f146d9a84b44bcc2c3caef94da54758HEAD
|
||||
3419812c9f146d9a84b44bcc2c3caef94da54758HEADrefs/heads/master</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> me@localhost <span class="nv">$ </span>git ls-remote https://.....................@github.com/capistrano/rails3-bootstrap-devise-cancan.git
|
||||
3419812c9f146d9a84b44bcc2c3caef94da54758HEAD
|
||||
3419812c9f146d9a84b44bcc2c3caef94da54758HEADrefs/heads/master
|
||||
</code></pre></div>
|
||||
|
||||
<p>Where <code>....</code> is a personal API token, as such:</p>
|
||||
|
||||
|
@ -442,9 +429,8 @@ have configured <em>passwordless</em> <code>sudo</code>. Configuring <code>sudo<
|
|||
access to come commands under some circumstances is beyond the scope of this
|
||||
documentation, but sufficed to say something like:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>deploy ALL=NOPASSWD:/etc/init.d/mysqld, /etc/init.d/apache2</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash">deploy <span class="nv">ALL</span><span class="o">=</span>NOPASSWD:/etc/init.d/mysqld, /etc/init.d/apache2
|
||||
</code></pre></div>
|
||||
|
||||
<p>This example would give the user named <code>deploy</code> access to call <code>sudo
|
||||
/etc/init.d/mysql _________</code> and the same for the <code>apache2</code> control script.</p>
|
||||
|
@ -459,17 +445,16 @@ notice a change.</p>
|
|||
<p>To configure this hierarchy, ignoring for the moment the passwordless <code>sudo</code>
|
||||
access that you may or may not need depending how well your servers are setup:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ ssh root@remote
|
||||
# Capistrano will use /var/www/....... where ... is the value set in
|
||||
# :application, you can override this by setting the ':deploy_to' variable
|
||||
root@remote $ deploy_to=/var/www/rails3-bootstrap-devise-cancan-demo
|
||||
root@remote $ mkdir -p ${deploy_to}
|
||||
root@remote $ chown deploy:deploy ${deploy_to}
|
||||
root@remote $ umask 0002
|
||||
root@remote $ chmod g+s ${deploy_to}
|
||||
root@remote $ mkdir ${deploy_to}/{releases,shared}</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> me@localhost <span class="nv">$ </span>ssh root@remote
|
||||
<span class="c"># Capistrano will use /var/www/....... where ... is the value set in</span>
|
||||
<span class="c"># :application, you can override this by setting the ':deploy_to' variable</span>
|
||||
root@remote <span class="nv">$ deploy_to</span><span class="o">=</span>/var/www/rails3-bootstrap-devise-cancan-demo
|
||||
root@remote <span class="nv">$ </span>mkdir -p <span class="k">${</span><span class="nv">deploy_to</span><span class="k">}</span>
|
||||
root@remote <span class="nv">$ </span>chown deploy:deploy <span class="k">${</span><span class="nv">deploy_to</span><span class="k">}</span>
|
||||
root@remote <span class="nv">$ </span><span class="nb">umask </span>0002
|
||||
root@remote <span class="nv">$ </span>chmod g+s <span class="k">${</span><span class="nv">deploy_to</span><span class="k">}</span>
|
||||
root@remote <span class="nv">$ </span>mkdir <span class="k">${</span><span class="nv">deploy_to</span><span class="k">}</span>/<span class="o">{</span>releases,shared<span class="o">}</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p><strong>Note:</strong> The <code>chmod g+s</code> is a really handy, and little known Unix feature, it
|
||||
means that at the operating system level, without having to pay much attention
|
||||
|
@ -482,14 +467,13 @@ group: read/write, other: none</em>. This means that we'll be able to read t
|
|||
files from Apache, or our web server by running the web server in the <code>deploy</code>
|
||||
group namespace.</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>root@remote # stat -c "%A (%a) %n" ${deploy_to}/
|
||||
drwx--S--- (2700) /var/www/rails3-bootstrap-devise-cancan-demo
|
||||
<div class="highlight"><pre><code class="bash"> root@remote <span class="c"># stat -c "%A (%a) %n" ${deploy_to}/</span>
|
||||
drwx--S--- <span class="o">(</span>2700<span class="o">)</span> /var/www/rails3-bootstrap-devise-cancan-demo
|
||||
|
||||
root@remote # stat -c "%A (%a) %n" ${deploy_to}/*
|
||||
drwxrwsr-x (2775) /var/www/rails3-bootstrap-devise-cancan-demo/releases
|
||||
drwxrwsr-x (2775) /var/www/rails3-bootstrap-devise-cancan-demo/shared</code></pre>
|
||||
</div>
|
||||
root@remote <span class="c"># stat -c "%A (%a) %n" ${deploy_to}/*</span>
|
||||
drwxrwsr-x <span class="o">(</span>2775<span class="o">)</span> /var/www/rails3-bootstrap-devise-cancan-demo/releases
|
||||
drwxrwsr-x <span class="o">(</span>2775<span class="o">)</span> /var/www/rails3-bootstrap-devise-cancan-demo/shared
|
||||
</code></pre></div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
@ -509,10 +493,9 @@ to make this work reliably for unique logins across team members)</p>
|
|||
<p>To create this deploy user we'll assume something like the following has been
|
||||
done:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>root@remote $ adduser deploy
|
||||
root@remote $ passwd -l deploy</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> root@remote <span class="nv">$ </span>adduser deploy
|
||||
root@remote <span class="nv">$ </span>passwd -l deploy
|
||||
</code></pre></div>
|
||||
|
||||
<p>The first line creates a completely standard user, it has a home directory,
|
||||
which we'll need in a moment, and has a shell, so it may log in. This needs to
|
||||
|
@ -552,9 +535,8 @@ public key to the <code>deploy</code> user's <code>authorized_keys</code> fi
|
|||
quits or gets fired, you can remove their key from that file, and the rest of
|
||||
you can keep on shipping!</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ ssh-keygen -t rsa -C 'me@my_email_address.com'</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> me@localhost <span class="nv">$ </span>ssh-keygen -t rsa -C <span class="s1">'me@my_email_address.com'</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>You'll be prompted for a passphrase, that's fine. Type one and keep it safe.
|
||||
This passphrase ensures that if your computer is stolen, people still need a
|
||||
|
@ -570,17 +552,15 @@ minutes upwards.)</p>
|
|||
|
||||
<p>We can see which keys are loaded in the SSH agent by running <code>ssh-add -l</code></p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ ssh-add -l
|
||||
2048 af:ce:7e:c5:93:18:39:ff:54:20:7a:2d:ec:05:7c:a5 /Users/me/.ssh/id_rsa (RSA)</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> me@localhost <span class="nv">$ </span>ssh-add -l
|
||||
2048 af:ce:7e:c5:93:18:39:ff:54:20:7a:2d:ec:05:7c:a5 /Users/me/.ssh/id_rsa <span class="o">(</span>RSA<span class="o">)</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>If you don't see any keys listed, you can simply run <code>ssh-add</code>:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ ssh-add
|
||||
Identity added: /Users/me/.ssh/id_rsa (/Users/me/.ssh/id_rsa)</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> me@localhost <span class="nv">$ </span>ssh-add
|
||||
Identity added: /Users/me/.ssh/id_rsa <span class="o">(</span>/Users/me/.ssh/id_rsa<span class="o">)</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>Typically, ssh-add will ask you for the passphrase when you add a key.</p>
|
||||
|
||||
|
@ -596,10 +576,9 @@ additional identity.</p>
|
|||
<code>/home/users/deploy/.ssh/authorized_keys</code>, to get the contents of that file,
|
||||
we can ask our local key agent for the public parts of the keys it has loaded:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ ssh-add -L
|
||||
ssh-rsa jccXJ/JRfGxnkh/8iL........dbfCH/9cDiKa0Dw8XGAo01mU/w== /Users/me/.ssh/id_rsa</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> me@localhost <span class="nv">$ </span>ssh-add -L
|
||||
ssh-rsa jccXJ/JRfGxnkh/8iL........dbfCH/9cDiKa0Dw8XGAo01mU/w<span class="o">==</span> /Users/me/.ssh/id_rsa
|
||||
</code></pre></div>
|
||||
|
||||
<p>This will be a lot longer when you run it, I snipped the output because it
|
||||
looked bad.</p>
|
||||
|
@ -614,15 +593,14 @@ none, other none), in the <code>~/.ssh</code> directory which needs the permissi
|
|||
<a href="http://linux.die.net/man/1/ssh-copy-id"><code>ssh-copy-id</code></a> which streamlines this
|
||||
process, otherwise the workflow is something like:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ ssh root@remote
|
||||
root@remote $ su - deploy
|
||||
deploy@remote $ cd ~
|
||||
deploy@remote $ mkdir .ssh
|
||||
deploy@remote $ echo "ssh-rsa jccXJ/JRfGxnkh/8iL........dbfCH/9cDiKa0Dw8XGAo01mU/w== /Users/me/.ssh/id_rsa" >> .ssh/authorized_keys
|
||||
deploy@remote $ chmod 700 .ssh
|
||||
deploy@remote $ chmod 600 .ssh/authorized_keys</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> me@localhost <span class="nv">$ </span>ssh root@remote
|
||||
root@remote <span class="nv">$ </span>su - deploy
|
||||
deploy@remote <span class="nv">$ </span><span class="nb">cd</span> ~
|
||||
deploy@remote <span class="nv">$ </span>mkdir .ssh
|
||||
deploy@remote <span class="nv">$ </span><span class="nb">echo</span> <span class="s2">"ssh-rsa jccXJ/JRfGxnkh/8iL........dbfCH/9cDiKa0Dw8XGAo01mU/w== /Users/me/.ssh/id_rsa"</span> >> .ssh/authorized_keys
|
||||
deploy@remote <span class="nv">$ </span>chmod 700 .ssh
|
||||
deploy@remote <span class="nv">$ </span>chmod 600 .ssh/authorized_keys
|
||||
</code></pre></div>
|
||||
|
||||
<p><strong>Remember:</strong> This needs to be done on every server you want to use, you can
|
||||
use the same key for each one, but only one key per developer is recommended.
|
||||
|
@ -630,11 +608,10 @@ use the same key for each one, but only one key per developer is recommended.
|
|||
|
||||
<p>If we did all that correctly, we should now be able to do something like this:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ ssh deploy@one-of-my-servers.com 'hostname; uptime'
|
||||
one-of-my-servers.com
|
||||
19:23:32 up 62 days, 44 min, 1 user, load average: 0.00, 0.01, 0.05</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> me@localhost <span class="nv">$ </span>ssh deploy@one-of-my-servers.com <span class="s1">'hostname; uptime'</span>
|
||||
one-of-my-servers.com
|
||||
19:23:32 up 62 days, 44 min, 1 user, load average: 0.00, 0.01, 0.05
|
||||
</code></pre></div>
|
||||
|
||||
<p>That should happen without having to enter a passphrase for your SSH key, or
|
||||
prompting you for an SSH password (which the deploy user doesn't have anyway).</p>
|
||||
|
@ -665,18 +642,17 @@ charset="utf-8"></script>
|
|||
<p>If your server isn't accessible directly and you need to use the SSH
|
||||
ProxyCommand option, you should do</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>require 'net/ssh/proxy/command'
|
||||
<div class="highlight"><pre><code class="ruby"><span class="nb">require</span> <span class="s1">'net/ssh/proxy/command'</span>
|
||||
|
||||
set :ssh_options, proxy: Net::SSH::Proxy::Command.new('ssh mygateway.com -W %h:%p')
|
||||
<span class="n">set</span> <span class="ss">:ssh_options</span><span class="p">,</span> <span class="ss">proxy</span><span class="p">:</span> <span class="no">Net</span><span class="o">::</span><span class="no">SSH</span><span class="o">::</span><span class="no">Proxy</span><span class="o">::</span><span class="no">Command</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="s1">'ssh mygateway.com -W %h:%p'</span><span class="p">)</span>
|
||||
|
||||
# OR
|
||||
<span class="c1"># OR</span>
|
||||
|
||||
server 'internal-hostname',
|
||||
ssh_options: {
|
||||
proxy: Net::SSH::Proxy::Command.new('ssh mygateway.com -W %h:%p'),
|
||||
}</code></pre>
|
||||
</div>
|
||||
<span class="n">server</span> <span class="s1">'internal-hostname'</span><span class="p">,</span>
|
||||
<span class="n">ssh_options</span><span class="p">:</span> <span class="p">{</span>
|
||||
<span class="ss">proxy</span><span class="p">:</span> <span class="no">Net</span><span class="o">::</span><span class="no">SSH</span><span class="o">::</span><span class="no">Proxy</span><span class="o">::</span><span class="no">Command</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="s1">'ssh mygateway.com -W %h:%p'</span><span class="p">),</span>
|
||||
<span class="p">}</span>
|
||||
</code></pre></div>
|
||||
|
||||
<h4 id="toc_2">1.2 From our servers to the repository host</h4>
|
||||
|
||||
|
@ -693,10 +669,9 @@ Github.</p>
|
|||
|
||||
<p>Here's how we can check if that works, first get the URL of the repository:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ git config remote.origin.url
|
||||
git@github.com:capistrano/rails3-bootstrap-devise-cancan.git</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> me@localhost <span class="nv">$ </span>git config remote.origin.url
|
||||
git@github.com:capistrano/rails3-bootstrap-devise-cancan.git
|
||||
</code></pre></div>
|
||||
|
||||
<p>Here we're listing our private (for testing purposes) fork of the
|
||||
rails3-bootstrap-devise-cancan repository forked from the Rails Examples and
|
||||
|
@ -704,13 +679,12 @@ Tutorials project.</p>
|
|||
|
||||
<p>We can try to access the repository via our server by doing the following:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'># List SSH keys that are loaded into the agent
|
||||
me@localhost $ ssh-add -l
|
||||
# Make sure they key is loaded if 'ssh-add -l' didn't show anything
|
||||
me@localhost $ ssh-add
|
||||
me@localhost $ ssh -A deploy@one-of-my-servers.com 'git ls-remote git@github.com:capistrano/rails3-bootstrap-devise-cancan.git</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> <span class="c"># List SSH keys that are loaded into the agent</span>
|
||||
me@localhost <span class="nv">$ </span>ssh-add -l
|
||||
<span class="c"># Make sure they key is loaded if 'ssh-add -l' didn't show anything</span>
|
||||
me@localhost <span class="nv">$ </span>ssh-add
|
||||
me@localhost <span class="nv">$ </span>ssh -A deploy@one-of-my-servers.com <span class="err">'</span>git ls-remote git@github.com:capistrano/rails3-bootstrap-devise-cancan.git
|
||||
</code></pre></div>
|
||||
|
||||
<p>We first check that the agent has the keys loaded. If not we simply load it
|
||||
and enter the passphrase when prompted.</p>
|
||||
|
@ -726,17 +700,16 @@ to the list of known hosts.</p>
|
|||
|
||||
<p>From the SSH documentation:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>-A Enables forwarding of the authentication agent connection. This can also be
|
||||
specified on a per-host basis in a configuration file.
|
||||
<div class="highlight"><pre><code class="bash"> -A Enables forwarding of the authentication agent connection. This can also be
|
||||
specified on a per-host basis in a configuration file.
|
||||
|
||||
Agent forwarding should be enabled with caution. Users with the ability to
|
||||
bypass file permissions on the remote host (for the agent's UNIX-domain
|
||||
socket) can access the local agent through the forwarded connection. An
|
||||
attacker cannot obtain key material from the agent, however they can perform
|
||||
operations on the keys that enable them to authenticate using the identities
|
||||
loaded into the agent.</code></pre>
|
||||
</div>
|
||||
Agent forwarding should be enabled with caution. Users with the ability to
|
||||
bypass file permissions on the remote host <span class="o">(</span><span class="k">for </span>the agent<span class="err">'</span>s UNIX-domain
|
||||
socket<span class="o">)</span> can access the <span class="nb">local </span>agent through the forwarded connection. An
|
||||
attacker cannot obtain key material from the agent, however they can perform
|
||||
operations on the keys that <span class="nb">enable </span>them to authenticate using the identities
|
||||
loaded into the agent.
|
||||
</code></pre></div>
|
||||
|
||||
<p>In layman's terms, you shouldn't use SSH agent forwarding to machines where you
|
||||
don't trust the administrators, as they can can override the permissions on
|
||||
|
@ -755,11 +728,10 @@ Github, we'll be prompted for a username and password:</p>
|
|||
|
||||
<h5 id="toc_5">1.2.2.1 With a regular username/password</h5>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ git ls-remote https://github.com/capistrano/rails3-bootstrap-devise-cancan.git
|
||||
Username for 'https://github.com': myownusername
|
||||
Password for 'https://capistrano@github.com':</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> me@localhost <span class="nv">$ </span>git ls-remote https://github.com/capistrano/rails3-bootstrap-devise-cancan.git
|
||||
Username <span class="k">for</span> <span class="s1">'https://github.com'</span>: myownusername
|
||||
Password <span class="k">for</span> <span class="s1">'https://capistrano@github.com'</span>:
|
||||
</code></pre></div>
|
||||
|
||||
<p>This challenge response prompt doesn't work well for automating things, so
|
||||
there are two ways to get around this depending on your server's host
|
||||
|
@ -770,11 +742,10 @@ because the netrc is a global file that doesn't lend itself well to security
|
|||
HTTPS not plain ol' HTTP is to embed the username and password in the URL,
|
||||
note this won't work well if your password has special characters:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ git ls-remote https://capistrano:ourverysecretpassword@github.com/capistrano/rails3-bootstrap-devise-cancan.git
|
||||
3419812c9f146d9a84b44bcc2c3caef94da54758HEAD
|
||||
3419812c9f146d9a84b44bcc2c3caef94da54758HEADrefs/heads/master</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> me@localhost <span class="nv">$ </span>git ls-remote https://capistrano:ourverysecretpassword@github.com/capistrano/rails3-bootstrap-devise-cancan.git
|
||||
3419812c9f146d9a84b44bcc2c3caef94da54758HEAD
|
||||
3419812c9f146d9a84b44bcc2c3caef94da54758HEADrefs/heads/master
|
||||
</code></pre></div>
|
||||
|
||||
<p>The bigger problem with passwords, whether inlined into the URL, or entered
|
||||
into a <code>netrc</code> file, is that the password gives access to <strong>your entire Github
|
||||
|
@ -787,11 +758,10 @@ at Github, they recently rolled out a feature called <a href="https://github.com
|
|||
Tokens</a> which allow you to
|
||||
do something like this:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ git ls-remote https://.....................@github.com/capistrano/rails3-bootstrap-devise-cancan.git
|
||||
3419812c9f146d9a84b44bcc2c3caef94da54758HEAD
|
||||
3419812c9f146d9a84b44bcc2c3caef94da54758HEADrefs/heads/master</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> me@localhost <span class="nv">$ </span>git ls-remote https://.....................@github.com/capistrano/rails3-bootstrap-devise-cancan.git
|
||||
3419812c9f146d9a84b44bcc2c3caef94da54758HEAD
|
||||
3419812c9f146d9a84b44bcc2c3caef94da54758HEADrefs/heads/master
|
||||
</code></pre></div>
|
||||
|
||||
<p>Where <code>....</code> is a personal API token, as such:</p>
|
||||
|
||||
|
@ -824,9 +794,8 @@ have configured <em>passwordless</em> <code>sudo</code>. Configuring <code>sudo<
|
|||
access to come commands under some circumstances is beyond the scope of this
|
||||
documentation, but sufficed to say something like:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>deploy ALL=NOPASSWD:/etc/init.d/mysqld, /etc/init.d/apache2</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash">deploy <span class="nv">ALL</span><span class="o">=</span>NOPASSWD:/etc/init.d/mysqld, /etc/init.d/apache2
|
||||
</code></pre></div>
|
||||
|
||||
<p>This example would give the user named <code>deploy</code> access to call <code>sudo
|
||||
/etc/init.d/mysql _________</code> and the same for the <code>apache2</code> control script.</p>
|
||||
|
@ -841,17 +810,16 @@ notice a change.</p>
|
|||
<p>To configure this hierarchy, ignoring for the moment the passwordless <code>sudo</code>
|
||||
access that you may or may not need depending how well your servers are setup:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ ssh root@remote
|
||||
# Capistrano will use /var/www/....... where ... is the value set in
|
||||
# :application, you can override this by setting the ':deploy_to' variable
|
||||
root@remote $ deploy_to=/var/www/rails3-bootstrap-devise-cancan-demo
|
||||
root@remote $ mkdir -p ${deploy_to}
|
||||
root@remote $ chown deploy:deploy ${deploy_to}
|
||||
root@remote $ umask 0002
|
||||
root@remote $ chmod g+s ${deploy_to}
|
||||
root@remote $ mkdir ${deploy_to}/{releases,shared}</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> me@localhost <span class="nv">$ </span>ssh root@remote
|
||||
<span class="c"># Capistrano will use /var/www/....... where ... is the value set in</span>
|
||||
<span class="c"># :application, you can override this by setting the ':deploy_to' variable</span>
|
||||
root@remote <span class="nv">$ deploy_to</span><span class="o">=</span>/var/www/rails3-bootstrap-devise-cancan-demo
|
||||
root@remote <span class="nv">$ </span>mkdir -p <span class="k">${</span><span class="nv">deploy_to</span><span class="k">}</span>
|
||||
root@remote <span class="nv">$ </span>chown deploy:deploy <span class="k">${</span><span class="nv">deploy_to</span><span class="k">}</span>
|
||||
root@remote <span class="nv">$ </span><span class="nb">umask </span>0002
|
||||
root@remote <span class="nv">$ </span>chmod g+s <span class="k">${</span><span class="nv">deploy_to</span><span class="k">}</span>
|
||||
root@remote <span class="nv">$ </span>mkdir <span class="k">${</span><span class="nv">deploy_to</span><span class="k">}</span>/<span class="o">{</span>releases,shared<span class="o">}</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p><strong>Note:</strong> The <code>chmod g+s</code> is a really handy, and little known Unix feature, it
|
||||
means that at the operating system level, without having to pay much attention
|
||||
|
@ -864,14 +832,13 @@ group: read/write, other: none</em>. This means that we'll be able to read t
|
|||
files from Apache, or our web server by running the web server in the <code>deploy</code>
|
||||
group namespace.</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>root@remote # stat -c "%A (%a) %n" ${deploy_to}/
|
||||
drwx--S--- (2700) /var/www/rails3-bootstrap-devise-cancan-demo
|
||||
<div class="highlight"><pre><code class="bash"> root@remote <span class="c"># stat -c "%A (%a) %n" ${deploy_to}/</span>
|
||||
drwx--S--- <span class="o">(</span>2700<span class="o">)</span> /var/www/rails3-bootstrap-devise-cancan-demo
|
||||
|
||||
root@remote # stat -c "%A (%a) %n" ${deploy_to}/*
|
||||
drwxrwsr-x (2775) /var/www/rails3-bootstrap-devise-cancan-demo/releases
|
||||
drwxrwsr-x (2775) /var/www/rails3-bootstrap-devise-cancan-demo/shared</code></pre>
|
||||
</div>
|
||||
root@remote <span class="c"># stat -c "%A (%a) %n" ${deploy_to}/*</span>
|
||||
drwxrwsr-x <span class="o">(</span>2775<span class="o">)</span> /var/www/rails3-bootstrap-devise-cancan-demo/releases
|
||||
drwxrwsr-x <span class="o">(</span>2775<span class="o">)</span> /var/www/rails3-bootstrap-devise-cancan-demo/shared
|
||||
</code></pre></div>
|
||||
-->
|
||||
|
||||
<!--</div> [> /container <] -->
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
<link rel="stylesheet" href="/css/capistrano.css">
|
||||
<link rel="stylesheet" href="/css/social_foundicons.css" />
|
||||
<link rel="stylesheet" href="/css/okaidia.css">
|
||||
<link rel="stylesheet" href="/css/syntax.css">
|
||||
<script src="/js/vendor/custom.modernizr.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
@ -135,19 +136,18 @@ technologies.</p>
|
|||
|
||||
<h3 id="toc_0">1. Checking the directory structure on the remote machine:</h3>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ ssh deploy@remote 'ls -lR /var/www/my-application'
|
||||
my-application:
|
||||
total 8
|
||||
drwxrwsr-x 2 deploy deploy 4096 Jun 24 20:55 releases
|
||||
drwxrwsr-x 2 deploy deploy 4096 Jun 24 20:55 shared
|
||||
<div class="highlight"><pre><code class="bash"> me@localhost <span class="nv">$ </span>ssh deploy@remote <span class="s1">'ls -lR /var/www/my-application'</span>
|
||||
my-application:
|
||||
total 8
|
||||
drwxrwsr-x 2 deploy deploy 4096 Jun 24 20:55 releases
|
||||
drwxrwsr-x 2 deploy deploy 4096 Jun 24 20:55 shared
|
||||
|
||||
my-application/releases:
|
||||
total 0
|
||||
my-application/releases:
|
||||
total 0
|
||||
|
||||
my-application/shared:
|
||||
total 0</code></pre>
|
||||
</div>
|
||||
my-application/shared:
|
||||
total 0
|
||||
</code></pre></div>
|
||||
|
||||
<p>This checks in one simple command that the ssh keys you setup are working (you
|
||||
might yet be prompted for the password), and the permissions on the directory
|
||||
|
@ -159,18 +159,17 @@ can be seen.</p>
|
|||
quickly introduce ourselves to a quick Cap task to check these things on all
|
||||
the machines for us:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>desc "Check that we can access everything"
|
||||
task :check_write_permissions do
|
||||
on roles(:all) do |host|
|
||||
if test("[ -w #{fetch(:deploy_to)} ]")
|
||||
info "#{fetch(:deploy_to)} is writable on #{host}"
|
||||
else
|
||||
error "#{fetch(:deploy_to)} is not writable on #{host}"
|
||||
end
|
||||
end
|
||||
end</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="n">desc</span> <span class="s2">"Check that we can access everything"</span>
|
||||
<span class="n">task</span> <span class="ss">:check_write_permissions</span> <span class="k">do</span>
|
||||
<span class="n">on</span> <span class="n">roles</span><span class="p">(</span><span class="ss">:all</span><span class="p">)</span> <span class="k">do</span> <span class="o">|</span><span class="n">host</span><span class="o">|</span>
|
||||
<span class="k">if</span> <span class="nb">test</span><span class="p">(</span><span class="s2">"[ -w </span><span class="si">#{</span><span class="n">fetch</span><span class="p">(</span><span class="ss">:deploy_to</span><span class="p">)</span><span class="si">}</span><span class="s2"> ]"</span><span class="p">)</span>
|
||||
<span class="n">info</span> <span class="s2">"</span><span class="si">#{</span><span class="n">fetch</span><span class="p">(</span><span class="ss">:deploy_to</span><span class="p">)</span><span class="si">}</span><span class="s2"> is writable on </span><span class="si">#{</span><span class="n">host</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="k">else</span>
|
||||
<span class="n">error</span> <span class="s2">"</span><span class="si">#{</span><span class="n">fetch</span><span class="p">(</span><span class="ss">:deploy_to</span><span class="p">)</span><span class="si">}</span><span class="s2"> is not writable on </span><span class="si">#{</span><span class="n">host</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>Running this should give you a pretty decent overview, one line of output for
|
||||
each server. It's also your first introduction to the API of Capistrano for
|
||||
|
@ -185,22 +184,20 @@ later, but add those lines to a file in <code>./lib/capistrano/tasks</code>, cal
|
|||
something like <code>access_check.cap</code>, and run <code>cap -T</code> from the top directory and
|
||||
we'll be able to see the task listed:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ bundle exec cap -T
|
||||
# ... lots of other tasks ...
|
||||
cap check_write_permissions # Check that we can access everything
|
||||
# ... lots of other tasks ...</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> me@localhost <span class="nv">$ </span>bundle <span class="nb">exec </span>cap -T
|
||||
<span class="c"># ... lots of other tasks ...</span>
|
||||
cap check_write_permissions <span class="c"># Check that we can access everything</span>
|
||||
<span class="c"># ... lots of other tasks ...</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>Then we simply call it:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ bundle exec cap staging check_write_permissions
|
||||
DEBUG [82c92144] Running /usr/bin/env [ -w /var/www/my-application ] on myserver.com
|
||||
DEBUG [82c92144] Command: [ -w /var/www/my-application ]
|
||||
DEBUG [82c92144] Finished in 0.456 seconds command successful.
|
||||
INFO /var/www/my-application is writable on myserver.com</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> me@localhost <span class="nv">$ </span>bundle <span class="nb">exec </span>cap staging check_write_permissions
|
||||
DEBUG <span class="o">[</span>82c92144<span class="o">]</span> Running /usr/bin/env <span class="o">[</span> -w /var/www/my-application <span class="o">]</span> on myserver.com
|
||||
DEBUG <span class="o">[</span>82c92144<span class="o">]</span> Command: <span class="o">[</span> -w /var/www/my-application <span class="o">]</span>
|
||||
DEBUG <span class="o">[</span>82c92144<span class="o">]</span> Finished in 0.456 seconds <span class="nb">command </span>successful.
|
||||
INFO /var/www/my-application is writable on myserver.com
|
||||
</code></pre></div>
|
||||
|
||||
<p>If we've done something wrong, that won't happen and we'll know that we need
|
||||
to jump on the mailing list to get help, into IRC or ask a friend.</p>
|
||||
|
@ -213,9 +210,8 @@ wrap Git in a shell script that makes it behave.</p>
|
|||
<p>Capistrano does just this, so to check if the Git access is working, we can
|
||||
simply call:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ cap staging git:check</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> me@localhost <span class="nv">$ </span>cap staging git:check
|
||||
</code></pre></div>
|
||||
|
||||
<p>This task is defined
|
||||
<a href="https://github.com/capistrano/capistrano/blob/master/lib/capistrano/tasks/git.rake">here</a>
|
||||
|
@ -228,26 +224,25 @@ one of the pieces we inherit from Rake)</p>
|
|||
|
||||
<p>If this fails we'll see:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ cap staging git:check
|
||||
cap staging git:check
|
||||
DEBUG Uploading /tmp/git-ssh.sh 0%
|
||||
INFO Uploading /tmp/git-ssh.sh 100%
|
||||
INFO [118bd3e4] Running /usr/bin/env chmod +x /tmp/git-ssh.sh on example.com
|
||||
DEBUG [118bd3e4] Command: /usr/bin/env chmod +x /tmp/git-ssh.sh
|
||||
INFO [118bd3e4] Finished in 0.049 seconds command successful.
|
||||
INFO [a996463f] Running /usr/bin/env git ls-remote git@github.com:capistrano/rails3-bootstrap-devise-cancan.git on harrow
|
||||
DEBUG [a996463f] Command: ( GIT_ASKPASS=/bin/echo GIT_SSH=/tmp/git-ssh.sh /usr/bin/env git ls-remote git@github.com:capistrano/rails3-bootstrap-devise-cancan.git )
|
||||
DEBUG [a996463f] Warning: Permanently added 'github.com,204.232.175.90' (RSA) to the list of known hosts.
|
||||
DEBUG [a996463f] Permission denied (publickey).
|
||||
DEBUG [a996463f] fatal: The remote end hung up unexpectedly
|
||||
cap aborted!
|
||||
git stdout: Nothing written
|
||||
git stderr: Nothing written
|
||||
<div class="highlight"><pre><code class="bash"> me@localhost <span class="nv">$ </span>cap staging git:check
|
||||
cap staging git:check
|
||||
DEBUG Uploading /tmp/git-ssh.sh 0%
|
||||
INFO Uploading /tmp/git-ssh.sh 100%
|
||||
INFO <span class="o">[</span>118bd3e4<span class="o">]</span> Running /usr/bin/env chmod +x /tmp/git-ssh.sh on example.com
|
||||
DEBUG <span class="o">[</span>118bd3e4<span class="o">]</span> Command: /usr/bin/env chmod +x /tmp/git-ssh.sh
|
||||
INFO <span class="o">[</span>118bd3e4<span class="o">]</span> Finished in 0.049 seconds <span class="nb">command </span>successful.
|
||||
INFO <span class="o">[</span>a996463f<span class="o">]</span> Running /usr/bin/env git ls-remote git@github.com:capistrano/rails3-bootstrap-devise-cancan.git on harrow
|
||||
DEBUG <span class="o">[</span>a996463f<span class="o">]</span> Command: <span class="o">(</span> <span class="nv">GIT_ASKPASS</span><span class="o">=</span>/bin/echo <span class="nv">GIT_SSH</span><span class="o">=</span>/tmp/git-ssh.sh /usr/bin/env git ls-remote git@github.com:capistrano/rails3-bootstrap-devise-cancan.git <span class="o">)</span>
|
||||
DEBUG <span class="o">[</span>a996463f<span class="o">]</span> Warning: Permanently added <span class="s1">'github.com,204.232.175.90'</span> <span class="o">(</span>RSA<span class="o">)</span> to the list of known hosts.
|
||||
DEBUG <span class="o">[</span>a996463f<span class="o">]</span> Permission denied <span class="o">(</span>publickey<span class="o">)</span>.
|
||||
DEBUG <span class="o">[</span>a996463f<span class="o">]</span> fatal: The remote end hung up unexpectedly
|
||||
cap aborted!
|
||||
git stdout: Nothing written
|
||||
git stderr: Nothing written
|
||||
|
||||
Tasks: TOP => git:check
|
||||
(See full trace by running task with --trace)</code></pre>
|
||||
</div>
|
||||
Tasks: <span class="nv">TOP</span> <span class="o">=</span>> git:check
|
||||
<span class="o">(</span>See full trace by running task with --trace<span class="o">)</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>This'll typically come out looking more beautiful depending on your terminal
|
||||
colour support, you may well see something like this:</p>
|
||||
|
@ -276,56 +271,52 @@ printed out the error messages for us to try and figure out what broke.</li>
|
|||
working by writing a tiny Cap task, or simply using SSH to do it for us, the
|
||||
choice is yours:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'># lib/capistrano/tasks/agent_forwarding.cap
|
||||
desc "Check if agent forwarding is working"
|
||||
task :forwarding do
|
||||
on roles(:all) do |h|
|
||||
if test("env | grep SSH_AUTH_SOCK")
|
||||
info "Agent forwarding is up to #{h}"
|
||||
else
|
||||
error "Agent forwarding is NOT up to #{h}"
|
||||
end
|
||||
end
|
||||
end</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="c1"># lib/capistrano/tasks/agent_forwarding.cap</span>
|
||||
<span class="n">desc</span> <span class="s2">"Check if agent forwarding is working"</span>
|
||||
<span class="n">task</span> <span class="ss">:forwarding</span> <span class="k">do</span>
|
||||
<span class="n">on</span> <span class="n">roles</span><span class="p">(</span><span class="ss">:all</span><span class="p">)</span> <span class="k">do</span> <span class="o">|</span><span class="n">h</span><span class="o">|</span>
|
||||
<span class="k">if</span> <span class="nb">test</span><span class="p">(</span><span class="s2">"env | grep SSH_AUTH_SOCK"</span><span class="p">)</span>
|
||||
<span class="n">info</span> <span class="s2">"Agent forwarding is up to </span><span class="si">#{</span><span class="n">h</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="k">else</span>
|
||||
<span class="n">error</span> <span class="s2">"Agent forwarding is NOT up to </span><span class="si">#{</span><span class="n">h</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>That gave the output:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>cap staging forwarding
|
||||
DEBUG [f1269276] Running /usr/bin/env env | grep SSH_AUTH_SOCK on example.com
|
||||
DEBUG [f1269276] Command: env | grep SSH_AUTH_SOCK
|
||||
DEBUG [f1269276] SSH_AUTH_SOCK=/tmp/ssh-nQUEmyQ2nS/agent.2546
|
||||
DEBUG [f1269276] Finished in 0.453 seconds command successful.
|
||||
INFO Agent forwarding is up to example.com</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> cap staging forwarding
|
||||
DEBUG <span class="o">[</span>f1269276<span class="o">]</span> Running /usr/bin/env env <span class="p">|</span> grep SSH_AUTH_SOCK on example.com
|
||||
DEBUG <span class="o">[</span>f1269276<span class="o">]</span> Command: env <span class="p">|</span> grep SSH_AUTH_SOCK
|
||||
DEBUG <span class="o">[</span>f1269276<span class="o">]</span> <span class="nv">SSH_AUTH_SOCK</span><span class="o">=</span>/tmp/ssh-nQUEmyQ2nS/agent.2546
|
||||
DEBUG <span class="o">[</span>f1269276<span class="o">]</span> Finished in 0.453 seconds <span class="nb">command </span>successful.
|
||||
INFO Agent forwarding is up to example.com
|
||||
</code></pre></div>
|
||||
|
||||
<p>If you don't feel like writing a Capistrano task, one could simply do:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ ssh -A example.com 'env | grep SSH_AUTH_SOCK'
|
||||
SSH_AUTH_SOCK=/tmp/ssh-Tb6X8V53tm/agent.2934</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> me@localhost <span class="nv">$ </span>ssh -A example.com <span class="s1">'env | grep SSH_AUTH_SOCK'</span>
|
||||
<span class="nv">SSH_AUTH_SOCK</span><span class="o">=</span>/tmp/ssh-Tb6X8V53tm/agent.2934
|
||||
</code></pre></div>
|
||||
|
||||
<p>If we see the <code>SSH_AUTH_SOCK</code> output, that's a pretty good indication that SSH
|
||||
agent forwarding is enabled, and if on your local machine <code>ssh-add -l</code> shows
|
||||
you an SSH key, then we're good to go. <strong>Make sure that you're using the
|
||||
<code>git@...</code> repository URL</strong></p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>cap staging git:check
|
||||
DEBUG Uploading /tmp/git-ssh.sh 0%
|
||||
INFO Uploading /tmp/git-ssh.sh 100%
|
||||
INFO [21382716] Running /usr/bin/env chmod +x /tmp/git-ssh.sh on example.com
|
||||
DEBUG [21382716] Command: /usr/bin/env chmod +x /tmp/git-ssh.sh
|
||||
INFO [21382716] Finished in 0.047 seconds command successful.
|
||||
INFO [f40edfbb] Running /usr/bin/env git ls-remote git@github.com:capistrano/rails3-bootstrap-devise-cancan.git on example.com
|
||||
DEBUG [f40edfbb] Command: ( GIT_ASKPASS=/bin/echo GIT_SSH=/tmp/git-ssh.sh /usr/bin/env git ls-remote git@github.com:capistrano/rails3-bootstrap-devise-cancan.git )
|
||||
DEBUG [f40edfbb] 3419812c9f146d9a84b44bcc2c3caef94da54758 HEAD
|
||||
DEBUG [f40edfbb] 3419812c9f146d9a84b44bcc2c3caef94da54758 refs/heads/master
|
||||
INFO [f40edfbb] Finished in 3.319 seconds command successful.</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> cap staging git:check
|
||||
DEBUG Uploading /tmp/git-ssh.sh 0%
|
||||
INFO Uploading /tmp/git-ssh.sh 100%
|
||||
INFO <span class="o">[</span>21382716<span class="o">]</span> Running /usr/bin/env chmod +x /tmp/git-ssh.sh on example.com
|
||||
DEBUG <span class="o">[</span>21382716<span class="o">]</span> Command: /usr/bin/env chmod +x /tmp/git-ssh.sh
|
||||
INFO <span class="o">[</span>21382716<span class="o">]</span> Finished in 0.047 seconds <span class="nb">command </span>successful.
|
||||
INFO <span class="o">[</span>f40edfbb<span class="o">]</span> Running /usr/bin/env git ls-remote git@github.com:capistrano/rails3-bootstrap-devise-cancan.git on example.com
|
||||
DEBUG <span class="o">[</span>f40edfbb<span class="o">]</span> Command: <span class="o">(</span> <span class="nv">GIT_ASKPASS</span><span class="o">=</span>/bin/echo <span class="nv">GIT_SSH</span><span class="o">=</span>/tmp/git-ssh.sh /usr/bin/env git ls-remote git@github.com:capistrano/rails3-bootstrap-devise-cancan.git <span class="o">)</span>
|
||||
DEBUG <span class="o">[</span>f40edfbb<span class="o">]</span> 3419812c9f146d9a84b44bcc2c3caef94da54758 HEAD
|
||||
DEBUG <span class="o">[</span>f40edfbb<span class="o">]</span> 3419812c9f146d9a84b44bcc2c3caef94da54758 refs/heads/master
|
||||
INFO <span class="o">[</span>f40edfbb<span class="o">]</span> Finished in 3.319 seconds <span class="nb">command </span>successful.
|
||||
</code></pre></div>
|
||||
|
||||
<p><img src="/images/successful-git-check-example-screenshot.png" alt="Capistrano Git Check Colour Example"></p>
|
||||
|
||||
|
@ -355,19 +346,18 @@ technologies.</p>
|
|||
|
||||
<h3 id="toc_0">1. Checking the directory structure on the remote machine:</h3>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ ssh deploy@remote 'ls -lR /var/www/my-application'
|
||||
my-application:
|
||||
total 8
|
||||
drwxrwsr-x 2 deploy deploy 4096 Jun 24 20:55 releases
|
||||
drwxrwsr-x 2 deploy deploy 4096 Jun 24 20:55 shared
|
||||
<div class="highlight"><pre><code class="bash"> me@localhost <span class="nv">$ </span>ssh deploy@remote <span class="s1">'ls -lR /var/www/my-application'</span>
|
||||
my-application:
|
||||
total 8
|
||||
drwxrwsr-x 2 deploy deploy 4096 Jun 24 20:55 releases
|
||||
drwxrwsr-x 2 deploy deploy 4096 Jun 24 20:55 shared
|
||||
|
||||
my-application/releases:
|
||||
total 0
|
||||
my-application/releases:
|
||||
total 0
|
||||
|
||||
my-application/shared:
|
||||
total 0</code></pre>
|
||||
</div>
|
||||
my-application/shared:
|
||||
total 0
|
||||
</code></pre></div>
|
||||
|
||||
<p>This checks in one simple command that the ssh keys you setup are working (you
|
||||
might yet be prompted for the password), and the permissions on the directory
|
||||
|
@ -379,18 +369,17 @@ can be seen.</p>
|
|||
quickly introduce ourselves to a quick Cap task to check these things on all
|
||||
the machines for us:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>desc "Check that we can access everything"
|
||||
task :check_write_permissions do
|
||||
on roles(:all) do |host|
|
||||
if test("[ -w #{fetch(:deploy_to)} ]")
|
||||
info "#{fetch(:deploy_to)} is writable on #{host}"
|
||||
else
|
||||
error "#{fetch(:deploy_to)} is not writable on #{host}"
|
||||
end
|
||||
end
|
||||
end</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="n">desc</span> <span class="s2">"Check that we can access everything"</span>
|
||||
<span class="n">task</span> <span class="ss">:check_write_permissions</span> <span class="k">do</span>
|
||||
<span class="n">on</span> <span class="n">roles</span><span class="p">(</span><span class="ss">:all</span><span class="p">)</span> <span class="k">do</span> <span class="o">|</span><span class="n">host</span><span class="o">|</span>
|
||||
<span class="k">if</span> <span class="nb">test</span><span class="p">(</span><span class="s2">"[ -w </span><span class="si">#{</span><span class="n">fetch</span><span class="p">(</span><span class="ss">:deploy_to</span><span class="p">)</span><span class="si">}</span><span class="s2"> ]"</span><span class="p">)</span>
|
||||
<span class="n">info</span> <span class="s2">"</span><span class="si">#{</span><span class="n">fetch</span><span class="p">(</span><span class="ss">:deploy_to</span><span class="p">)</span><span class="si">}</span><span class="s2"> is writable on </span><span class="si">#{</span><span class="n">host</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="k">else</span>
|
||||
<span class="n">error</span> <span class="s2">"</span><span class="si">#{</span><span class="n">fetch</span><span class="p">(</span><span class="ss">:deploy_to</span><span class="p">)</span><span class="si">}</span><span class="s2"> is not writable on </span><span class="si">#{</span><span class="n">host</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>Running this should give you a pretty decent overview, one line of output for
|
||||
each server. It's also your first introduction to the API of Capistrano for
|
||||
|
@ -405,22 +394,20 @@ later, but add those lines to a file in <code>./lib/capistrano/tasks</code>, cal
|
|||
something like <code>access_check.cap</code>, and run <code>cap -T</code> from the top directory and
|
||||
we'll be able to see the task listed:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ bundle exec cap -T
|
||||
# ... lots of other tasks ...
|
||||
cap check_write_permissions # Check that we can access everything
|
||||
# ... lots of other tasks ...</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> me@localhost <span class="nv">$ </span>bundle <span class="nb">exec </span>cap -T
|
||||
<span class="c"># ... lots of other tasks ...</span>
|
||||
cap check_write_permissions <span class="c"># Check that we can access everything</span>
|
||||
<span class="c"># ... lots of other tasks ...</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>Then we simply call it:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ bundle exec cap staging check_write_permissions
|
||||
DEBUG [82c92144] Running /usr/bin/env [ -w /var/www/my-application ] on myserver.com
|
||||
DEBUG [82c92144] Command: [ -w /var/www/my-application ]
|
||||
DEBUG [82c92144] Finished in 0.456 seconds command successful.
|
||||
INFO /var/www/my-application is writable on myserver.com</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> me@localhost <span class="nv">$ </span>bundle <span class="nb">exec </span>cap staging check_write_permissions
|
||||
DEBUG <span class="o">[</span>82c92144<span class="o">]</span> Running /usr/bin/env <span class="o">[</span> -w /var/www/my-application <span class="o">]</span> on myserver.com
|
||||
DEBUG <span class="o">[</span>82c92144<span class="o">]</span> Command: <span class="o">[</span> -w /var/www/my-application <span class="o">]</span>
|
||||
DEBUG <span class="o">[</span>82c92144<span class="o">]</span> Finished in 0.456 seconds <span class="nb">command </span>successful.
|
||||
INFO /var/www/my-application is writable on myserver.com
|
||||
</code></pre></div>
|
||||
|
||||
<p>If we've done something wrong, that won't happen and we'll know that we need
|
||||
to jump on the mailing list to get help, into IRC or ask a friend.</p>
|
||||
|
@ -433,9 +420,8 @@ wrap Git in a shell script that makes it behave.</p>
|
|||
<p>Capistrano does just this, so to check if the Git access is working, we can
|
||||
simply call:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ cap staging git:check</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> me@localhost <span class="nv">$ </span>cap staging git:check
|
||||
</code></pre></div>
|
||||
|
||||
<p>This task is defined
|
||||
<a href="https://github.com/capistrano/capistrano/blob/master/lib/capistrano/tasks/git.rake">here</a>
|
||||
|
@ -448,26 +434,25 @@ one of the pieces we inherit from Rake)</p>
|
|||
|
||||
<p>If this fails we'll see:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ cap staging git:check
|
||||
cap staging git:check
|
||||
DEBUG Uploading /tmp/git-ssh.sh 0%
|
||||
INFO Uploading /tmp/git-ssh.sh 100%
|
||||
INFO [118bd3e4] Running /usr/bin/env chmod +x /tmp/git-ssh.sh on example.com
|
||||
DEBUG [118bd3e4] Command: /usr/bin/env chmod +x /tmp/git-ssh.sh
|
||||
INFO [118bd3e4] Finished in 0.049 seconds command successful.
|
||||
INFO [a996463f] Running /usr/bin/env git ls-remote git@github.com:capistrano/rails3-bootstrap-devise-cancan.git on harrow
|
||||
DEBUG [a996463f] Command: ( GIT_ASKPASS=/bin/echo GIT_SSH=/tmp/git-ssh.sh /usr/bin/env git ls-remote git@github.com:capistrano/rails3-bootstrap-devise-cancan.git )
|
||||
DEBUG [a996463f] Warning: Permanently added 'github.com,204.232.175.90' (RSA) to the list of known hosts.
|
||||
DEBUG [a996463f] Permission denied (publickey).
|
||||
DEBUG [a996463f] fatal: The remote end hung up unexpectedly
|
||||
cap aborted!
|
||||
git stdout: Nothing written
|
||||
git stderr: Nothing written
|
||||
<div class="highlight"><pre><code class="bash"> me@localhost <span class="nv">$ </span>cap staging git:check
|
||||
cap staging git:check
|
||||
DEBUG Uploading /tmp/git-ssh.sh 0%
|
||||
INFO Uploading /tmp/git-ssh.sh 100%
|
||||
INFO <span class="o">[</span>118bd3e4<span class="o">]</span> Running /usr/bin/env chmod +x /tmp/git-ssh.sh on example.com
|
||||
DEBUG <span class="o">[</span>118bd3e4<span class="o">]</span> Command: /usr/bin/env chmod +x /tmp/git-ssh.sh
|
||||
INFO <span class="o">[</span>118bd3e4<span class="o">]</span> Finished in 0.049 seconds <span class="nb">command </span>successful.
|
||||
INFO <span class="o">[</span>a996463f<span class="o">]</span> Running /usr/bin/env git ls-remote git@github.com:capistrano/rails3-bootstrap-devise-cancan.git on harrow
|
||||
DEBUG <span class="o">[</span>a996463f<span class="o">]</span> Command: <span class="o">(</span> <span class="nv">GIT_ASKPASS</span><span class="o">=</span>/bin/echo <span class="nv">GIT_SSH</span><span class="o">=</span>/tmp/git-ssh.sh /usr/bin/env git ls-remote git@github.com:capistrano/rails3-bootstrap-devise-cancan.git <span class="o">)</span>
|
||||
DEBUG <span class="o">[</span>a996463f<span class="o">]</span> Warning: Permanently added <span class="s1">'github.com,204.232.175.90'</span> <span class="o">(</span>RSA<span class="o">)</span> to the list of known hosts.
|
||||
DEBUG <span class="o">[</span>a996463f<span class="o">]</span> Permission denied <span class="o">(</span>publickey<span class="o">)</span>.
|
||||
DEBUG <span class="o">[</span>a996463f<span class="o">]</span> fatal: The remote end hung up unexpectedly
|
||||
cap aborted!
|
||||
git stdout: Nothing written
|
||||
git stderr: Nothing written
|
||||
|
||||
Tasks: TOP => git:check
|
||||
(See full trace by running task with --trace)</code></pre>
|
||||
</div>
|
||||
Tasks: <span class="nv">TOP</span> <span class="o">=</span>> git:check
|
||||
<span class="o">(</span>See full trace by running task with --trace<span class="o">)</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>This'll typically come out looking more beautiful depending on your terminal
|
||||
colour support, you may well see something like this:</p>
|
||||
|
@ -496,56 +481,52 @@ printed out the error messages for us to try and figure out what broke.</li>
|
|||
working by writing a tiny Cap task, or simply using SSH to do it for us, the
|
||||
choice is yours:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'># lib/capistrano/tasks/agent_forwarding.cap
|
||||
desc "Check if agent forwarding is working"
|
||||
task :forwarding do
|
||||
on roles(:all) do |h|
|
||||
if test("env | grep SSH_AUTH_SOCK")
|
||||
info "Agent forwarding is up to #{h}"
|
||||
else
|
||||
error "Agent forwarding is NOT up to #{h}"
|
||||
end
|
||||
end
|
||||
end</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="c1"># lib/capistrano/tasks/agent_forwarding.cap</span>
|
||||
<span class="n">desc</span> <span class="s2">"Check if agent forwarding is working"</span>
|
||||
<span class="n">task</span> <span class="ss">:forwarding</span> <span class="k">do</span>
|
||||
<span class="n">on</span> <span class="n">roles</span><span class="p">(</span><span class="ss">:all</span><span class="p">)</span> <span class="k">do</span> <span class="o">|</span><span class="n">h</span><span class="o">|</span>
|
||||
<span class="k">if</span> <span class="nb">test</span><span class="p">(</span><span class="s2">"env | grep SSH_AUTH_SOCK"</span><span class="p">)</span>
|
||||
<span class="n">info</span> <span class="s2">"Agent forwarding is up to </span><span class="si">#{</span><span class="n">h</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="k">else</span>
|
||||
<span class="n">error</span> <span class="s2">"Agent forwarding is NOT up to </span><span class="si">#{</span><span class="n">h</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>That gave the output:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>cap staging forwarding
|
||||
DEBUG [f1269276] Running /usr/bin/env env | grep SSH_AUTH_SOCK on example.com
|
||||
DEBUG [f1269276] Command: env | grep SSH_AUTH_SOCK
|
||||
DEBUG [f1269276] SSH_AUTH_SOCK=/tmp/ssh-nQUEmyQ2nS/agent.2546
|
||||
DEBUG [f1269276] Finished in 0.453 seconds command successful.
|
||||
INFO Agent forwarding is up to example.com</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> cap staging forwarding
|
||||
DEBUG <span class="o">[</span>f1269276<span class="o">]</span> Running /usr/bin/env env <span class="p">|</span> grep SSH_AUTH_SOCK on example.com
|
||||
DEBUG <span class="o">[</span>f1269276<span class="o">]</span> Command: env <span class="p">|</span> grep SSH_AUTH_SOCK
|
||||
DEBUG <span class="o">[</span>f1269276<span class="o">]</span> <span class="nv">SSH_AUTH_SOCK</span><span class="o">=</span>/tmp/ssh-nQUEmyQ2nS/agent.2546
|
||||
DEBUG <span class="o">[</span>f1269276<span class="o">]</span> Finished in 0.453 seconds <span class="nb">command </span>successful.
|
||||
INFO Agent forwarding is up to example.com
|
||||
</code></pre></div>
|
||||
|
||||
<p>If you don't feel like writing a Capistrano task, one could simply do:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ ssh -A example.com 'env | grep SSH_AUTH_SOCK'
|
||||
SSH_AUTH_SOCK=/tmp/ssh-Tb6X8V53tm/agent.2934</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> me@localhost <span class="nv">$ </span>ssh -A example.com <span class="s1">'env | grep SSH_AUTH_SOCK'</span>
|
||||
<span class="nv">SSH_AUTH_SOCK</span><span class="o">=</span>/tmp/ssh-Tb6X8V53tm/agent.2934
|
||||
</code></pre></div>
|
||||
|
||||
<p>If we see the <code>SSH_AUTH_SOCK</code> output, that's a pretty good indication that SSH
|
||||
agent forwarding is enabled, and if on your local machine <code>ssh-add -l</code> shows
|
||||
you an SSH key, then we're good to go. <strong>Make sure that you're using the
|
||||
<code>git@...</code> repository URL</strong></p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>cap staging git:check
|
||||
DEBUG Uploading /tmp/git-ssh.sh 0%
|
||||
INFO Uploading /tmp/git-ssh.sh 100%
|
||||
INFO [21382716] Running /usr/bin/env chmod +x /tmp/git-ssh.sh on example.com
|
||||
DEBUG [21382716] Command: /usr/bin/env chmod +x /tmp/git-ssh.sh
|
||||
INFO [21382716] Finished in 0.047 seconds command successful.
|
||||
INFO [f40edfbb] Running /usr/bin/env git ls-remote git@github.com:capistrano/rails3-bootstrap-devise-cancan.git on example.com
|
||||
DEBUG [f40edfbb] Command: ( GIT_ASKPASS=/bin/echo GIT_SSH=/tmp/git-ssh.sh /usr/bin/env git ls-remote git@github.com:capistrano/rails3-bootstrap-devise-cancan.git )
|
||||
DEBUG [f40edfbb] 3419812c9f146d9a84b44bcc2c3caef94da54758 HEAD
|
||||
DEBUG [f40edfbb] 3419812c9f146d9a84b44bcc2c3caef94da54758 refs/heads/master
|
||||
INFO [f40edfbb] Finished in 3.319 seconds command successful.</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> cap staging git:check
|
||||
DEBUG Uploading /tmp/git-ssh.sh 0%
|
||||
INFO Uploading /tmp/git-ssh.sh 100%
|
||||
INFO <span class="o">[</span>21382716<span class="o">]</span> Running /usr/bin/env chmod +x /tmp/git-ssh.sh on example.com
|
||||
DEBUG <span class="o">[</span>21382716<span class="o">]</span> Command: /usr/bin/env chmod +x /tmp/git-ssh.sh
|
||||
INFO <span class="o">[</span>21382716<span class="o">]</span> Finished in 0.047 seconds <span class="nb">command </span>successful.
|
||||
INFO <span class="o">[</span>f40edfbb<span class="o">]</span> Running /usr/bin/env git ls-remote git@github.com:capistrano/rails3-bootstrap-devise-cancan.git on example.com
|
||||
DEBUG <span class="o">[</span>f40edfbb<span class="o">]</span> Command: <span class="o">(</span> <span class="nv">GIT_ASKPASS</span><span class="o">=</span>/bin/echo <span class="nv">GIT_SSH</span><span class="o">=</span>/tmp/git-ssh.sh /usr/bin/env git ls-remote git@github.com:capistrano/rails3-bootstrap-devise-cancan.git <span class="o">)</span>
|
||||
DEBUG <span class="o">[</span>f40edfbb<span class="o">]</span> 3419812c9f146d9a84b44bcc2c3caef94da54758 HEAD
|
||||
DEBUG <span class="o">[</span>f40edfbb<span class="o">]</span> 3419812c9f146d9a84b44bcc2c3caef94da54758 refs/heads/master
|
||||
INFO <span class="o">[</span>f40edfbb<span class="o">]</span> Finished in 3.319 seconds <span class="nb">command </span>successful.
|
||||
</code></pre></div>
|
||||
|
||||
<p><img src="/images/successful-git-check-example-screenshot.png" alt="Capistrano Git Check Colour Example"></p>
|
||||
-->
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
<link rel="stylesheet" href="/css/capistrano.css">
|
||||
<link rel="stylesheet" href="/css/social_foundicons.css" />
|
||||
<link rel="stylesheet" href="/css/okaidia.css">
|
||||
<link rel="stylesheet" href="/css/syntax.css">
|
||||
<script src="/js/vendor/custom.modernizr.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
@ -125,16 +126,15 @@
|
|||
<p>When you run <code>cap production deploy</code>, it invokes the following tasks in
|
||||
sequence:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>deploy:starting - start a deployment, make sure everything is ready
|
||||
deploy:started - started hook (for custom tasks)
|
||||
deploy:updating - update server(s) with a new release
|
||||
deploy:updated - updated hook
|
||||
deploy:publishing - publish the new release
|
||||
deploy:published - published hook
|
||||
deploy:finishing - finish the deployment, clean up everything
|
||||
deploy:finished - finished hook</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"><span class="ss">deploy</span><span class="p">:</span><span class="n">starting</span> <span class="o">-</span> <span class="n">start</span> <span class="n">a</span> <span class="n">deployment</span><span class="p">,</span> <span class="n">make</span> <span class="n">sure</span> <span class="n">everything</span> <span class="n">is</span> <span class="n">ready</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">started</span> <span class="o">-</span> <span class="n">started</span> <span class="n">hook</span> <span class="p">(</span><span class="k">for</span> <span class="n">custom</span> <span class="n">tasks</span><span class="p">)</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">updating</span> <span class="o">-</span> <span class="n">update</span> <span class="n">server</span><span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="n">with</span> <span class="n">a</span> <span class="kp">new</span> <span class="n">release</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">updated</span> <span class="o">-</span> <span class="n">updated</span> <span class="n">hook</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">publishing</span> <span class="o">-</span> <span class="n">publish</span> <span class="n">the</span> <span class="kp">new</span> <span class="n">release</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">published</span> <span class="o">-</span> <span class="n">published</span> <span class="n">hook</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">finishing</span> <span class="o">-</span> <span class="n">finish</span> <span class="n">the</span> <span class="n">deployment</span><span class="p">,</span> <span class="n">clean</span> <span class="n">up</span> <span class="n">everything</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">finished</span> <span class="o">-</span> <span class="n">finished</span> <span class="n">hook</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>Notice there are several hook tasks e.g. <code>:started</code>, <code>:updated</code> for
|
||||
you to hook up custom tasks into the flow using <code>after()</code> and <code>before()</code>.</p>
|
||||
|
@ -144,16 +144,15 @@ you to hook up custom tasks into the flow using <code>after()</code> and <code>b
|
|||
<p>When you run <code>cap production deploy:rollback</code>, it invokes the following
|
||||
tasks in sequence:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>deploy:starting
|
||||
deploy:started
|
||||
deploy:reverting - revert server(s) to previous release
|
||||
deploy:reverted - reverted hook
|
||||
deploy:publishing
|
||||
deploy:published
|
||||
deploy:finishing_rollback - finish the rollback, clean up everything
|
||||
deploy:finished</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"><span class="ss">deploy</span><span class="p">:</span><span class="n">starting</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">started</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">reverting</span> <span class="o">-</span> <span class="n">revert</span> <span class="n">server</span><span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="n">to</span> <span class="n">previous</span> <span class="n">release</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">reverted</span> <span class="o">-</span> <span class="n">reverted</span> <span class="n">hook</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">publishing</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">published</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">finishing_rollback</span> <span class="o">-</span> <span class="n">finish</span> <span class="n">the</span> <span class="n">rollback</span><span class="p">,</span> <span class="n">clean</span> <span class="n">up</span> <span class="n">everything</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">finished</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>As you can see, rollback flow shares many tasks with deploy flow. But note that, rollback flow runs its own <code>:finishing_rollback</code> task because its
|
||||
cleanup process is usually different from deploy flow.</p>
|
||||
|
@ -162,70 +161,67 @@ cleanup process is usually different from deploy flow.</p>
|
|||
|
||||
<p>Assume you require the following files in <code>Capfile</code>,</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'># Capfile
|
||||
require 'capistrano/setup'
|
||||
require 'capistrano/deploy'
|
||||
require 'capistrano/bundler'
|
||||
require 'capistrano/rails/migrations'
|
||||
require 'capistrano/rails/assets'</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"><span class="c1"># Capfile</span>
|
||||
<span class="nb">require</span> <span class="s1">'capistrano/setup'</span>
|
||||
<span class="nb">require</span> <span class="s1">'capistrano/deploy'</span>
|
||||
<span class="nb">require</span> <span class="s1">'capistrano/bundler'</span>
|
||||
<span class="nb">require</span> <span class="s1">'capistrano/rails/migrations'</span>
|
||||
<span class="nb">require</span> <span class="s1">'capistrano/rails/assets'</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>When you run <code>cap production deploy</code>, it runs these tasks:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>deploy
|
||||
deploy:starting
|
||||
[before]
|
||||
deploy:ensure_stage
|
||||
deploy:set_shared_assets
|
||||
deploy:check
|
||||
deploy:started
|
||||
deploy:updating
|
||||
git:create_release
|
||||
deploy:symlink:shared
|
||||
deploy:updated
|
||||
[before]
|
||||
deploy:bundle
|
||||
[after]
|
||||
deploy:migrate
|
||||
deploy:compile_assets
|
||||
deploy:cleanup_assets
|
||||
deploy:normalise_assets
|
||||
deploy:publishing
|
||||
deploy:symlink:release
|
||||
deploy:restart
|
||||
deploy:published
|
||||
deploy:finishing
|
||||
deploy:cleanup
|
||||
deploy:finished
|
||||
deploy:log_revision</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"><span class="n">deploy</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">starting</span>
|
||||
<span class="o">[</span><span class="n">before</span><span class="o">]</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">ensure_stage</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">set_shared_assets</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">check</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">started</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">updating</span>
|
||||
<span class="ss">git</span><span class="p">:</span><span class="n">create_release</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="ss">symlink</span><span class="p">:</span><span class="n">shared</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">updated</span>
|
||||
<span class="o">[</span><span class="n">before</span><span class="o">]</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">bundle</span>
|
||||
<span class="o">[</span><span class="n">after</span><span class="o">]</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">migrate</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">compile_assets</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">cleanup_assets</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">normalise_assets</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">publishing</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="ss">symlink</span><span class="p">:</span><span class="n">release</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">restart</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">published</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">finishing</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">cleanup</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">finished</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">log_revision</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>For <code>cap production deploy:rollback</code>, it runs these tasks:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>deploy
|
||||
deploy:starting
|
||||
[before]
|
||||
deploy:ensure_stage
|
||||
deploy:set_shared_assets
|
||||
deploy:check
|
||||
deploy:started
|
||||
deploy:reverting
|
||||
deploy:revert_release
|
||||
deploy:reverted
|
||||
[after]
|
||||
deploy:rollback_assets
|
||||
deploy:publishing
|
||||
deploy:symlink:release
|
||||
deploy:restart
|
||||
deploy:published
|
||||
deploy:finishing_rollback
|
||||
deploy:cleanup_rollback
|
||||
deploy:finished
|
||||
deploy:log_revision</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"><span class="n">deploy</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">starting</span>
|
||||
<span class="o">[</span><span class="n">before</span><span class="o">]</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">ensure_stage</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">set_shared_assets</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">check</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">started</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">reverting</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">revert_release</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">reverted</span>
|
||||
<span class="o">[</span><span class="n">after</span><span class="o">]</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">rollback_assets</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">publishing</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="ss">symlink</span><span class="p">:</span><span class="n">release</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">restart</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">published</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">finishing_rollback</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">cleanup_rollback</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">finished</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">log_revision</span>
|
||||
</code></pre></div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
@ -243,16 +239,15 @@ require 'capistrano/rails/assets'</code></pre>
|
|||
<p>When you run <code>cap production deploy</code>, it invokes the following tasks in
|
||||
sequence:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>deploy:starting - start a deployment, make sure everything is ready
|
||||
deploy:started - started hook (for custom tasks)
|
||||
deploy:updating - update server(s) with a new release
|
||||
deploy:updated - updated hook
|
||||
deploy:publishing - publish the new release
|
||||
deploy:published - published hook
|
||||
deploy:finishing - finish the deployment, clean up everything
|
||||
deploy:finished - finished hook</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"><span class="ss">deploy</span><span class="p">:</span><span class="n">starting</span> <span class="o">-</span> <span class="n">start</span> <span class="n">a</span> <span class="n">deployment</span><span class="p">,</span> <span class="n">make</span> <span class="n">sure</span> <span class="n">everything</span> <span class="n">is</span> <span class="n">ready</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">started</span> <span class="o">-</span> <span class="n">started</span> <span class="n">hook</span> <span class="p">(</span><span class="k">for</span> <span class="n">custom</span> <span class="n">tasks</span><span class="p">)</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">updating</span> <span class="o">-</span> <span class="n">update</span> <span class="n">server</span><span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="n">with</span> <span class="n">a</span> <span class="kp">new</span> <span class="n">release</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">updated</span> <span class="o">-</span> <span class="n">updated</span> <span class="n">hook</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">publishing</span> <span class="o">-</span> <span class="n">publish</span> <span class="n">the</span> <span class="kp">new</span> <span class="n">release</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">published</span> <span class="o">-</span> <span class="n">published</span> <span class="n">hook</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">finishing</span> <span class="o">-</span> <span class="n">finish</span> <span class="n">the</span> <span class="n">deployment</span><span class="p">,</span> <span class="n">clean</span> <span class="n">up</span> <span class="n">everything</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">finished</span> <span class="o">-</span> <span class="n">finished</span> <span class="n">hook</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>Notice there are several hook tasks e.g. <code>:started</code>, <code>:updated</code> for
|
||||
you to hook up custom tasks into the flow using <code>after()</code> and <code>before()</code>.</p>
|
||||
|
@ -262,16 +257,15 @@ you to hook up custom tasks into the flow using <code>after()</code> and <code>b
|
|||
<p>When you run <code>cap production deploy:rollback</code>, it invokes the following
|
||||
tasks in sequence:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>deploy:starting
|
||||
deploy:started
|
||||
deploy:reverting - revert server(s) to previous release
|
||||
deploy:reverted - reverted hook
|
||||
deploy:publishing
|
||||
deploy:published
|
||||
deploy:finishing_rollback - finish the rollback, clean up everything
|
||||
deploy:finished</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"><span class="ss">deploy</span><span class="p">:</span><span class="n">starting</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">started</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">reverting</span> <span class="o">-</span> <span class="n">revert</span> <span class="n">server</span><span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="n">to</span> <span class="n">previous</span> <span class="n">release</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">reverted</span> <span class="o">-</span> <span class="n">reverted</span> <span class="n">hook</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">publishing</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">published</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">finishing_rollback</span> <span class="o">-</span> <span class="n">finish</span> <span class="n">the</span> <span class="n">rollback</span><span class="p">,</span> <span class="n">clean</span> <span class="n">up</span> <span class="n">everything</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">finished</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>As you can see, rollback flow shares many tasks with deploy flow. But note that, rollback flow runs its own <code>:finishing_rollback</code> task because its
|
||||
cleanup process is usually different from deploy flow.</p>
|
||||
|
@ -280,70 +274,67 @@ cleanup process is usually different from deploy flow.</p>
|
|||
|
||||
<p>Assume you require the following files in <code>Capfile</code>,</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'># Capfile
|
||||
require 'capistrano/setup'
|
||||
require 'capistrano/deploy'
|
||||
require 'capistrano/bundler'
|
||||
require 'capistrano/rails/migrations'
|
||||
require 'capistrano/rails/assets'</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"><span class="c1"># Capfile</span>
|
||||
<span class="nb">require</span> <span class="s1">'capistrano/setup'</span>
|
||||
<span class="nb">require</span> <span class="s1">'capistrano/deploy'</span>
|
||||
<span class="nb">require</span> <span class="s1">'capistrano/bundler'</span>
|
||||
<span class="nb">require</span> <span class="s1">'capistrano/rails/migrations'</span>
|
||||
<span class="nb">require</span> <span class="s1">'capistrano/rails/assets'</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>When you run <code>cap production deploy</code>, it runs these tasks:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>deploy
|
||||
deploy:starting
|
||||
[before]
|
||||
deploy:ensure_stage
|
||||
deploy:set_shared_assets
|
||||
deploy:check
|
||||
deploy:started
|
||||
deploy:updating
|
||||
git:create_release
|
||||
deploy:symlink:shared
|
||||
deploy:updated
|
||||
[before]
|
||||
deploy:bundle
|
||||
[after]
|
||||
deploy:migrate
|
||||
deploy:compile_assets
|
||||
deploy:cleanup_assets
|
||||
deploy:normalise_assets
|
||||
deploy:publishing
|
||||
deploy:symlink:release
|
||||
deploy:restart
|
||||
deploy:published
|
||||
deploy:finishing
|
||||
deploy:cleanup
|
||||
deploy:finished
|
||||
deploy:log_revision</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"><span class="n">deploy</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">starting</span>
|
||||
<span class="o">[</span><span class="n">before</span><span class="o">]</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">ensure_stage</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">set_shared_assets</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">check</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">started</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">updating</span>
|
||||
<span class="ss">git</span><span class="p">:</span><span class="n">create_release</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="ss">symlink</span><span class="p">:</span><span class="n">shared</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">updated</span>
|
||||
<span class="o">[</span><span class="n">before</span><span class="o">]</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">bundle</span>
|
||||
<span class="o">[</span><span class="n">after</span><span class="o">]</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">migrate</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">compile_assets</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">cleanup_assets</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">normalise_assets</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">publishing</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="ss">symlink</span><span class="p">:</span><span class="n">release</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">restart</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">published</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">finishing</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">cleanup</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">finished</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">log_revision</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>For <code>cap production deploy:rollback</code>, it runs these tasks:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>deploy
|
||||
deploy:starting
|
||||
[before]
|
||||
deploy:ensure_stage
|
||||
deploy:set_shared_assets
|
||||
deploy:check
|
||||
deploy:started
|
||||
deploy:reverting
|
||||
deploy:revert_release
|
||||
deploy:reverted
|
||||
[after]
|
||||
deploy:rollback_assets
|
||||
deploy:publishing
|
||||
deploy:symlink:release
|
||||
deploy:restart
|
||||
deploy:published
|
||||
deploy:finishing_rollback
|
||||
deploy:cleanup_rollback
|
||||
deploy:finished
|
||||
deploy:log_revision</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"><span class="n">deploy</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">starting</span>
|
||||
<span class="o">[</span><span class="n">before</span><span class="o">]</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">ensure_stage</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">set_shared_assets</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">check</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">started</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">reverting</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">revert_release</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">reverted</span>
|
||||
<span class="o">[</span><span class="n">after</span><span class="o">]</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">rollback_assets</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">publishing</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="ss">symlink</span><span class="p">:</span><span class="n">release</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">restart</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">published</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">finishing_rollback</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">cleanup_rollback</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">finished</span>
|
||||
<span class="ss">deploy</span><span class="p">:</span><span class="n">log_revision</span>
|
||||
</code></pre></div>
|
||||
-->
|
||||
|
||||
<!--</div> [> /container <] -->
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
<link rel="stylesheet" href="/css/capistrano.css">
|
||||
<link rel="stylesheet" href="/css/social_foundicons.css" />
|
||||
<link rel="stylesheet" href="/css/okaidia.css">
|
||||
<link rel="stylesheet" href="/css/syntax.css">
|
||||
<script src="/js/vendor/custom.modernizr.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
@ -132,47 +133,48 @@ therefore recommended to use an appropriate bundler.
|
|||
|
||||
<p>The following command will install the latest released capistrano <code>v3</code> revision:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>$ gem install capistrano</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> <span class="nv">$ </span>gem install capistrano
|
||||
</code></pre></div>
|
||||
|
||||
<p>Or grab the bleeding edge head from:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>$ git clone https://github.com/capistrano/capistrano.git
|
||||
$ cd capistrano
|
||||
$ gem build *.gemspec
|
||||
$ gem install *.gem</code></pre>
|
||||
</div>
|
||||
Or grab the bleeding edge head from:
|
||||
|
||||
<h3 id="toc_1">Usage in a Rails project</h3>
|
||||
|
||||
<p>Add the following lines to the Gemfile:</p>
|
||||
<div class="highlight"><pre><code class="bash"> <span class="nv">$ </span>git clone https://github.com/capistrano/capistrano.git
|
||||
<span class="nv">$ </span><span class="nb">cd </span>capistrano
|
||||
<span class="nv">$ </span>gem build *.gemspec
|
||||
<span class="nv">$ </span>gem install *.gem
|
||||
</code></pre></div>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>group :development do
|
||||
gem 'capistrano-rails', '~> 1.0.0'
|
||||
end</code></pre>
|
||||
</div>
|
||||
|
||||
<p>The <code>capistrano-rails</code> gem includes extras specifically designed for Ruby on
|
||||
Rails, specifically:</p>
|
||||
### Usage in a Rails project
|
||||
|
||||
<ul>
|
||||
<li>Asset Pipeline Support</li>
|
||||
<li>Database Migration Support</li>
|
||||
</ul>
|
||||
Add the following lines to the Gemfile:
|
||||
|
||||
<p>The documentation for these components can be found in
|
||||
<a href="https://github.com/capistrano/rails/blob/master/README.md">their</a>,
|
||||
<a href="https://github.com/capistrano/bundler/blob/master/README.md">respective</a>,
|
||||
<a href="https://github.com/capistrano/rails/blob/master/README.md">READMEs</a>. However for the most
|
||||
part, to get the best, and most sensible results, simply <code>require</code> in
|
||||
Capfile, after the <code>require 'capistrano/deploy'</code> line:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>require 'capistrano/rails'</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="n">group</span> <span class="ss">:development</span> <span class="k">do</span>
|
||||
<span class="n">gem</span> <span class="s1">'capistrano-rails'</span><span class="p">,</span> <span class="s1">'~> 1.0.0'</span>
|
||||
<span class="k">end</span>
|
||||
</code></pre></div>
|
||||
|
||||
|
||||
The `capistrano-rails` gem includes extras specifically designed for Ruby on
|
||||
Rails, specifically:
|
||||
|
||||
* Asset Pipeline Support
|
||||
* Database Migration Support
|
||||
|
||||
The documentation for these components can be found in
|
||||
[their][capistrano-rails-asset-pipeline-readme],
|
||||
[respective][capistrano-rails-gem-bundler-readme],
|
||||
[READMEs][capistrano-rails-database-migrations-readme]. However for the most
|
||||
part, to get the best, and most sensible results, simply `require` in
|
||||
Capfile, after the `require 'capistrano/deploy'` line:
|
||||
|
||||
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="nb">require</span> <span class="s1">'capistrano/rails'</span>
|
||||
</code></pre></div>
|
||||
|
||||
|
||||
<div class="alert alert-info">
|
||||
<h5>Help! I was using Capistrano `v2.x` and I didn't want to upgrade!</h5>
|
||||
|
@ -181,17 +183,18 @@ If you are using Capistrano `v2.x.x` and have also installed Capistrano `v3`
|
|||
by mistake, then you can lock your Gem version for Capistrano at something
|
||||
like:
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>gem 'capistrano', '~> 2.15' # Or whatever patch release you are using</code></pre>
|
||||
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="n">gem</span> <span class="s1">'capistrano'</span><span class="p">,</span> <span class="s1">'~> 2.15'</span> <span class="c1"># Or whatever patch release you are using</span>
|
||||
</code></pre></div>
|
||||
|
||||
|
||||
This is the [pessimistic operator][rubygems-pessimistic-operator] which
|
||||
installs the closest matching version, at the time of writing this would
|
||||
install `2.15.4`, and any other point-release in the `2.15.x` family without
|
||||
the risk of accidentally upgrading to `v3`.
|
||||
</div>
|
||||
|
||||
<p>This is the <a href="http://docs.rubygems.org/read/chapter/16#page74">pessimistic operator</a> which
|
||||
installs the closest matching version, at the time of writing this would
|
||||
install <code>2.15.4</code>, and any other point-release in the <code>2.15.x</code> family without
|
||||
the risk of accidentally upgrading to <code>v3</code>.
|
||||
</div></p>
|
||||
|
||||
<h2 id="toc_2"></h2>
|
||||
<h2 id="toc_1"></h2>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
@ -216,47 +219,48 @@ therefore recommended to use an appropriate bundler.
|
|||
|
||||
<p>The following command will install the latest released capistrano <code>v3</code> revision:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>$ gem install capistrano</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> <span class="nv">$ </span>gem install capistrano
|
||||
</code></pre></div>
|
||||
|
||||
<p>Or grab the bleeding edge head from:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>$ git clone https://github.com/capistrano/capistrano.git
|
||||
$ cd capistrano
|
||||
$ gem build *.gemspec
|
||||
$ gem install *.gem</code></pre>
|
||||
</div>
|
||||
Or grab the bleeding edge head from:
|
||||
|
||||
<h3 id="toc_1">Usage in a Rails project</h3>
|
||||
|
||||
<p>Add the following lines to the Gemfile:</p>
|
||||
<div class="highlight"><pre><code class="bash"> <span class="nv">$ </span>git clone https://github.com/capistrano/capistrano.git
|
||||
<span class="nv">$ </span><span class="nb">cd </span>capistrano
|
||||
<span class="nv">$ </span>gem build *.gemspec
|
||||
<span class="nv">$ </span>gem install *.gem
|
||||
</code></pre></div>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>group :development do
|
||||
gem 'capistrano-rails', '~> 1.0.0'
|
||||
end</code></pre>
|
||||
</div>
|
||||
|
||||
<p>The <code>capistrano-rails</code> gem includes extras specifically designed for Ruby on
|
||||
Rails, specifically:</p>
|
||||
### Usage in a Rails project
|
||||
|
||||
<ul>
|
||||
<li>Asset Pipeline Support</li>
|
||||
<li>Database Migration Support</li>
|
||||
</ul>
|
||||
Add the following lines to the Gemfile:
|
||||
|
||||
<p>The documentation for these components can be found in
|
||||
<a href="https://github.com/capistrano/rails/blob/master/README.md">their</a>,
|
||||
<a href="https://github.com/capistrano/bundler/blob/master/README.md">respective</a>,
|
||||
<a href="https://github.com/capistrano/rails/blob/master/README.md">READMEs</a>. However for the most
|
||||
part, to get the best, and most sensible results, simply <code>require</code> in
|
||||
Capfile, after the <code>require 'capistrano/deploy'</code> line:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>require 'capistrano/rails'</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="n">group</span> <span class="ss">:development</span> <span class="k">do</span>
|
||||
<span class="n">gem</span> <span class="s1">'capistrano-rails'</span><span class="p">,</span> <span class="s1">'~> 1.0.0'</span>
|
||||
<span class="k">end</span>
|
||||
</code></pre></div>
|
||||
|
||||
|
||||
The `capistrano-rails` gem includes extras specifically designed for Ruby on
|
||||
Rails, specifically:
|
||||
|
||||
* Asset Pipeline Support
|
||||
* Database Migration Support
|
||||
|
||||
The documentation for these components can be found in
|
||||
[their][capistrano-rails-asset-pipeline-readme],
|
||||
[respective][capistrano-rails-gem-bundler-readme],
|
||||
[READMEs][capistrano-rails-database-migrations-readme]. However for the most
|
||||
part, to get the best, and most sensible results, simply `require` in
|
||||
Capfile, after the `require 'capistrano/deploy'` line:
|
||||
|
||||
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="nb">require</span> <span class="s1">'capistrano/rails'</span>
|
||||
</code></pre></div>
|
||||
|
||||
|
||||
<div class="alert alert-info">
|
||||
<h5>Help! I was using Capistrano `v2.x` and I didn't want to upgrade!</h5>
|
||||
|
@ -265,17 +269,18 @@ If you are using Capistrano `v2.x.x` and have also installed Capistrano `v3`
|
|||
by mistake, then you can lock your Gem version for Capistrano at something
|
||||
like:
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>gem 'capistrano', '~> 2.15' # Or whatever patch release you are using</code></pre>
|
||||
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="n">gem</span> <span class="s1">'capistrano'</span><span class="p">,</span> <span class="s1">'~> 2.15'</span> <span class="c1"># Or whatever patch release you are using</span>
|
||||
</code></pre></div>
|
||||
|
||||
|
||||
This is the [pessimistic operator][rubygems-pessimistic-operator] which
|
||||
installs the closest matching version, at the time of writing this would
|
||||
install `2.15.4`, and any other point-release in the `2.15.x` family without
|
||||
the risk of accidentally upgrading to `v3`.
|
||||
</div>
|
||||
|
||||
<p>This is the <a href="http://docs.rubygems.org/read/chapter/16#page74">pessimistic operator</a> which
|
||||
installs the closest matching version, at the time of writing this would
|
||||
install <code>2.15.4</code>, and any other point-release in the <code>2.15.x</code> family without
|
||||
the risk of accidentally upgrading to <code>v3</code>.
|
||||
</div></p>
|
||||
|
||||
<h2 id="toc_2"></h2>
|
||||
<h2 id="toc_1"></h2>
|
||||
-->
|
||||
|
||||
<!--</div> [> /container <] -->
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
<link rel="stylesheet" href="/css/capistrano.css">
|
||||
<link rel="stylesheet" href="/css/social_foundicons.css" />
|
||||
<link rel="stylesheet" href="/css/okaidia.css">
|
||||
<link rel="stylesheet" href="/css/syntax.css">
|
||||
<script src="/js/vendor/custom.modernizr.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
@ -153,34 +154,31 @@ configuration into place at deploy time.</p>
|
|||
<p>The original <code>database.yml</code> should be added to the <code>.gitignore</code> (or your SCM's
|
||||
parallel concept of ignored files)</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>$ cp config/database.yml{,.example}
|
||||
$ echo config/database.yml >> .gitignore</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> <span class="nv">$ </span>cp config/database.yml<span class="o">{</span>,.example<span class="o">}</span>
|
||||
<span class="nv">$ </span><span class="nb">echo </span>config/database.yml >> .gitignore
|
||||
</code></pre></div>
|
||||
|
||||
<p>This should be done for any other secret files, we'll create the production
|
||||
version of the file when we deploy, and symlink it into place.</p>
|
||||
|
||||
<h3 id="toc_2">3. Initialize Capistrano in your application.</h3>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>$ cd my-project
|
||||
$ cap install</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> <span class="nv">$ </span><span class="nb">cd </span>my-project
|
||||
<span class="nv">$ </span>cap install
|
||||
</code></pre></div>
|
||||
|
||||
<p>This will create a bunch of files, the important ones are:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>├── Capfile
|
||||
├── config
|
||||
│ ├── deploy
|
||||
│ │ ├── production.rb
|
||||
│ │ └── staging.rb
|
||||
│ └── deploy.rb
|
||||
└── lib
|
||||
└── capistrano
|
||||
└── tasks</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> ├── Capfile
|
||||
├── config
|
||||
│ ├── deploy
|
||||
│ │ ├── production.rb
|
||||
│ │ └── staging.rb
|
||||
│ └── deploy.rb
|
||||
└── lib
|
||||
└── capistrano
|
||||
└── tasks
|
||||
</code></pre></div>
|
||||
|
||||
<p>Your new Capfile will automatically any tasks from any *.cap files in lib/capistrano/tasks.</p>
|
||||
|
||||
|
@ -205,28 +203,27 @@ common.</p>
|
|||
|
||||
<p>The example file generated will look something like this:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>set :stage, :staging
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="n">set</span> <span class="ss">:stage</span><span class="p">,</span> <span class="ss">:staging</span>
|
||||
|
||||
# Simple Role Syntax
|
||||
# ==================
|
||||
# Supports bulk-adding hosts to roles, the primary
|
||||
# server in each group is considered to be the first
|
||||
# unless any hosts have the primary property set.
|
||||
role :app, %w{example.com}
|
||||
role :web, %w{example.com}
|
||||
role :db, %w{example.com}
|
||||
<span class="c1"># Simple Role Syntax</span>
|
||||
<span class="c1"># ==================</span>
|
||||
<span class="c1"># Supports bulk-adding hosts to roles, the primary</span>
|
||||
<span class="c1"># server in each group is considered to be the first</span>
|
||||
<span class="c1"># unless any hosts have the primary property set.</span>
|
||||
<span class="n">role</span> <span class="ss">:app</span><span class="p">,</span> <span class="sx">%w{example.com}</span>
|
||||
<span class="n">role</span> <span class="ss">:web</span><span class="p">,</span> <span class="sx">%w{example.com}</span>
|
||||
<span class="n">role</span> <span class="ss">:db</span><span class="p">,</span> <span class="sx">%w{example.com}</span>
|
||||
|
||||
# Extended Server Syntax
|
||||
# ======================
|
||||
# This can be used to drop a more detailed server
|
||||
# definition into the server list. The second argument
|
||||
# is something that quacks like a hash and can be used
|
||||
# to set extended properties on the server.
|
||||
server 'example.com', roles: %w{web app}, my_property: :my_value
|
||||
<span class="c1"># Extended Server Syntax</span>
|
||||
<span class="c1"># ======================</span>
|
||||
<span class="c1"># This can be used to drop a more detailed server</span>
|
||||
<span class="c1"># definition into the server list. The second argument</span>
|
||||
<span class="c1"># is something that quacks like a hash and can be used</span>
|
||||
<span class="c1"># to set extended properties on the server.</span>
|
||||
<span class="n">server</span> <span class="s1">'example.com'</span><span class="p">,</span> <span class="ss">roles</span><span class="p">:</span> <span class="sx">%w{web app}</span><span class="p">,</span> <span class="n">my_property</span><span class="p">:</span> <span class="ss">:my_value</span>
|
||||
|
||||
# set :rails_env, :staging</code></pre>
|
||||
</div>
|
||||
<span class="c1"># set :rails_env, :staging</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>Both the simple role, and extended server syntaxes result in one or more
|
||||
servers for each role being defined. The <code>app</code> and <code>db</code> roles are just
|
||||
|
@ -245,12 +242,11 @@ servers, one where we set the username, and another where we set the port.
|
|||
These host strings are parsed and expanded out in to the equivalent of the
|
||||
server line after the comment:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>role :web, %w{hello@world.com example.com:1234}
|
||||
# ...is the same as doing...
|
||||
server 'world.com' roles: [:web], user: 'hello'
|
||||
server 'example.com', roles: [:web], port: 1234</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="n">role</span> <span class="ss">:web</span><span class="p">,</span> <span class="sx">%w{hello@world.com example.com:1234}</span>
|
||||
<span class="c1"># ...is the same as doing...</span>
|
||||
<span class="n">server</span> <span class="s1">'world.com'</span> <span class="ss">roles</span><span class="p">:</span> <span class="o">[</span><span class="ss">:web</span><span class="o">]</span><span class="p">,</span> <span class="ss">user</span><span class="p">:</span> <span class="s1">'hello'</span>
|
||||
<span class="n">server</span> <span class="s1">'example.com'</span><span class="p">,</span> <span class="ss">roles</span><span class="p">:</span> <span class="o">[</span><span class="ss">:web</span><span class="o">]</span><span class="p">,</span> <span class="ss">port</span><span class="p">:</span> <span class="mi">1234</span>
|
||||
</code></pre></div>
|
||||
|
||||
<h3 id="toc_4">5. Set the shared information in <code>deploy.rb</code>.</h3>
|
||||
|
||||
|
@ -262,11 +258,10 @@ deploy</em> are specified here.</p>
|
|||
self-documenting, commented-out configuration options, feel free to play with
|
||||
them a little:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>set :application, 'my app name'
|
||||
set :repo_url, 'git@example.com:me/my_repo.git'
|
||||
ask :branch, proc { `git rev-parse --abbrev-ref HEAD`.chomp }</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="n">set</span> <span class="ss">:application</span><span class="p">,</span> <span class="s1">'my app name'</span>
|
||||
<span class="n">set</span> <span class="ss">:repo_url</span><span class="p">,</span> <span class="s1">'git@example.com:me/my_repo.git'</span>
|
||||
<span class="n">ask</span> <span class="ss">:branch</span><span class="p">,</span> <span class="nb">proc</span> <span class="p">{</span> <span class="sb">`git rev-parse --abbrev-ref HEAD`</span><span class="o">.</span><span class="n">chomp</span> <span class="p">}</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>Here we'd set the name of the application, ideally in a way that's safe for
|
||||
filenames on your target operating system.</p>
|
||||
|
@ -285,11 +280,10 @@ Cancan (for authorisation) along side Twitter Bootstrap for assets has been
|
|||
forked to the Capistrano repository, but you can find the (unchanged) original
|
||||
<a href="https://github.com/RailsApps/rails3-bootstrap-devise-cancan">here</a>.</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>set :application, 'rails3-bootstrap-devise-cancan-demo'
|
||||
set :repo_url, 'https://github.com/capistrano/rails3-bootstrap-devise-cancan'
|
||||
set :branch, 'master'</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="n">set</span> <span class="ss">:application</span><span class="p">,</span> <span class="s1">'rails3-bootstrap-devise-cancan-demo'</span>
|
||||
<span class="n">set</span> <span class="ss">:repo_url</span><span class="p">,</span> <span class="s1">'https://github.com/capistrano/rails3-bootstrap-devise-cancan'</span>
|
||||
<span class="n">set</span> <span class="ss">:branch</span><span class="p">,</span> <span class="s1">'master'</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>I've simplified the <code>:branch</code> variable to simply be a <code>set</code> variable, not a
|
||||
question prompt, as this repository only has a master branch.</p>
|
||||
|
@ -347,34 +341,31 @@ configuration into place at deploy time.</p>
|
|||
<p>The original <code>database.yml</code> should be added to the <code>.gitignore</code> (or your SCM's
|
||||
parallel concept of ignored files)</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>$ cp config/database.yml{,.example}
|
||||
$ echo config/database.yml >> .gitignore</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> <span class="nv">$ </span>cp config/database.yml<span class="o">{</span>,.example<span class="o">}</span>
|
||||
<span class="nv">$ </span><span class="nb">echo </span>config/database.yml >> .gitignore
|
||||
</code></pre></div>
|
||||
|
||||
<p>This should be done for any other secret files, we'll create the production
|
||||
version of the file when we deploy, and symlink it into place.</p>
|
||||
|
||||
<h3 id="toc_2">3. Initialize Capistrano in your application.</h3>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>$ cd my-project
|
||||
$ cap install</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> <span class="nv">$ </span><span class="nb">cd </span>my-project
|
||||
<span class="nv">$ </span>cap install
|
||||
</code></pre></div>
|
||||
|
||||
<p>This will create a bunch of files, the important ones are:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>├── Capfile
|
||||
├── config
|
||||
│ ├── deploy
|
||||
│ │ ├── production.rb
|
||||
│ │ └── staging.rb
|
||||
│ └── deploy.rb
|
||||
└── lib
|
||||
└── capistrano
|
||||
└── tasks</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> ├── Capfile
|
||||
├── config
|
||||
│ ├── deploy
|
||||
│ │ ├── production.rb
|
||||
│ │ └── staging.rb
|
||||
│ └── deploy.rb
|
||||
└── lib
|
||||
└── capistrano
|
||||
└── tasks
|
||||
</code></pre></div>
|
||||
|
||||
<p>Your new Capfile will automatically any tasks from any *.cap files in lib/capistrano/tasks.</p>
|
||||
|
||||
|
@ -399,28 +390,27 @@ common.</p>
|
|||
|
||||
<p>The example file generated will look something like this:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>set :stage, :staging
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="n">set</span> <span class="ss">:stage</span><span class="p">,</span> <span class="ss">:staging</span>
|
||||
|
||||
# Simple Role Syntax
|
||||
# ==================
|
||||
# Supports bulk-adding hosts to roles, the primary
|
||||
# server in each group is considered to be the first
|
||||
# unless any hosts have the primary property set.
|
||||
role :app, %w{example.com}
|
||||
role :web, %w{example.com}
|
||||
role :db, %w{example.com}
|
||||
<span class="c1"># Simple Role Syntax</span>
|
||||
<span class="c1"># ==================</span>
|
||||
<span class="c1"># Supports bulk-adding hosts to roles, the primary</span>
|
||||
<span class="c1"># server in each group is considered to be the first</span>
|
||||
<span class="c1"># unless any hosts have the primary property set.</span>
|
||||
<span class="n">role</span> <span class="ss">:app</span><span class="p">,</span> <span class="sx">%w{example.com}</span>
|
||||
<span class="n">role</span> <span class="ss">:web</span><span class="p">,</span> <span class="sx">%w{example.com}</span>
|
||||
<span class="n">role</span> <span class="ss">:db</span><span class="p">,</span> <span class="sx">%w{example.com}</span>
|
||||
|
||||
# Extended Server Syntax
|
||||
# ======================
|
||||
# This can be used to drop a more detailed server
|
||||
# definition into the server list. The second argument
|
||||
# is something that quacks like a hash and can be used
|
||||
# to set extended properties on the server.
|
||||
server 'example.com', roles: %w{web app}, my_property: :my_value
|
||||
<span class="c1"># Extended Server Syntax</span>
|
||||
<span class="c1"># ======================</span>
|
||||
<span class="c1"># This can be used to drop a more detailed server</span>
|
||||
<span class="c1"># definition into the server list. The second argument</span>
|
||||
<span class="c1"># is something that quacks like a hash and can be used</span>
|
||||
<span class="c1"># to set extended properties on the server.</span>
|
||||
<span class="n">server</span> <span class="s1">'example.com'</span><span class="p">,</span> <span class="ss">roles</span><span class="p">:</span> <span class="sx">%w{web app}</span><span class="p">,</span> <span class="n">my_property</span><span class="p">:</span> <span class="ss">:my_value</span>
|
||||
|
||||
# set :rails_env, :staging</code></pre>
|
||||
</div>
|
||||
<span class="c1"># set :rails_env, :staging</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>Both the simple role, and extended server syntaxes result in one or more
|
||||
servers for each role being defined. The <code>app</code> and <code>db</code> roles are just
|
||||
|
@ -439,12 +429,11 @@ servers, one where we set the username, and another where we set the port.
|
|||
These host strings are parsed and expanded out in to the equivalent of the
|
||||
server line after the comment:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>role :web, %w{hello@world.com example.com:1234}
|
||||
# ...is the same as doing...
|
||||
server 'world.com' roles: [:web], user: 'hello'
|
||||
server 'example.com', roles: [:web], port: 1234</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="n">role</span> <span class="ss">:web</span><span class="p">,</span> <span class="sx">%w{hello@world.com example.com:1234}</span>
|
||||
<span class="c1"># ...is the same as doing...</span>
|
||||
<span class="n">server</span> <span class="s1">'world.com'</span> <span class="ss">roles</span><span class="p">:</span> <span class="o">[</span><span class="ss">:web</span><span class="o">]</span><span class="p">,</span> <span class="ss">user</span><span class="p">:</span> <span class="s1">'hello'</span>
|
||||
<span class="n">server</span> <span class="s1">'example.com'</span><span class="p">,</span> <span class="ss">roles</span><span class="p">:</span> <span class="o">[</span><span class="ss">:web</span><span class="o">]</span><span class="p">,</span> <span class="ss">port</span><span class="p">:</span> <span class="mi">1234</span>
|
||||
</code></pre></div>
|
||||
|
||||
<h3 id="toc_4">5. Set the shared information in <code>deploy.rb</code>.</h3>
|
||||
|
||||
|
@ -456,11 +445,10 @@ deploy</em> are specified here.</p>
|
|||
self-documenting, commented-out configuration options, feel free to play with
|
||||
them a little:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>set :application, 'my app name'
|
||||
set :repo_url, 'git@example.com:me/my_repo.git'
|
||||
ask :branch, proc { `git rev-parse --abbrev-ref HEAD`.chomp }</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="n">set</span> <span class="ss">:application</span><span class="p">,</span> <span class="s1">'my app name'</span>
|
||||
<span class="n">set</span> <span class="ss">:repo_url</span><span class="p">,</span> <span class="s1">'git@example.com:me/my_repo.git'</span>
|
||||
<span class="n">ask</span> <span class="ss">:branch</span><span class="p">,</span> <span class="nb">proc</span> <span class="p">{</span> <span class="sb">`git rev-parse --abbrev-ref HEAD`</span><span class="o">.</span><span class="n">chomp</span> <span class="p">}</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>Here we'd set the name of the application, ideally in a way that's safe for
|
||||
filenames on your target operating system.</p>
|
||||
|
@ -479,11 +467,10 @@ Cancan (for authorisation) along side Twitter Bootstrap for assets has been
|
|||
forked to the Capistrano repository, but you can find the (unchanged) original
|
||||
<a href="https://github.com/RailsApps/rails3-bootstrap-devise-cancan">here</a>.</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>set :application, 'rails3-bootstrap-devise-cancan-demo'
|
||||
set :repo_url, 'https://github.com/capistrano/rails3-bootstrap-devise-cancan'
|
||||
set :branch, 'master'</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="n">set</span> <span class="ss">:application</span><span class="p">,</span> <span class="s1">'rails3-bootstrap-devise-cancan-demo'</span>
|
||||
<span class="n">set</span> <span class="ss">:repo_url</span><span class="p">,</span> <span class="s1">'https://github.com/capistrano/rails3-bootstrap-devise-cancan'</span>
|
||||
<span class="n">set</span> <span class="ss">:branch</span><span class="p">,</span> <span class="s1">'master'</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>I've simplified the <code>:branch</code> variable to simply be a <code>set</code> variable, not a
|
||||
question prompt, as this repository only has a master branch.</p>
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
<link rel="stylesheet" href="/css/capistrano.css">
|
||||
<link rel="stylesheet" href="/css/social_foundicons.css" />
|
||||
<link rel="stylesheet" href="/css/okaidia.css">
|
||||
<link rel="stylesheet" href="/css/syntax.css">
|
||||
<script src="/js/vendor/custom.modernizr.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
<link rel="stylesheet" href="/css/capistrano.css">
|
||||
<link rel="stylesheet" href="/css/social_foundicons.css" />
|
||||
<link rel="stylesheet" href="/css/okaidia.css">
|
||||
<link rel="stylesheet" href="/css/syntax.css">
|
||||
<script src="/js/vendor/custom.modernizr.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
<link rel="stylesheet" href="/css/capistrano.css">
|
||||
<link rel="stylesheet" href="/css/social_foundicons.css" />
|
||||
<link rel="stylesheet" href="/css/okaidia.css">
|
||||
<link rel="stylesheet" href="/css/syntax.css">
|
||||
<script src="/js/vendor/custom.modernizr.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
@ -139,9 +140,9 @@ Ruby software to form part of a larger tool.</p>
|
|||
|
||||
<h4 id="toc_1">What does it look like?</h4>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ cap staging deploy</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> me@localhost <span class="nv">$ </span>cap staging deploy
|
||||
</code></pre></div>
|
||||
|
||||
|
||||
<div>
|
||||
<pre data-line class="language-capistrano"><code data-language="capistrano"><span style="color:white;">DEBUG</span> Uploading /tmp/git-ssh.sh 0%
|
||||
|
@ -217,53 +218,52 @@ Ruby software to form part of a larger tool.</p>
|
|||
<li>A sane, expressive API:</li>
|
||||
</ul>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>desc "Show off the API"
|
||||
task :ditty do
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="n">desc</span> <span class="s2">"Show off the API"</span>
|
||||
<span class="n">task</span> <span class="ss">:ditty</span> <span class="k">do</span>
|
||||
|
||||
on roles(:all) do |host|
|
||||
# Capture output from the remote host, and re-use it
|
||||
# we can reflect on the `host` object passed to the block
|
||||
# and use the `info` logger method to benefit from the
|
||||
# output formatter that is selected.
|
||||
uptime = capture('uptime')
|
||||
if host.roles.include?(:web)
|
||||
info "Your webserver #{host} has uptime: #{uptime}"
|
||||
end
|
||||
end
|
||||
<span class="n">on</span> <span class="n">roles</span><span class="p">(</span><span class="ss">:all</span><span class="p">)</span> <span class="k">do</span> <span class="o">|</span><span class="n">host</span><span class="o">|</span>
|
||||
<span class="c1"># Capture output from the remote host, and re-use it</span>
|
||||
<span class="c1"># we can reflect on the `host` object passed to the block</span>
|
||||
<span class="c1"># and use the `info` logger method to benefit from the</span>
|
||||
<span class="c1"># output formatter that is selected.</span>
|
||||
<span class="n">uptime</span> <span class="o">=</span> <span class="n">capture</span><span class="p">(</span><span class="s1">'uptime'</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="n">host</span><span class="o">.</span><span class="n">roles</span><span class="o">.</span><span class="n">include?</span><span class="p">(</span><span class="ss">:web</span><span class="p">)</span>
|
||||
<span class="n">info</span> <span class="s2">"Your webserver </span><span class="si">#{</span><span class="n">host</span><span class="si">}</span><span class="s2"> has uptime: </span><span class="si">#{</span><span class="n">uptime</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
|
||||
on roles(:app) do
|
||||
# We can set environmental variables for the duration of a block
|
||||
# and move the process into a directoy, executing arbitrary tasks
|
||||
# such as letting Rails do some heavy lifting.
|
||||
with({:rails_env => :production}) do
|
||||
within('/var/www/my/rails/app') do
|
||||
execute :rails, :runner, 'MyModel.something'
|
||||
end
|
||||
end
|
||||
end
|
||||
<span class="n">on</span> <span class="n">roles</span><span class="p">(</span><span class="ss">:app</span><span class="p">)</span> <span class="k">do</span>
|
||||
<span class="c1"># We can set environmental variables for the duration of a block</span>
|
||||
<span class="c1"># and move the process into a directoy, executing arbitrary tasks</span>
|
||||
<span class="c1"># such as letting Rails do some heavy lifting.</span>
|
||||
<span class="n">with</span><span class="p">({</span><span class="ss">:rails_env</span> <span class="o">=></span> <span class="ss">:production</span><span class="p">})</span> <span class="k">do</span>
|
||||
<span class="n">within</span><span class="p">(</span><span class="s1">'/var/www/my/rails/app'</span><span class="p">)</span> <span class="k">do</span>
|
||||
<span class="n">execute</span> <span class="ss">:rails</span><span class="p">,</span> <span class="ss">:runner</span><span class="p">,</span> <span class="s1">'MyModel.something'</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
|
||||
on roles(:db) do
|
||||
# We can even switch users, provided we have support on the remote
|
||||
# server for switching to that user without being prompted for a
|
||||
# passphrase.
|
||||
as 'postgres' do
|
||||
widgets = capture "echo 'SELECT * FROM widgets;' | psql my_database"
|
||||
if widgets.to_i < 50
|
||||
warn "There are fewer than 50 widgets in the database on #{host}!"
|
||||
end
|
||||
end
|
||||
end
|
||||
<span class="n">on</span> <span class="n">roles</span><span class="p">(</span><span class="ss">:db</span><span class="p">)</span> <span class="k">do</span>
|
||||
<span class="c1"># We can even switch users, provided we have support on the remote</span>
|
||||
<span class="c1"># server for switching to that user without being prompted for a</span>
|
||||
<span class="c1"># passphrase.</span>
|
||||
<span class="n">as</span> <span class="s1">'postgres'</span> <span class="k">do</span>
|
||||
<span class="n">widgets</span> <span class="o">=</span> <span class="n">capture</span> <span class="s2">"echo 'SELECT * FROM widgets;' | psql my_database"</span>
|
||||
<span class="k">if</span> <span class="n">widgets</span><span class="o">.</span><span class="n">to_i</span> <span class="o"><</span> <span class="mi">50</span>
|
||||
<span class="nb">warn</span> <span class="s2">"There are fewer than 50 widgets in the database on </span><span class="si">#{</span><span class="n">host</span><span class="si">}</span><span class="s2">!"</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
|
||||
on roles(:all) do
|
||||
# We can even use `test` the way the Unix gods intended
|
||||
if test("[ -d /some/directory ]")
|
||||
info "Phew, it's ok, the directory exists!"
|
||||
end
|
||||
end
|
||||
<span class="n">on</span> <span class="n">roles</span><span class="p">(</span><span class="ss">:all</span><span class="p">)</span> <span class="k">do</span>
|
||||
<span class="c1"># We can even use `test` the way the Unix gods intended</span>
|
||||
<span class="k">if</span> <span class="nb">test</span><span class="p">(</span><span class="s2">"[ -d /some/directory ]"</span><span class="p">)</span>
|
||||
<span class="n">info</span> <span class="s2">"Phew, it's ok, the directory exists!"</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
|
||||
end</code></pre>
|
||||
</div>
|
||||
<span class="k">end</span>
|
||||
</code></pre></div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
@ -295,9 +295,9 @@ Ruby software to form part of a larger tool.</p>
|
|||
|
||||
<h4 id="toc_1">What does it look like?</h4>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ cap staging deploy</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="bash"> me@localhost <span class="nv">$ </span>cap staging deploy
|
||||
</code></pre></div>
|
||||
|
||||
|
||||
<div>
|
||||
<pre data-line class="language-capistrano"><code data-language="capistrano"><span style="color:white;">DEBUG</span> Uploading /tmp/git-ssh.sh 0%
|
||||
|
@ -373,53 +373,52 @@ Ruby software to form part of a larger tool.</p>
|
|||
<li>A sane, expressive API:</li>
|
||||
</ul>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>desc "Show off the API"
|
||||
task :ditty do
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="n">desc</span> <span class="s2">"Show off the API"</span>
|
||||
<span class="n">task</span> <span class="ss">:ditty</span> <span class="k">do</span>
|
||||
|
||||
on roles(:all) do |host|
|
||||
# Capture output from the remote host, and re-use it
|
||||
# we can reflect on the `host` object passed to the block
|
||||
# and use the `info` logger method to benefit from the
|
||||
# output formatter that is selected.
|
||||
uptime = capture('uptime')
|
||||
if host.roles.include?(:web)
|
||||
info "Your webserver #{host} has uptime: #{uptime}"
|
||||
end
|
||||
end
|
||||
<span class="n">on</span> <span class="n">roles</span><span class="p">(</span><span class="ss">:all</span><span class="p">)</span> <span class="k">do</span> <span class="o">|</span><span class="n">host</span><span class="o">|</span>
|
||||
<span class="c1"># Capture output from the remote host, and re-use it</span>
|
||||
<span class="c1"># we can reflect on the `host` object passed to the block</span>
|
||||
<span class="c1"># and use the `info` logger method to benefit from the</span>
|
||||
<span class="c1"># output formatter that is selected.</span>
|
||||
<span class="n">uptime</span> <span class="o">=</span> <span class="n">capture</span><span class="p">(</span><span class="s1">'uptime'</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="n">host</span><span class="o">.</span><span class="n">roles</span><span class="o">.</span><span class="n">include?</span><span class="p">(</span><span class="ss">:web</span><span class="p">)</span>
|
||||
<span class="n">info</span> <span class="s2">"Your webserver </span><span class="si">#{</span><span class="n">host</span><span class="si">}</span><span class="s2"> has uptime: </span><span class="si">#{</span><span class="n">uptime</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
|
||||
on roles(:app) do
|
||||
# We can set environmental variables for the duration of a block
|
||||
# and move the process into a directoy, executing arbitrary tasks
|
||||
# such as letting Rails do some heavy lifting.
|
||||
with({:rails_env => :production}) do
|
||||
within('/var/www/my/rails/app') do
|
||||
execute :rails, :runner, 'MyModel.something'
|
||||
end
|
||||
end
|
||||
end
|
||||
<span class="n">on</span> <span class="n">roles</span><span class="p">(</span><span class="ss">:app</span><span class="p">)</span> <span class="k">do</span>
|
||||
<span class="c1"># We can set environmental variables for the duration of a block</span>
|
||||
<span class="c1"># and move the process into a directoy, executing arbitrary tasks</span>
|
||||
<span class="c1"># such as letting Rails do some heavy lifting.</span>
|
||||
<span class="n">with</span><span class="p">({</span><span class="ss">:rails_env</span> <span class="o">=></span> <span class="ss">:production</span><span class="p">})</span> <span class="k">do</span>
|
||||
<span class="n">within</span><span class="p">(</span><span class="s1">'/var/www/my/rails/app'</span><span class="p">)</span> <span class="k">do</span>
|
||||
<span class="n">execute</span> <span class="ss">:rails</span><span class="p">,</span> <span class="ss">:runner</span><span class="p">,</span> <span class="s1">'MyModel.something'</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
|
||||
on roles(:db) do
|
||||
# We can even switch users, provided we have support on the remote
|
||||
# server for switching to that user without being prompted for a
|
||||
# passphrase.
|
||||
as 'postgres' do
|
||||
widgets = capture "echo 'SELECT * FROM widgets;' | psql my_database"
|
||||
if widgets.to_i < 50
|
||||
warn "There are fewer than 50 widgets in the database on #{host}!"
|
||||
end
|
||||
end
|
||||
end
|
||||
<span class="n">on</span> <span class="n">roles</span><span class="p">(</span><span class="ss">:db</span><span class="p">)</span> <span class="k">do</span>
|
||||
<span class="c1"># We can even switch users, provided we have support on the remote</span>
|
||||
<span class="c1"># server for switching to that user without being prompted for a</span>
|
||||
<span class="c1"># passphrase.</span>
|
||||
<span class="n">as</span> <span class="s1">'postgres'</span> <span class="k">do</span>
|
||||
<span class="n">widgets</span> <span class="o">=</span> <span class="n">capture</span> <span class="s2">"echo 'SELECT * FROM widgets;' | psql my_database"</span>
|
||||
<span class="k">if</span> <span class="n">widgets</span><span class="o">.</span><span class="n">to_i</span> <span class="o"><</span> <span class="mi">50</span>
|
||||
<span class="nb">warn</span> <span class="s2">"There are fewer than 50 widgets in the database on </span><span class="si">#{</span><span class="n">host</span><span class="si">}</span><span class="s2">!"</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
|
||||
on roles(:all) do
|
||||
# We can even use `test` the way the Unix gods intended
|
||||
if test("[ -d /some/directory ]")
|
||||
info "Phew, it's ok, the directory exists!"
|
||||
end
|
||||
end
|
||||
<span class="n">on</span> <span class="n">roles</span><span class="p">(</span><span class="ss">:all</span><span class="p">)</span> <span class="k">do</span>
|
||||
<span class="c1"># We can even use `test` the way the Unix gods intended</span>
|
||||
<span class="k">if</span> <span class="nb">test</span><span class="p">(</span><span class="s2">"[ -d /some/directory ]"</span><span class="p">)</span>
|
||||
<span class="n">info</span> <span class="s2">"Phew, it's ok, the directory exists!"</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
|
||||
end</code></pre>
|
||||
</div>
|
||||
<span class="k">end</span>
|
||||
</code></pre></div>
|
||||
-->
|
||||
|
||||
<!--</div> [> /container <] -->
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
<link rel="stylesheet" href="/css/capistrano.css">
|
||||
<link rel="stylesheet" href="/css/social_foundicons.css" />
|
||||
<link rel="stylesheet" href="/css/okaidia.css">
|
||||
<link rel="stylesheet" href="/css/syntax.css">
|
||||
<script src="/js/vendor/custom.modernizr.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
@ -126,18 +127,18 @@
|
|||
<p>2.
|
||||
We recommend to capify the project from scratch and move definitions from old to new configs then.</p>
|
||||
|
||||
<p><div>
|
||||
<pre data-line=''><code class='language-bash'>mkdir old_cap
|
||||
mv Capfile old_cap
|
||||
mv config/deploy.rb old_cap
|
||||
mv config/deploy/ old_cap # --> only for multistage setups</code></pre>
|
||||
</div></p>
|
||||
<div class="highlight"><pre><code class="bash"> mkdir old_cap
|
||||
mv Capfile old_cap
|
||||
mv config/deploy.rb old_cap
|
||||
mv config/deploy/ old_cap <span class="c"># --> only for multistage setups</span>
|
||||
|
||||
</code></pre></div>
|
||||
|
||||
<p>It's time to capify:</p>
|
||||
|
||||
<p><div>
|
||||
<pre data-line=''><code class='language-bash'>cap install</code></pre>
|
||||
</div></p>
|
||||
<div class="highlight"><pre><code class="bash"> cap install
|
||||
|
||||
</code></pre></div>
|
||||
|
||||
<p>3.
|
||||
Capistrano 3.x is multistage by default, so you will have <code>config/deploy/production.rb</code> and <code>config/deploy/staging.rb</code> right after capifying.
|
||||
|
@ -149,11 +150,11 @@ mv config/deploy/ old_cap # --> only for multistage setups</code></pre>
|
|||
<p>5.
|
||||
If you had a gateway server set doing <code>set :gateway, "www.capify.org"</code> you should upgrade to</p>
|
||||
|
||||
<p><div>
|
||||
<pre data-line=''><code class='language-ruby'>require 'net/ssh/proxy/command'</p>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="nb">require</span> <span class="s1">'net/ssh/proxy/command'</span>
|
||||
|
||||
<p>set :ssh_options, proxy: Net::SSH::Proxy::Command.new('ssh mygateway.com -W %h:%p')</code></pre>
|
||||
</div></p>
|
||||
<span class="n">set</span> <span class="ss">:ssh_options</span><span class="p">,</span> <span class="ss">proxy</span><span class="p">:</span> <span class="no">Net</span><span class="o">::</span><span class="no">SSH</span><span class="o">::</span><span class="no">Proxy</span><span class="o">::</span><span class="no">Command</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="s1">'ssh mygateway.com -W %h:%p'</span><span class="p">)</span>
|
||||
|
||||
</code></pre></div>
|
||||
|
||||
<p>Or the per-server <code>ssh_options</code> equivalent.</p>
|
||||
|
||||
|
@ -167,9 +168,9 @@ mv config/deploy/ old_cap # --> only for multistage setups</code></pre>
|
|||
<p>7.
|
||||
If you didn't use <code>deploy_to</code> before and deployed to <code>/u/apps/your_app_name</code>, you need one more change. Now default deploy path is <code>/var/www/app_name</code> and your config will be broken after upgrade. Just declare custom <code>deploy_to</code> option:</p>
|
||||
|
||||
<p><div>
|
||||
<pre data-line=''><code class='language-ruby'>set :deploy_to, "/u/apps/#{fetch(:application)}"</code></pre>
|
||||
</div></p>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="n">set</span> <span class="ss">:deploy_to</span><span class="p">,</span> <span class="s2">"/u/apps/</span><span class="si">#{</span><span class="n">fetch</span><span class="p">(</span><span class="ss">:application</span><span class="p">)</span><span class="si">}</span><span class="s2">"</span>
|
||||
|
||||
</code></pre></div>
|
||||
|
||||
<p>But in advance, <code>/u/apps</code> is not the best place to store apps and we advice you to change it later.</p>
|
||||
|
||||
|
@ -185,22 +186,20 @@ mv config/deploy/ old_cap # --> only for multistage setups</code></pre>
|
|||
|
||||
<p>Instead of:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>run <<-CMD.compact
|
||||
cd -- #{latest_release} &&
|
||||
RAILS_ENV=#{rails_env.to_s.shellescape} #{asset_env} #{rake} assets:precompile
|
||||
CMD</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="n">run</span> <span class="o"><<-</span><span class="no">CMD</span><span class="o">.</span><span class="n">compact</span>
|
||||
<span class="sh"> cd -- #{latest_release} &&</span>
|
||||
<span class="sh"> RAILS_ENV=#{rails_env.to_s.shellescape} #{asset_env} #{rake} assets:precompile</span>
|
||||
<span class="no"> CMD</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>It's better to use:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>within fetch(:latest_release_directory)
|
||||
with rails_env: fetch(:rails_env) do
|
||||
execute :rake, 'assets:precompile'
|
||||
end
|
||||
end</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="n">within</span> <span class="n">fetch</span><span class="p">(</span><span class="ss">:latest_release_directory</span><span class="p">)</span>
|
||||
<span class="n">with</span> <span class="n">rails_env</span><span class="p">:</span> <span class="n">fetch</span><span class="p">(</span><span class="ss">:rails_env</span><span class="p">)</span> <span class="k">do</span>
|
||||
<span class="n">execute</span> <span class="ss">:rake</span><span class="p">,</span> <span class="s1">'assets:precompile'</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
</code></pre></div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
@ -219,18 +218,18 @@ end</code></pre>
|
|||
<p>2.
|
||||
We recommend to capify the project from scratch and move definitions from old to new configs then.</p>
|
||||
|
||||
<p><div>
|
||||
<pre data-line=''><code class='language-bash'>mkdir old_cap
|
||||
mv Capfile old_cap
|
||||
mv config/deploy.rb old_cap
|
||||
mv config/deploy/ old_cap # --> only for multistage setups</code></pre>
|
||||
</div></p>
|
||||
<div class="highlight"><pre><code class="bash"> mkdir old_cap
|
||||
mv Capfile old_cap
|
||||
mv config/deploy.rb old_cap
|
||||
mv config/deploy/ old_cap <span class="c"># --> only for multistage setups</span>
|
||||
|
||||
</code></pre></div>
|
||||
|
||||
<p>It's time to capify:</p>
|
||||
|
||||
<p><div>
|
||||
<pre data-line=''><code class='language-bash'>cap install</code></pre>
|
||||
</div></p>
|
||||
<div class="highlight"><pre><code class="bash"> cap install
|
||||
|
||||
</code></pre></div>
|
||||
|
||||
<p>3.
|
||||
Capistrano 3.x is multistage by default, so you will have <code>config/deploy/production.rb</code> and <code>config/deploy/staging.rb</code> right after capifying.
|
||||
|
@ -242,11 +241,11 @@ mv config/deploy/ old_cap # --> only for multistage setups</code></pre>
|
|||
<p>5.
|
||||
If you had a gateway server set doing <code>set :gateway, "www.capify.org"</code> you should upgrade to</p>
|
||||
|
||||
<p><div>
|
||||
<pre data-line=''><code class='language-ruby'>require 'net/ssh/proxy/command'</p>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="nb">require</span> <span class="s1">'net/ssh/proxy/command'</span>
|
||||
|
||||
<p>set :ssh_options, proxy: Net::SSH::Proxy::Command.new('ssh mygateway.com -W %h:%p')</code></pre>
|
||||
</div></p>
|
||||
<span class="n">set</span> <span class="ss">:ssh_options</span><span class="p">,</span> <span class="ss">proxy</span><span class="p">:</span> <span class="no">Net</span><span class="o">::</span><span class="no">SSH</span><span class="o">::</span><span class="no">Proxy</span><span class="o">::</span><span class="no">Command</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="s1">'ssh mygateway.com -W %h:%p'</span><span class="p">)</span>
|
||||
|
||||
</code></pre></div>
|
||||
|
||||
<p>Or the per-server <code>ssh_options</code> equivalent.</p>
|
||||
|
||||
|
@ -260,9 +259,9 @@ mv config/deploy/ old_cap # --> only for multistage setups</code></pre>
|
|||
<p>7.
|
||||
If you didn't use <code>deploy_to</code> before and deployed to <code>/u/apps/your_app_name</code>, you need one more change. Now default deploy path is <code>/var/www/app_name</code> and your config will be broken after upgrade. Just declare custom <code>deploy_to</code> option:</p>
|
||||
|
||||
<p><div>
|
||||
<pre data-line=''><code class='language-ruby'>set :deploy_to, "/u/apps/#{fetch(:application)}"</code></pre>
|
||||
</div></p>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="n">set</span> <span class="ss">:deploy_to</span><span class="p">,</span> <span class="s2">"/u/apps/</span><span class="si">#{</span><span class="n">fetch</span><span class="p">(</span><span class="ss">:application</span><span class="p">)</span><span class="si">}</span><span class="s2">"</span>
|
||||
|
||||
</code></pre></div>
|
||||
|
||||
<p>But in advance, <code>/u/apps</code> is not the best place to store apps and we advice you to change it later.</p>
|
||||
|
||||
|
@ -278,22 +277,20 @@ mv config/deploy/ old_cap # --> only for multistage setups</code></pre>
|
|||
|
||||
<p>Instead of:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>run <<-CMD.compact
|
||||
cd -- #{latest_release} &&
|
||||
RAILS_ENV=#{rails_env.to_s.shellescape} #{asset_env} #{rake} assets:precompile
|
||||
CMD</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="n">run</span> <span class="o"><<-</span><span class="no">CMD</span><span class="o">.</span><span class="n">compact</span>
|
||||
<span class="sh"> cd -- #{latest_release} &&</span>
|
||||
<span class="sh"> RAILS_ENV=#{rails_env.to_s.shellescape} #{asset_env} #{rake} assets:precompile</span>
|
||||
<span class="no"> CMD</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>It's better to use:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>within fetch(:latest_release_directory)
|
||||
with rails_env: fetch(:rails_env) do
|
||||
execute :rake, 'assets:precompile'
|
||||
end
|
||||
end</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"> <span class="n">within</span> <span class="n">fetch</span><span class="p">(</span><span class="ss">:latest_release_directory</span><span class="p">)</span>
|
||||
<span class="n">with</span> <span class="n">rails_env</span><span class="p">:</span> <span class="n">fetch</span><span class="p">(</span><span class="ss">:rails_env</span><span class="p">)</span> <span class="k">do</span>
|
||||
<span class="n">execute</span> <span class="ss">:rake</span><span class="p">,</span> <span class="s1">'assets:precompile'</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
</code></pre></div>
|
||||
-->
|
||||
|
||||
<!--</div> [> /container <] -->
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
<link rel="stylesheet" href="/css/capistrano.css">
|
||||
<link rel="stylesheet" href="/css/social_foundicons.css" />
|
||||
<link rel="stylesheet" href="/css/okaidia.css">
|
||||
<link rel="stylesheet" href="/css/syntax.css">
|
||||
<script src="/js/vendor/custom.modernizr.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
@ -120,15 +121,14 @@
|
|||
<h2>A remote server automation and deployment tool written in Ruby.</h2>
|
||||
<h3 id="toc_0">A Simple Task</h3>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>role :demo, %w{example.com example.org example.net}
|
||||
task :uptime do |host|
|
||||
on roles(:demo), in: :parallel do
|
||||
uptime = capture(:uptime)
|
||||
puts "#{host.hostname} reports: #{uptime}"
|
||||
end
|
||||
end</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"><span class="n">role</span> <span class="ss">:demo</span><span class="p">,</span> <span class="sx">%w{example.com example.org example.net}</span>
|
||||
<span class="n">task</span> <span class="ss">:uptime</span> <span class="k">do</span> <span class="o">|</span><span class="n">host</span><span class="o">|</span>
|
||||
<span class="n">on</span> <span class="n">roles</span><span class="p">(</span><span class="ss">:demo</span><span class="p">),</span> <span class="k">in</span><span class="p">:</span> <span class="ss">:parallel</span> <span class="k">do</span>
|
||||
<span class="n">uptime</span> <span class="o">=</span> <span class="n">capture</span><span class="p">(</span><span class="ss">:uptime</span><span class="p">)</span>
|
||||
<span class="nb">puts</span> <span class="s2">"</span><span class="si">#{</span><span class="n">host</span><span class="o">.</span><span class="n">hostname</span><span class="si">}</span><span class="s2"> reports: </span><span class="si">#{</span><span class="n">uptime</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>Capistrano extends the <em>Rake</em> DSL with methods specific to running commands
|
||||
<code>on()</code> servers.</p>
|
||||
|
@ -160,15 +160,14 @@ extended to support them.</p>
|
|||
|
||||
<!-- <h3 id="toc_0">A Simple Task</h3>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>role :demo, %w{example.com example.org example.net}
|
||||
task :uptime do |host|
|
||||
on roles(:demo), in: :parallel do
|
||||
uptime = capture(:uptime)
|
||||
puts "#{host.hostname} reports: #{uptime}"
|
||||
end
|
||||
end</code></pre>
|
||||
</div>
|
||||
<div class="highlight"><pre><code class="ruby"><span class="n">role</span> <span class="ss">:demo</span><span class="p">,</span> <span class="sx">%w{example.com example.org example.net}</span>
|
||||
<span class="n">task</span> <span class="ss">:uptime</span> <span class="k">do</span> <span class="o">|</span><span class="n">host</span><span class="o">|</span>
|
||||
<span class="n">on</span> <span class="n">roles</span><span class="p">(</span><span class="ss">:demo</span><span class="p">),</span> <span class="k">in</span><span class="p">:</span> <span class="ss">:parallel</span> <span class="k">do</span>
|
||||
<span class="n">uptime</span> <span class="o">=</span> <span class="n">capture</span><span class="p">(</span><span class="ss">:uptime</span><span class="p">)</span>
|
||||
<span class="nb">puts</span> <span class="s2">"</span><span class="si">#{</span><span class="n">host</span><span class="o">.</span><span class="n">hostname</span><span class="si">}</span><span class="s2"> reports: </span><span class="si">#{</span><span class="n">uptime</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
</code></pre></div>
|
||||
|
||||
<p>Capistrano extends the <em>Rake</em> DSL with methods specific to running commands
|
||||
<code>on()</code> servers.</p>
|
||||
|
|
|
@ -14,14 +14,14 @@ h1, h2, h3, h4, h5, h6 {
|
|||
font-family: 'Enriqueta', serif;
|
||||
}
|
||||
|
||||
p code, li code {
|
||||
/*p code, li code {
|
||||
padding: 3px;
|
||||
background-color: #E6E6E6;
|
||||
font-family: "droid-sans-mono", Consolas, Monaco, 'Andale Mono', monospace;
|
||||
font-size: 0.9em;
|
||||
color: #222;
|
||||
border-radius: 3px;
|
||||
}
|
||||
}*/
|
||||
|
||||
footer {
|
||||
padding: 1em;
|
||||
|
@ -52,6 +52,6 @@ footer ul.social.icons li {
|
|||
height: 44px !important;
|
||||
}
|
||||
|
||||
pre code {
|
||||
/*pre code {
|
||||
color: #fff;
|
||||
}
|
||||
}*/
|
||||
|
|
60
css/syntax.css
Normal file
60
css/syntax.css
Normal file
|
@ -0,0 +1,60 @@
|
|||
.highlight { background: #ffffff; padding: 10px; }
|
||||
.highlight .c { color: #999988; font-style: italic } /* Comment */
|
||||
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
|
||||
.highlight .k { font-weight: bold } /* Keyword */
|
||||
.highlight .o { font-weight: bold } /* Operator */
|
||||
.highlight .cm { color: #999988; font-style: italic } /* Comment.Multiline */
|
||||
.highlight .cp { color: #999999; font-weight: bold } /* Comment.Preproc */
|
||||
.highlight .c1 { color: #999988; font-style: italic } /* Comment.Single */
|
||||
.highlight .cs { color: #999999; font-weight: bold; font-style: italic } /* Comment.Special */
|
||||
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
|
||||
.highlight .gd .x { color: #000000; background-color: #ffaaaa } /* Generic.Deleted.Specific */
|
||||
.highlight .ge { font-style: italic } /* Generic.Emph */
|
||||
.highlight .gr { color: #aa0000 } /* Generic.Error */
|
||||
.highlight .gh { color: #999999 } /* Generic.Heading */
|
||||
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
|
||||
.highlight .gi .x { color: #000000; background-color: #aaffaa } /* Generic.Inserted.Specific */
|
||||
.highlight .go { color: #888888 } /* Generic.Output */
|
||||
.highlight .gp { color: #555555 } /* Generic.Prompt */
|
||||
.highlight .gs { font-weight: bold } /* Generic.Strong */
|
||||
.highlight .gu { color: #aaaaaa } /* Generic.Subheading */
|
||||
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
|
||||
.highlight .kc { font-weight: bold } /* Keyword.Constant */
|
||||
.highlight .kd { font-weight: bold } /* Keyword.Declaration */
|
||||
.highlight .kp { font-weight: bold } /* Keyword.Pseudo */
|
||||
.highlight .kr { font-weight: bold } /* Keyword.Reserved */
|
||||
.highlight .kt { color: #445588; font-weight: bold } /* Keyword.Type */
|
||||
.highlight .m { color: #009999 } /* Literal.Number */
|
||||
.highlight .s { color: #d14 } /* Literal.String */
|
||||
.highlight .na { color: #008080 } /* Name.Attribute */
|
||||
.highlight .nb { color: #0086B3 } /* Name.Builtin */
|
||||
.highlight .nc { color: #445588; font-weight: bold } /* Name.Class */
|
||||
.highlight .no { color: #008080 } /* Name.Constant */
|
||||
.highlight .ni { color: #800080 } /* Name.Entity */
|
||||
.highlight .ne { color: #990000; font-weight: bold } /* Name.Exception */
|
||||
.highlight .nf { color: #990000; font-weight: bold } /* Name.Function */
|
||||
.highlight .nn { color: #555555 } /* Name.Namespace */
|
||||
.highlight .nt { color: #000080 } /* Name.Tag */
|
||||
.highlight .nv { color: #008080 } /* Name.Variable */
|
||||
.highlight .ow { font-weight: bold } /* Operator.Word */
|
||||
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
|
||||
.highlight .mf { color: #009999 } /* Literal.Number.Float */
|
||||
.highlight .mh { color: #009999 } /* Literal.Number.Hex */
|
||||
.highlight .mi { color: #009999 } /* Literal.Number.Integer */
|
||||
.highlight .mo { color: #009999 } /* Literal.Number.Oct */
|
||||
.highlight .sb { color: #d14 } /* Literal.String.Backtick */
|
||||
.highlight .sc { color: #d14 } /* Literal.String.Char */
|
||||
.highlight .sd { color: #d14 } /* Literal.String.Doc */
|
||||
.highlight .s2 { color: #d14 } /* Literal.String.Double */
|
||||
.highlight .se { color: #d14 } /* Literal.String.Escape */
|
||||
.highlight .sh { color: #d14 } /* Literal.String.Heredoc */
|
||||
.highlight .si { color: #d14 } /* Literal.String.Interpol */
|
||||
.highlight .sx { color: #d14 } /* Literal.String.Other */
|
||||
.highlight .sr { color: #009926 } /* Literal.String.Regex */
|
||||
.highlight .s1 { color: #d14 } /* Literal.String.Single */
|
||||
.highlight .ss { color: #990073 } /* Literal.String.Symbol */
|
||||
.highlight .bp { color: #999999 } /* Name.Builtin.Pseudo */
|
||||
.highlight .vc { color: #008080 } /* Name.Variable.Class */
|
||||
.highlight .vg { color: #008080 } /* Name.Variable.Global */
|
||||
.highlight .vi { color: #008080 } /* Name.Variable.Instance */
|
||||
.highlight .il { color: #009999 } /* Literal.Number.Integer.Long */
|
|
@ -3,7 +3,7 @@ title: Capistrano in ruby script
|
|||
layout: default
|
||||
---
|
||||
Instead of building a config folder and deploy, you may want to programmatically set everything in a single ruby script. This could be done as follows:
|
||||
{% prism ruby %}
|
||||
{% highlight ruby %}
|
||||
require 'capistrano/all'
|
||||
|
||||
stages = "production"
|
||||
|
@ -19,6 +19,6 @@ Instead of building a config folder and deploy, you may want to programmatically
|
|||
|
||||
Capistrano::Application.invoke("production")
|
||||
Capistrano::Application.invoke("deploy")
|
||||
{% endprism%}
|
||||
{% endhighlight%}
|
||||
|
||||
Note that the require order is important as the stage needs to be set before you load setup and deploy.
|
||||
|
|
|
@ -13,14 +13,14 @@ that match a given set of hostnames.
|
|||
|
||||
If the filter matches no servers, no actions will be taken.
|
||||
|
||||
If you specify a filter, it will match servers that have the listed hostnames,
|
||||
If you specify a filter, it will match servers that have the listed hostnames,
|
||||
and it will run *all* the roles for each server. In other words, it only affects
|
||||
the servers the task runs on, not what tasks are run on a server.
|
||||
the servers the task runs on, not what tasks are run on a server.
|
||||
|
||||
You can limit by role and by host; if you do this, the role filtering will
|
||||
apply first. For example, lets say you filtered by the role `app`, then by
|
||||
the hostnames `server1` and `server2`. Capistrano would first filter the
|
||||
available servers to only those with the role `app`, then filter them
|
||||
available servers to only those with the role `app`, then filter them
|
||||
to look for servers with the hostname `server1` or `server2`. If only `server2`
|
||||
had the role `app` (`server1` has some other role), then in this situation your
|
||||
task would only run on `server2`.
|
||||
|
@ -34,9 +34,9 @@ There are three ways to specify the host filter.
|
|||
Capistrano will read the host filter from the environment variable `HOSTS`
|
||||
if it is set. You can set it inline:
|
||||
|
||||
{% prism bash %}
|
||||
{% highlight bash %}
|
||||
HOSTS=server1,server2 cap production deploy
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
Specify multiple hosts by separating them with a comma.
|
||||
|
||||
|
@ -45,9 +45,9 @@ Specify multiple hosts by separating them with a comma.
|
|||
You can set the host filter inside your deploy configuration. For example,
|
||||
you can set the following inside `config/deploy.rb`:
|
||||
|
||||
{% prism ruby %}
|
||||
{% highlight ruby %}
|
||||
set :filter, :hosts => %w{server1 server2}
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
Note that you specify the filter as an array rather than as a comma-separated
|
||||
list of servers when using this method.
|
||||
|
@ -57,9 +57,9 @@ list of servers when using this method.
|
|||
In a similar way to using the environment variable, you can set the role
|
||||
filter by specifying it as a command line argument to `cap`:
|
||||
|
||||
{% prism bash %}
|
||||
{% highlight bash %}
|
||||
cap --hosts=server1,server2 production deploy
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
Like the environment variable method, specify multiple servers by separating
|
||||
them with a comma.
|
||||
Like the environment variable method, specify multiple servers by separating
|
||||
them with a comma.
|
||||
|
|
|
@ -8,7 +8,7 @@ The `remote_file` task is allowing the existence of a remote file to be set as a
|
|||
As as example, this task can be used to ensure that files to be linked exist
|
||||
before running the check:linked_files task:
|
||||
|
||||
{% prism ruby %}
|
||||
{% highlight ruby %}
|
||||
namespace :deploy do
|
||||
namespace :check do
|
||||
task :linked_files => 'config/newrelic.yml'
|
||||
|
@ -21,4 +21,4 @@ before running the check:linked_files task:
|
|||
sh "curl -o #{t.name} https://rpm.newrelic.com/accounts/xx/newrelic.yml"
|
||||
end
|
||||
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
|
|
@ -12,7 +12,7 @@ match a given role or roles.
|
|||
|
||||
If the filter matches no servers, no actions will be taken.
|
||||
|
||||
If you specify a filter, it will match any servers that have that role, but
|
||||
If you specify a filter, it will match any servers that have that role, but
|
||||
it will _only_ run the tasks for that role, not for any other roles that
|
||||
server may have. For example, if you filtered for servers with the `web` role,
|
||||
and a server had both the `web` and `db` role, only the `web` role would
|
||||
|
@ -27,9 +27,9 @@ There are three ways to specify the role filter.
|
|||
Capistrano will read the role filter from the environment variable `ROLES`
|
||||
if it is set. You can set it inline:
|
||||
|
||||
{% prism bash %}
|
||||
{% highlight bash %}
|
||||
ROLES=app,web cap production deploy
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
Specify multiple roles by separating them with a comma.
|
||||
|
||||
|
@ -38,9 +38,9 @@ Specify multiple roles by separating them with a comma.
|
|||
You can set the role filter inside your deploy configuration. For example,
|
||||
you can set the following inside `config/deploy.rb`:
|
||||
|
||||
{% prism ruby %}
|
||||
{% highlight ruby %}
|
||||
set :filter, :roles => %w{app web}
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
Note that you specify the filter as an array rather than as a comma-separated
|
||||
list of roles when using this method.
|
||||
|
@ -50,9 +50,9 @@ list of roles when using this method.
|
|||
In a similar way to using the environment variable, you can set the role
|
||||
filter by specifying it as a command line argument to `cap`:
|
||||
|
||||
{% prism bash %}
|
||||
{% highlight bash %}
|
||||
cap --roles=app,web production deploy
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
Like the environment variable method, specify multiple roles by separating them
|
||||
with a comma.
|
||||
with a comma.
|
||||
|
|
|
@ -7,10 +7,10 @@ Capistrano executes commands on remote servers using [**SSHKit**](https://github
|
|||
|
||||
An example setting a working directory, user and environment variable:
|
||||
|
||||
{% prism ruby %}
|
||||
{% highlight ruby %}
|
||||
on roles(:app), in: :sequence, wait: 5 do
|
||||
within "/opt/sites/example.com" do
|
||||
# commands in this block execute in the
|
||||
# commands in this block execute in the
|
||||
# directory: /opt/sites/example.com
|
||||
as :deploy do
|
||||
# commands in this block execute as the "deploy" user.
|
||||
|
@ -23,7 +23,7 @@ on roles(:app), in: :sequence, wait: 5 do
|
|||
end
|
||||
end
|
||||
end
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
For more examples, see the EXAMPLES.md file in the [**SSHKit**](https://github.com/capistrano/sshkit) project:
|
||||
|
||||
|
|
|
@ -60,23 +60,23 @@ figure this out!
|
|||
First, we'll try a *real* SSH session, logging in via our terminal, and seeing
|
||||
what happens:
|
||||
|
||||
{% prism bash %}
|
||||
{% highlight bash %}
|
||||
me@localhost $ ssh me@remote
|
||||
me@remote $ [[ $- == *i* ]] && echo 'Interactive' || echo 'Not interactive'
|
||||
Interactive
|
||||
me@remote $ shopt -q login_shell && echo 'Login shell' || echo 'Not login shell'
|
||||
Login shell
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
Contrast that with what happens when we hand the command to run to the SSH
|
||||
command line without logging in first...
|
||||
|
||||
{% prism bash %}
|
||||
{% highlight bash %}
|
||||
me@localhost $ ssh me@remote "[[ $- == *i* ]] && echo 'Interactive' || echo 'Not interactive'"
|
||||
Interactive
|
||||
me@localhost $ ssh me@remote "shopt -q login_shell && echo 'Login shell' || echo 'Not login shell'"
|
||||
Not login shell
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
Here we can see that Bash is still starting in **interactive** mode when we're
|
||||
just running a single command, that's because the terminal we are using is
|
||||
|
@ -86,7 +86,7 @@ When we try the same with Capistrano we'll see yet another set of results; we
|
|||
can have a very simple, Capfile, we don't even need to load the default
|
||||
recipes to test this:
|
||||
|
||||
{% prism ruby %}
|
||||
{% highlight ruby %}
|
||||
# Capistrano 3.0.x
|
||||
task :query_interactive do
|
||||
on 'me@remote' do
|
||||
|
@ -98,16 +98,16 @@ recipes to test this:
|
|||
info capture("shopt -q login_shell && echo 'Login shell' || echo 'Not login shell'")
|
||||
end
|
||||
end
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
Gives us the following:
|
||||
|
||||
{% prism bash %}
|
||||
{% highlight bash %}
|
||||
me@localhost $ cap query_login
|
||||
INFO Not login shell
|
||||
me@localhost $ cap query_interactive
|
||||
INFO Not interactive
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
## <a id="which_startup_files_loaded"></a>Which shell startup files do get loaded?
|
||||
|
||||
|
|
|
@ -12,10 +12,10 @@ to make this work reliably for unique logins across team members)
|
|||
To create this deploy user we'll assume something like the following has been
|
||||
done:
|
||||
|
||||
{% prism bash %}
|
||||
{% highlight bash %}
|
||||
root@remote $ adduser deploy
|
||||
root@remote $ passwd -l deploy
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
The first line creates a completely standard user, it has a home directory,
|
||||
which we'll need in a moment, and has a shell, so it may log in. This needs to
|
||||
|
@ -53,9 +53,9 @@ public key to the `deploy` user's `authorized_keys` file, that way if someone
|
|||
quits or gets fired, you can remove their key from that file, and the rest of
|
||||
you can keep on shipping!
|
||||
|
||||
{% prism bash %}
|
||||
{% highlight bash %}
|
||||
me@localhost $ ssh-keygen -t rsa -C 'me@my_email_address.com'
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
You'll be prompted for a passphrase, that's fine. Type one and keep it safe.
|
||||
This passphrase ensures that if your computer is stolen, people still need a
|
||||
|
@ -71,17 +71,17 @@ minutes upwards.)
|
|||
|
||||
We can see which keys are loaded in the SSH agent by running `ssh-add -l`
|
||||
|
||||
{% prism bash %}
|
||||
{% highlight bash %}
|
||||
me@localhost $ ssh-add -l
|
||||
2048 af:ce:7e:c5:93:18:39:ff:54:20:7a:2d:ec:05:7c:a5 /Users/me/.ssh/id_rsa (RSA)
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
If you don't see any keys listed, you can simply run `ssh-add`:
|
||||
|
||||
{% prism bash %}
|
||||
{% highlight bash %}
|
||||
me@localhost $ ssh-add
|
||||
Identity added: /Users/me/.ssh/id_rsa (/Users/me/.ssh/id_rsa)
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
Typically, ssh-add will ask you for the passphrase when you add a key.
|
||||
|
||||
|
@ -97,10 +97,10 @@ At this point with the key loaded into the agent, we need to put the
|
|||
`/home/users/deploy/.ssh/authorized_keys`, to get the contents of that file,
|
||||
we can ask our local key agent for the public parts of the keys it has loaded:
|
||||
|
||||
{% prism bash %}
|
||||
{% highlight bash %}
|
||||
me@localhost $ ssh-add -L
|
||||
ssh-rsa jccXJ/JRfGxnkh/8iL........dbfCH/9cDiKa0Dw8XGAo01mU/w== /Users/me/.ssh/id_rsa
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
This will be a lot longer when you run it, I snipped the output because it
|
||||
looked bad.
|
||||
|
@ -115,7 +115,7 @@ If you are on linux there often exists a command
|
|||
[`ssh-copy-id`](http://linux.die.net/man/1/ssh-copy-id) which streamlines this
|
||||
process, otherwise the workflow is something like:
|
||||
|
||||
{% prism bash %}
|
||||
{% highlight bash %}
|
||||
me@localhost $ ssh root@remote
|
||||
root@remote $ su - deploy
|
||||
deploy@remote $ cd ~
|
||||
|
@ -123,7 +123,7 @@ process, otherwise the workflow is something like:
|
|||
deploy@remote $ echo "ssh-rsa jccXJ/JRfGxnkh/8iL........dbfCH/9cDiKa0Dw8XGAo01mU/w== /Users/me/.ssh/id_rsa" >> .ssh/authorized_keys
|
||||
deploy@remote $ chmod 700 .ssh
|
||||
deploy@remote $ chmod 600 .ssh/authorized_keys
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
**Remember:** This needs to be done on every server you want to use, you can
|
||||
use the same key for each one, but only one key per developer is recommended.
|
||||
|
@ -131,11 +131,11 @@ use the same key for each one, but only one key per developer is recommended.
|
|||
|
||||
If we did all that correctly, we should now be able to do something like this:
|
||||
|
||||
{% prism bash %}
|
||||
{% highlight bash %}
|
||||
me@localhost $ ssh deploy@one-of-my-servers.com 'hostname; uptime'
|
||||
one-of-my-servers.com
|
||||
19:23:32 up 62 days, 44 min, 1 user, load average: 0.00, 0.01, 0.05
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
That should happen without having to enter a passphrase for your SSH key, or
|
||||
prompting you for an SSH password (which the deploy user doesn't have anyway).
|
||||
|
@ -163,7 +163,7 @@ charset="utf-8"></script>
|
|||
If your server isn't accessible directly and you need to use the SSH
|
||||
ProxyCommand option, you should do
|
||||
|
||||
{% prism ruby %}
|
||||
{% highlight ruby %}
|
||||
require 'net/ssh/proxy/command'
|
||||
|
||||
set :ssh_options, proxy: Net::SSH::Proxy::Command.new('ssh mygateway.com -W %h:%p')
|
||||
|
@ -174,7 +174,7 @@ server 'internal-hostname',
|
|||
ssh_options: {
|
||||
proxy: Net::SSH::Proxy::Command.new('ssh mygateway.com -W %h:%p'),
|
||||
}
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
#### 1.2 From our servers to the repository host
|
||||
|
||||
|
@ -191,10 +191,10 @@ Github.
|
|||
|
||||
Here's how we can check if that works, first get the URL of the repository:
|
||||
|
||||
{% prism bash %}
|
||||
{% highlight bash %}
|
||||
me@localhost $ git config remote.origin.url
|
||||
git@github.com:capistrano/rails3-bootstrap-devise-cancan.git
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
Here we're listing our private (for testing purposes) fork of the
|
||||
rails3-bootstrap-devise-cancan repository forked from the Rails Examples and
|
||||
|
@ -202,13 +202,13 @@ Tutorials project.
|
|||
|
||||
We can try to access the repository via our server by doing the following:
|
||||
|
||||
{% prism bash %}
|
||||
{% highlight bash %}
|
||||
# List SSH keys that are loaded into the agent
|
||||
me@localhost $ ssh-add -l
|
||||
# Make sure they key is loaded if 'ssh-add -l' didn't show anything
|
||||
me@localhost $ ssh-add
|
||||
me@localhost $ ssh -A deploy@one-of-my-servers.com 'git ls-remote git@github.com:capistrano/rails3-bootstrap-devise-cancan.git
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
We first check that the agent has the keys loaded. If not we simply load it
|
||||
and enter the passphrase when prompted.
|
||||
|
@ -224,7 +224,7 @@ to the list of known hosts.
|
|||
|
||||
From the SSH documentation:
|
||||
|
||||
{% prism bash %}
|
||||
{% highlight bash %}
|
||||
-A Enables forwarding of the authentication agent connection. This can also be
|
||||
specified on a per-host basis in a configuration file.
|
||||
|
||||
|
@ -234,7 +234,7 @@ From the SSH documentation:
|
|||
attacker cannot obtain key material from the agent, however they can perform
|
||||
operations on the keys that enable them to authenticate using the identities
|
||||
loaded into the agent.
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
In layman's terms, you shouldn't use SSH agent forwarding to machines where you
|
||||
don't trust the administrators, as they can can override the permissions on
|
||||
|
@ -253,11 +253,11 @@ Github, we'll be prompted for a username and password:
|
|||
|
||||
##### 1.2.2.1 With a regular username/password
|
||||
|
||||
{% prism bash %}
|
||||
{% highlight bash %}
|
||||
me@localhost $ git ls-remote https://github.com/capistrano/rails3-bootstrap-devise-cancan.git
|
||||
Username for 'https://github.com': myownusername
|
||||
Password for 'https://capistrano@github.com':
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
This challenge response prompt doesn't work well for automating things, so
|
||||
there are two ways to get around this depending on your server's host
|
||||
|
@ -268,11 +268,11 @@ The other mechanism, and the reason that its **very** important to always use
|
|||
HTTPS not plain ol' HTTP is to embed the username and password in the URL,
|
||||
note this won't work well if your password has special characters:
|
||||
|
||||
{% prism bash %}
|
||||
{% highlight bash %}
|
||||
me@localhost $ git ls-remote https://capistrano:ourverysecretpassword@github.com/capistrano/rails3-bootstrap-devise-cancan.git
|
||||
3419812c9f146d9a84b44bcc2c3caef94da54758HEAD
|
||||
3419812c9f146d9a84b44bcc2c3caef94da54758HEADrefs/heads/master
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
The bigger problem with passwords, whether inlined into the URL, or entered
|
||||
into a `netrc` file, is that the password gives access to **your entire Github
|
||||
|
@ -285,11 +285,11 @@ at Github, they recently rolled out a feature called [Personal API
|
|||
Tokens](https://github.com/blog/1509-personal-api-tokens) which allow you to
|
||||
do something like this:
|
||||
|
||||
{% prism bash %}
|
||||
{% highlight bash %}
|
||||
me@localhost $ git ls-remote https://.....................@github.com/capistrano/rails3-bootstrap-devise-cancan.git
|
||||
3419812c9f146d9a84b44bcc2c3caef94da54758HEAD
|
||||
3419812c9f146d9a84b44bcc2c3caef94da54758HEADrefs/heads/master
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
Where `....` is a personal API token, as such:
|
||||
|
||||
|
@ -320,9 +320,9 @@ have configured *passwordless* `sudo`. Configuring `sudo` to give some users
|
|||
access to come commands under some circumstances is beyond the scope of this
|
||||
documentation, but sufficed to say something like:
|
||||
|
||||
{% prism bash %}
|
||||
{% highlight bash %}
|
||||
deploy ALL=NOPASSWD:/etc/init.d/mysqld, /etc/init.d/apache2
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
This example would give the user named `deploy` access to call `sudo
|
||||
/etc/init.d/mysql _________` and the same for the `apache2` control script.
|
||||
|
@ -337,7 +337,7 @@ notice a change.
|
|||
To configure this hierarchy, ignoring for the moment the passwordless `sudo`
|
||||
access that you may or may not need depending how well your servers are setup:
|
||||
|
||||
{% prism bash %}
|
||||
{% highlight bash %}
|
||||
me@localhost $ ssh root@remote
|
||||
# Capistrano will use /var/www/....... where ... is the value set in
|
||||
# :application, you can override this by setting the ':deploy_to' variable
|
||||
|
@ -347,7 +347,7 @@ access that you may or may not need depending how well your servers are setup:
|
|||
root@remote $ umask 0002
|
||||
root@remote $ chmod g+s ${deploy_to}
|
||||
root@remote $ mkdir ${deploy_to}/{releases,shared}
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
**Note:** The `chmod g+s` is a really handy, and little known Unix feature, it
|
||||
means that at the operating system level, without having to pay much attention
|
||||
|
@ -360,12 +360,12 @@ group: read/write, other: none*. This means that we'll be able to read these
|
|||
files from Apache, or our web server by running the web server in the `deploy`
|
||||
group namespace.
|
||||
|
||||
{% prism bash %}
|
||||
{% highlight bash %}
|
||||
root@remote # stat -c "%A (%a) %n" ${deploy_to}/
|
||||
drwx--S--- (2700) /var/www/rails3-bootstrap-devise-cancan-demo
|
||||
|
||||
root@remote # stat -c "%A (%a) %n" ${deploy_to}/*
|
||||
drwxrwsr-x (2775) /var/www/rails3-bootstrap-devise-cancan-demo/releases
|
||||
drwxrwsr-x (2775) /var/www/rails3-bootstrap-devise-cancan-demo/shared
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ technologies.
|
|||
|
||||
### 1. Checking the directory structure on the remote machine:
|
||||
|
||||
{% prism bash %}
|
||||
{% highlight bash %}
|
||||
me@localhost $ ssh deploy@remote 'ls -lR /var/www/my-application'
|
||||
my-application:
|
||||
total 8
|
||||
|
@ -32,7 +32,7 @@ technologies.
|
|||
|
||||
my-application/shared:
|
||||
total 0
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
This checks in one simple command that the ssh keys you setup are working (you
|
||||
might yet be prompted for the password), and the permissions on the directory
|
||||
|
@ -44,7 +44,7 @@ Now that we know how to check for permissions, and repository access, we'll
|
|||
quickly introduce ourselves to a quick Cap task to check these things on all
|
||||
the machines for us:
|
||||
|
||||
{% prism ruby %}
|
||||
{% highlight ruby %}
|
||||
desc "Check that we can access everything"
|
||||
task :check_write_permissions do
|
||||
on roles(:all) do |host|
|
||||
|
@ -55,7 +55,7 @@ the machines for us:
|
|||
end
|
||||
end
|
||||
end
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
Running this should give you a pretty decent overview, one line of output for
|
||||
each server. It's also your first introduction to the API of Capistrano for
|
||||
|
@ -70,22 +70,22 @@ later, but add those lines to a file in `./lib/capistrano/tasks`, call it
|
|||
something like `access_check.cap`, and run `cap -T` from the top directory and
|
||||
we'll be able to see the task listed:
|
||||
|
||||
{% prism bash %}
|
||||
{% highlight bash %}
|
||||
me@localhost $ bundle exec cap -T
|
||||
# ... lots of other tasks ...
|
||||
cap check_write_permissions # Check that we can access everything
|
||||
# ... lots of other tasks ...
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
Then we simply call it:
|
||||
|
||||
{% prism bash %}
|
||||
{% highlight bash %}
|
||||
me@localhost $ bundle exec cap staging check_write_permissions
|
||||
DEBUG [82c92144] Running /usr/bin/env [ -w /var/www/my-application ] on myserver.com
|
||||
DEBUG [82c92144] Command: [ -w /var/www/my-application ]
|
||||
DEBUG [82c92144] Finished in 0.456 seconds command successful.
|
||||
INFO /var/www/my-application is writable on myserver.com
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
If we've done something wrong, that won't happen and we'll know that we need
|
||||
to jump on the mailing list to get help, into IRC or ask a friend.
|
||||
|
@ -98,9 +98,9 @@ wrap Git in a shell script that makes it behave.
|
|||
Capistrano does just this, so to check if the Git access is working, we can
|
||||
simply call:
|
||||
|
||||
{% prism bash %}
|
||||
{% highlight bash %}
|
||||
me@localhost $ cap staging git:check
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
This task is defined
|
||||
[here](https://github.com/capistrano/capistrano/blob/master/lib/capistrano/tasks/git.rake)
|
||||
|
@ -113,7 +113,7 @@ one of the pieces we inherit from Rake)
|
|||
|
||||
If this fails we'll see:
|
||||
|
||||
{% prism bash %}
|
||||
{% highlight bash %}
|
||||
me@localhost $ cap staging git:check
|
||||
cap staging git:check
|
||||
DEBUG Uploading /tmp/git-ssh.sh 0%
|
||||
|
@ -132,7 +132,7 @@ If this fails we'll see:
|
|||
|
||||
Tasks: TOP => git:check
|
||||
(See full trace by running task with --trace)
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
This'll typically come out looking more beautiful depending on your terminal
|
||||
colour support, you may well see something like this:
|
||||
|
@ -159,7 +159,7 @@ In this case, we'll be using SSH agent forwarding, we can check if that's
|
|||
working by writing a tiny Cap task, or simply using SSH to do it for us, the
|
||||
choice is yours:
|
||||
|
||||
{% prism ruby %}
|
||||
{% highlight ruby %}
|
||||
# lib/capistrano/tasks/agent_forwarding.cap
|
||||
desc "Check if agent forwarding is working"
|
||||
task :forwarding do
|
||||
|
@ -171,32 +171,32 @@ choice is yours:
|
|||
end
|
||||
end
|
||||
end
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
That gave the output:
|
||||
|
||||
{% prism bash %}
|
||||
{% highlight bash %}
|
||||
cap staging forwarding
|
||||
DEBUG [f1269276] Running /usr/bin/env env | grep SSH_AUTH_SOCK on example.com
|
||||
DEBUG [f1269276] Command: env | grep SSH_AUTH_SOCK
|
||||
DEBUG [f1269276] SSH_AUTH_SOCK=/tmp/ssh-nQUEmyQ2nS/agent.2546
|
||||
DEBUG [f1269276] Finished in 0.453 seconds command successful.
|
||||
INFO Agent forwarding is up to example.com
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
If you don't feel like writing a Capistrano task, one could simply do:
|
||||
|
||||
{% prism bash %}
|
||||
{% highlight bash %}
|
||||
me@localhost $ ssh -A example.com 'env | grep SSH_AUTH_SOCK'
|
||||
SSH_AUTH_SOCK=/tmp/ssh-Tb6X8V53tm/agent.2934
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
If we see the `SSH_AUTH_SOCK` output, that's a pretty good indication that SSH
|
||||
agent forwarding is enabled, and if on your local machine `ssh-add -l` shows
|
||||
you an SSH key, then we're good to go. **Make sure that you're using the
|
||||
`git@...` repository URL**
|
||||
|
||||
{% prism bash %}
|
||||
{% highlight bash %}
|
||||
cap staging git:check
|
||||
DEBUG Uploading /tmp/git-ssh.sh 0%
|
||||
INFO Uploading /tmp/git-ssh.sh 100%
|
||||
|
@ -208,6 +208,6 @@ you an SSH key, then we're good to go. **Make sure that you're using the
|
|||
DEBUG [f40edfbb] 3419812c9f146d9a84b44bcc2c3caef94da54758 HEAD
|
||||
DEBUG [f40edfbb] 3419812c9f146d9a84b44bcc2c3caef94da54758 refs/heads/master
|
||||
INFO [f40edfbb] Finished in 3.319 seconds command successful.
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
![Capistrano Git Check Colour Example](/images/successful-git-check-example-screenshot.png)
|
||||
|
|
|
@ -10,7 +10,7 @@ Capistrano v3 provides a default **deploy flow** and a **rollback flow**:
|
|||
When you run `cap production deploy`, it invokes the following tasks in
|
||||
sequence:
|
||||
|
||||
{% prism ruby %}
|
||||
{% highlight ruby %}
|
||||
deploy:starting - start a deployment, make sure everything is ready
|
||||
deploy:started - started hook (for custom tasks)
|
||||
deploy:updating - update server(s) with a new release
|
||||
|
@ -19,7 +19,7 @@ deploy:publishing - publish the new release
|
|||
deploy:published - published hook
|
||||
deploy:finishing - finish the deployment, clean up everything
|
||||
deploy:finished - finished hook
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
Notice there are several hook tasks e.g. `:started`, `:updated` for
|
||||
you to hook up custom tasks into the flow using `after()` and `before()`.
|
||||
|
@ -29,7 +29,7 @@ you to hook up custom tasks into the flow using `after()` and `before()`.
|
|||
When you run `cap production deploy:rollback`, it invokes the following
|
||||
tasks in sequence:
|
||||
|
||||
{% prism ruby %}
|
||||
{% highlight ruby %}
|
||||
deploy:starting
|
||||
deploy:started
|
||||
deploy:reverting - revert server(s) to previous release
|
||||
|
@ -38,7 +38,7 @@ deploy:publishing
|
|||
deploy:published
|
||||
deploy:finishing_rollback - finish the rollback, clean up everything
|
||||
deploy:finished
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
As you can see, rollback flow shares many tasks with deploy flow. But note that, rollback flow runs its own `:finishing_rollback` task because its
|
||||
cleanup process is usually different from deploy flow.
|
||||
|
@ -47,18 +47,18 @@ cleanup process is usually different from deploy flow.
|
|||
|
||||
Assume you require the following files in `Capfile`,
|
||||
|
||||
{% prism ruby %}
|
||||
{% highlight ruby %}
|
||||
# Capfile
|
||||
require 'capistrano/setup'
|
||||
require 'capistrano/deploy'
|
||||
require 'capistrano/bundler'
|
||||
require 'capistrano/rails/migrations'
|
||||
require 'capistrano/rails/assets'
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
When you run `cap production deploy`, it runs these tasks:
|
||||
|
||||
{% prism ruby %}
|
||||
{% highlight ruby %}
|
||||
deploy
|
||||
deploy:starting
|
||||
[before]
|
||||
|
@ -85,11 +85,11 @@ deploy
|
|||
deploy:cleanup
|
||||
deploy:finished
|
||||
deploy:log_revision
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
For `cap production deploy:rollback`, it runs these tasks:
|
||||
|
||||
{% prism ruby %}
|
||||
{% highlight ruby %}
|
||||
deploy
|
||||
deploy:starting
|
||||
[before]
|
||||
|
@ -110,5 +110,5 @@ deploy
|
|||
deploy:cleanup_rollback
|
||||
deploy:finished
|
||||
deploy:log_revision
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
|
|
|
@ -17,28 +17,28 @@ therefore recommended to use an appropriate bundler.
|
|||
|
||||
The following command will install the latest released capistrano `v3` revision:
|
||||
|
||||
{% prism bash %}
|
||||
{% highlight bash %}
|
||||
$ gem install capistrano
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
Or grab the bleeding edge head from:
|
||||
|
||||
{% prism bash %}
|
||||
{% highlight bash %}
|
||||
$ git clone https://github.com/capistrano/capistrano.git
|
||||
$ cd capistrano
|
||||
$ gem build *.gemspec
|
||||
$ gem install *.gem
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
### Usage in a Rails project
|
||||
|
||||
Add the following lines to the Gemfile:
|
||||
|
||||
{% prism ruby %}
|
||||
{% highlight ruby %}
|
||||
group :development do
|
||||
gem 'capistrano-rails', '~> 1.0.0'
|
||||
end
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
The `capistrano-rails` gem includes extras specifically designed for Ruby on
|
||||
Rails, specifically:
|
||||
|
@ -53,9 +53,9 @@ The documentation for these components can be found in
|
|||
part, to get the best, and most sensible results, simply `require` in
|
||||
Capfile, after the `require 'capistrano/deploy'` line:
|
||||
|
||||
{% prism ruby %}
|
||||
{% highlight ruby %}
|
||||
require 'capistrano/rails'
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
<div class="alert alert-info">
|
||||
<h5>Help! I was using Capistrano `v2.x` and I didn't want to upgrade!</h5>
|
||||
|
@ -64,9 +64,9 @@ If you are using Capistrano `v2.x.x` and have also installed Capistrano `v3`
|
|||
by mistake, then you can lock your Gem version for Capistrano at something
|
||||
like:
|
||||
|
||||
{% prism ruby %}
|
||||
{% highlight ruby %}
|
||||
gem 'capistrano', '~> 2.15' # Or whatever patch release you are using
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
This is the [pessimistic operator][rubygems-pessimistic-operator] which
|
||||
installs the closest matching version, at the time of writing this would
|
||||
|
|
|
@ -38,24 +38,24 @@ configuration into place at deploy time.
|
|||
The original `database.yml` should be added to the `.gitignore` (or your SCM's
|
||||
parallel concept of ignored files)
|
||||
|
||||
{% prism bash %}
|
||||
{% highlight bash %}
|
||||
$ cp config/database.yml{,.example}
|
||||
$ echo config/database.yml >> .gitignore
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
This should be done for any other secret files, we'll create the production
|
||||
version of the file when we deploy, and symlink it into place.
|
||||
|
||||
### 3. Initialize Capistrano in your application.
|
||||
|
||||
{% prism bash %}
|
||||
{% highlight bash %}
|
||||
$ cd my-project
|
||||
$ cap install
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
This will create a bunch of files, the important ones are:
|
||||
|
||||
{% prism bash %}
|
||||
{% highlight bash %}
|
||||
├── Capfile
|
||||
├── config
|
||||
│ ├── deploy
|
||||
|
@ -65,7 +65,7 @@ This will create a bunch of files, the important ones are:
|
|||
└── lib
|
||||
└── capistrano
|
||||
└── tasks
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
Your new Capfile will automatically any tasks from any *.cap files in lib/capistrano/tasks.
|
||||
|
||||
|
@ -90,7 +90,7 @@ common.
|
|||
|
||||
The example file generated will look something like this:
|
||||
|
||||
{% prism ruby %}
|
||||
{% highlight ruby %}
|
||||
set :stage, :staging
|
||||
|
||||
# Simple Role Syntax
|
||||
|
@ -111,7 +111,7 @@ The example file generated will look something like this:
|
|||
server 'example.com', roles: %w{web app}, my_property: :my_value
|
||||
|
||||
# set :rails_env, :staging
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
Both the simple role, and extended server syntaxes result in one or more
|
||||
servers for each role being defined. The `app` and `db` roles are just
|
||||
|
@ -130,12 +130,12 @@ servers, one where we set the username, and another where we set the port.
|
|||
These host strings are parsed and expanded out in to the equivalent of the
|
||||
server line after the comment:
|
||||
|
||||
{% prism ruby %}
|
||||
{% highlight ruby %}
|
||||
role :web, %w{hello@world.com example.com:1234}
|
||||
# ...is the same as doing...
|
||||
server 'world.com' roles: [:web], user: 'hello'
|
||||
server 'example.com', roles: [:web], port: 1234
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
### 5. Set the shared information in `deploy.rb`.
|
||||
|
||||
|
@ -147,11 +147,11 @@ The generated sample file starts with the following, and is followed by a few
|
|||
self-documenting, commented-out configuration options, feel free to play with
|
||||
them a little:
|
||||
|
||||
{% prism ruby %}
|
||||
{% highlight ruby %}
|
||||
set :application, 'my app name'
|
||||
set :repo_url, 'git@example.com:me/my_repo.git'
|
||||
ask :branch, proc { `git rev-parse --abbrev-ref HEAD`.chomp }
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
Here we'd set the name of the application, ideally in a way that's safe for
|
||||
filenames on your target operating system.
|
||||
|
@ -170,11 +170,11 @@ Cancan (for authorisation) along side Twitter Bootstrap for assets has been
|
|||
forked to the Capistrano repository, but you can find the (unchanged) original
|
||||
[here](https://github.com/RailsApps/rails3-bootstrap-devise-cancan).
|
||||
|
||||
{% prism ruby %}
|
||||
{% highlight ruby %}
|
||||
set :application, 'rails3-bootstrap-devise-cancan-demo'
|
||||
set :repo_url, 'https://github.com/capistrano/rails3-bootstrap-devise-cancan'
|
||||
set :branch, 'master'
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
I've simplified the `:branch` variable to simply be a `set` variable, not a
|
||||
question prompt, as this repository only has a master branch.
|
||||
|
|
|
@ -22,9 +22,9 @@ Ruby software to form part of a larger tool.
|
|||
|
||||
#### What does it look like?
|
||||
|
||||
{% prism bash %}
|
||||
{% highlight bash %}
|
||||
me@localhost $ cap staging deploy
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
<div>
|
||||
<pre data-line class="language-capistrano"><code data-language="capistrano"><span style="color:white;">DEBUG</span> Uploading /tmp/git-ssh.sh 0%
|
||||
|
@ -98,7 +98,7 @@ There's lots of cool stuff in the Capistrano toy box:
|
|||
* Support for complex environments.
|
||||
* A sane, expressive API:
|
||||
|
||||
{% prism ruby %}
|
||||
{% highlight ruby %}
|
||||
desc "Show off the API"
|
||||
task :ditty do
|
||||
|
||||
|
@ -144,4 +144,4 @@ There's lots of cool stuff in the Capistrano toy box:
|
|||
end
|
||||
|
||||
end
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
|
|
@ -12,18 +12,18 @@ layout: default
|
|||
2.
|
||||
We recommend to capify the project from scratch and move definitions from old to new configs then.
|
||||
|
||||
{% prism bash %}
|
||||
{% highlight bash %}
|
||||
mkdir old_cap
|
||||
mv Capfile old_cap
|
||||
mv config/deploy.rb old_cap
|
||||
mv config/deploy/ old_cap # --> only for multistage setups
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
It's time to capify:
|
||||
|
||||
{% prism bash %}
|
||||
{% highlight bash %}
|
||||
cap install
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
3.
|
||||
Capistrano 3.x is multistage by default, so you will have `config/deploy/production.rb` and `config/deploy/staging.rb` right after capifying.
|
||||
|
@ -35,11 +35,11 @@ layout: default
|
|||
5.
|
||||
If you had a gateway server set doing `set :gateway, "www.capify.org"` you should upgrade to
|
||||
|
||||
{% prism ruby %}
|
||||
{% highlight ruby %}
|
||||
require 'net/ssh/proxy/command'
|
||||
|
||||
set :ssh_options, proxy: Net::SSH::Proxy::Command.new('ssh mygateway.com -W %h:%p')
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
Or the per-server `ssh_options` equivalent.
|
||||
|
||||
|
@ -54,9 +54,9 @@ layout: default
|
|||
7.
|
||||
If you didn't use `deploy_to` before and deployed to `/u/apps/your_app_name`, you need one more change. Now default deploy path is `/var/www/app_name` and your config will be broken after upgrade. Just declare custom `deploy_to` option:
|
||||
|
||||
{% prism ruby %}
|
||||
{% highlight ruby %}
|
||||
set :deploy_to, "/u/apps/#{fetch(:application)}"
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
But in advance, `/u/apps` is not the best place to store apps and we advice you to change it later.
|
||||
|
||||
|
@ -72,19 +72,19 @@ layout: default
|
|||
|
||||
Instead of:
|
||||
|
||||
{% prism ruby %}
|
||||
{% highlight ruby %}
|
||||
run <<-CMD.compact
|
||||
cd -- #{latest_release} &&
|
||||
RAILS_ENV=#{rails_env.to_s.shellescape} #{asset_env} #{rake} assets:precompile
|
||||
CMD
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
It's better to use:
|
||||
|
||||
{% prism ruby %}
|
||||
{% highlight ruby %}
|
||||
within fetch(:latest_release_directory)
|
||||
with rails_env: fetch(:rails_env) do
|
||||
execute :rake, 'assets:precompile'
|
||||
end
|
||||
end
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
|
|
@ -5,7 +5,7 @@ title: A remote server automation and deployment tool written in Ruby.
|
|||
|
||||
### A Simple Task
|
||||
|
||||
{% prism ruby %}
|
||||
{% highlight ruby %}
|
||||
role :demo, %w{example.com example.org example.net}
|
||||
task :uptime do |host|
|
||||
on roles(:demo), in: :parallel do
|
||||
|
@ -13,7 +13,7 @@ task :uptime do |host|
|
|||
puts "#{host.hostname} reports: #{uptime}"
|
||||
end
|
||||
end
|
||||
{% endprism %}
|
||||
{% endhighlight %}
|
||||
|
||||
Capistrano extends the *Rake* DSL with methods specific to running commands
|
||||
`on()` servers.
|
||||
|
|
Loading…
Reference in a new issue