Yes, but that wasn't flexible or elegant enough ;)
This is what I've ended up with, which seems to be working as desired.
I'd be very interested if someone has something better for the line
where I call Kernel#caller.
def at_once(joiner=' && ')
nested = caller.any?{|c|c =~ /config\/deploy\.rb.+at_once'$/}
unless nested
cmds ||= Array.new
self.class.send(:define_method, :get_cmd) {|c|cmds << c}
alias old_run run
alias run get_cmd
end
yield
unless nested
alias run old_run
run cmds.join(joiner)
end
end
namespace :env do
task :init do
at_once do
run "cd #{deploy_to}"
run "eval `#{deploy_to}/bin/env.sh`"
end
end
task :sandbox do
set :current_envronment, :sandbox
set :rails_env, :sandbox
set :deploy_to, "/var/www/#{application}-sandbox"
end
task :echo do
at_once do
init
run 'echo $RAILS_ENV'
run 'which ruby'
run 'which gem'
end
end
$ cap env:sandbox env:echo
* executing `env:sandbox'
* executing `env:echo'
* executing `env:init'
* executing "cd /var/www/myapp-sandbox && eval
`/var/www/myapp-sandbox/bin/env.sh` && echo $RAILS_ENV && which ruby
&& which gem"
servers: ["example.com"]
[example.com] executing command
** [out :: example.com]
** [out :: example.com] /var/www/myapp-sandbox/usr/bin/ruby
** [out :: example.com] /var/www/myapp-sandbox/usr/bin/gem
command finished
-Ian
On 1/9/08, Jamis Buck <[EMAIL PROTECTED]> wrote:
> The easiest thing to do is probably going to be something like this:
>
> run "x && y"
>
> If x is something you always want to run for all of your commands,
> then you can do something like this:
>
> def run_with_x(y)
> run "x && #{y}"
> end
>
> run_with_x("y")
>
> - Jamis
>
> On Jan 9, 2008, at 4:44 PM, Ian Smith-Heisters wrote:
>
> >
> > Ok, that's what I was beginning to suspect.
> >
> > So I thought I'd be clever and write a little helper method that would
> > help me string together a bunch of commands with, say, ' && ':
> >
> >>> def run(cmd); puts "I have yer #{cmd}"; end
> > => nil
> >>> def at_once(joiner=' && ')
> >>> cmds = Array.new
> >>> Object.define_method(:get_cmd) {|c|cmds << c}
> >>> alias :old_run :run
> >>> alias :run :get_cmd
> >>> yield
> >>> alias :run :old_run
> >>> run cmds.join(joiner)
> >>> end
> > => nil
> >>> at_once{run('x');run('y')}
> > I have yer x && y
> > => nil
> >>> run 'x'
> > I have yer x
> > => nil
> >>> run 'y'
> > I have yer y
> > => nil
> >>>
> >
> > Which works fine on the console. Unfortunately, when I stick the
> > at_once definition at the top of my deploy.rb script, it runs into all
> > kinds of problems like "`method_missing': undefined method `at_once'
> > for #<Capistrano::Configuration::Namespaces::Namespace:0xb7859b18>"
> > when I try to use it.
> >
> > Any ideas on how to get that to work?
> >
> > Thanks,
> > Ian
> >
> > On 1/9/08, Jamis Buck <[EMAIL PROTECTED]> wrote:
> >> Each invocation of run() or sudo() is done in a brand new SSH
> >> channel.
> >> Running commands via capistrano is not at all like executing commands
> >> in a shell like bash--environment settings do not stick from one
> >> command to the next. If you have setup that you want done on each
> >> run(), you will need to do as you said and create a wrapper method
> >> that prepends the setup you want done to each command.
> >>
> >> - Jamis
> >>
> >> On Jan 8, 2008, at 5:29 PM, I. E. Smith-Heisters wrote:
> >>
> >>>
> >>> Hi all,
> >>>
> >>> I have a bunch of staging servers, all of which have their own,
> >>> custom
> >>> compiled ruby and gem versions. In order to work with a given server
> >>> instance, a user is supposed to eval a script that sets up their
> >>> bash
> >>> environment. Like this:
> >>>
> >>> $ cd /var/www/staging-x
> >>> $ eval `bin/env.sh`
> >>> $ which ruby
> >>> /var/www/staging-x/usr/bin/ruby
> >>> $ which gem
> >>> /var/www/staging-x/usr/bin/gem
> >>>
> >>> When I use Cap to run "eval `bin/env.sh`", the variables it exports
> >>> are not persisted:
> >>>
> >>> namespace :env do
> >>> task :init do
> >>> run "cd #{deploy_to}"
> >>> run "eval `#{deploy_to}/bin/env.sh`"
> >>> end
> >>>
> >>> task :sandbox do
> >>> set :rails_env, :sandbox
> >>> set :deploy_to, "/var/www/#{application}-sandbox"
> >>> init
> >>> end
> >>>
> >>> task :echo do
> >>> run 'echo $RAILS_ENV'
> >>> run 'which ruby'
> >>> run 'which gem'
> >>> end
> >>> end
> >>>
> >>> $ cap env:sandbox env:echo
> >>> <snip>
> >>> * executing `env:echo'
> >>> * executing "echo $RAILS_ENV"
> >>> servers: ["example.com"]
> >>> [example.com] executing command
> >>> ** [out :: example.com]
> >>> command finished
> >>> * executing "which ruby"
> >>> servers: ["example.com"]
> >>> [example.com] executing command
> >>> ** [out :: example.com] /usr/bin/ruby
> >>> command finished
> >>> * executing "which gem"
> >>> servers: ["example.com"]
> >>> [example.com] executing command
> >>> *** [err :: example.com] which: no gem in (/usr/kerberos/bin:/usr/
> >>> local/bin:/bin:/usr/bin)
> >>> command finished
> >>> command "which gem" failed on example.com
> >>>
> >>> As you can see, the PATH variable still points to the system version
> >>> of ruby, and since the system doesn't have gem installed, "which
> >>> gem"
> >>> kills the script outright.
> >>>
> >>> I've been looking around and I see lots of problems surrounding
> >>> people's bashrc files being read and other ssh configuration issues,
> >>> but this really seems to be something to do with how Capistrano is
> >>> executing each command and the persistence of the environment
> >>> between
> >>> them. A colleague suggested I do something like
> >>>
> >>> run "eval `bin/env.sh` && foobar"
> >>>
> >>> which I guess is a possibility, but hardly an elegant solution,
> >>> since
> >>> I'd have to prefix each command with the eval statement (probably
> >>> best
> >>> accomplished by extending "run").
> >>>
> >>> Thanks in advance for any help you might be able to offer.
> >>>
> >>> -Ian
> >>>>>
> >>
> >>
> >>
> >
> > > >
>
>
>
--~--~---------~--~----~------------~-------~--~----~
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at http://groups.google.com/group/capistrano
-~----------~----~----~----~------~----~------~--~---