exit status and task success

1,517 views
Skip to first unread message

Gerhardus Geldenhuis

unread,
Jan 21, 2009, 12:24:55 PM1/21/09
to Capistrano
Hi
Is there a way to run different tasks based on the exit status of a
run command? Also how can I "force" a task to fail or succeed, how is
the failure/success of a task determined/defined.

Regards

Rafael G.

unread,
Jan 21, 2009, 12:42:13 PM1/21/09
to capis...@googlegroups.com
You can write a task with :on_error set to :continue and then catch the
exception, I never done it, the idea is:
task :foo, :on_error => :continue do
begin
run "important task"
rescue Exception => error
puts "Important task fail!!: #{error}"
foo.task_if_foo_fail
end
end

rgo.vcf

Jamis Buck

unread,
Jan 21, 2009, 1:07:26 PM1/21/09
to capis...@googlegroups.com
What Rafael said, except if you're rescuing the exception you should be
able to leave off the :on_error => :continue bit.

Also, to force a task to succeed or fail...I assume you mean run()? Or
do you really mean task()?

To force a run command to succeed, just append "; true" to the end of
the command:

run "something that might fail; true"

Likewise, to make it fail, just append "; false" to the end:

run "something that must fail; false"

(That's not Capistrano magic, that's *nix. Most (all?) unices come with
'true' and 'false' commands. The 'true' command does nothing except exit
with a status code of 0. The 'false' command does nothing except exit
with a status code of 1.)

- Jamis

Donovan Bray

unread,
Jan 21, 2009, 9:41:26 PM1/21/09
to capis...@googlegroups.com
run "echo whatever; true"

Will always succeed no matter what exit status the first command yields.

run "echo whatever; false"

Will fail.

On Jan 21, 2009, at 9:24 AM, Gerhardus Geldenhuis <Gerhardus....@gmail.com

Gerhardus Geldenhuis

unread,
Jan 22, 2009, 5:22:44 AM1/22/09
to Capistrano
Hi
Thanks for all the answers.

What I was unclear about is the relationship between the unix command
line exit status and the success status of the task. It now seems
clear that if the the command succeeds the task succeeds and vice
versa.

This leads me on to another question. Should you generally encapsulate
only one external command in a capistrano task, or can I have an if
statement in my task that acts on the success/failure(true/false) of
the command line. I will illustrate by a simple example.

if run "dosomething" then do task1
else first do task 2

and to clarify what I meant in my previous email I would also like to
do the following:
task
result = (run "command")
if result = 'a piece of string' then fail task immediatly to trigger
rollback
end

Regards

Jamis Buck

unread,
Jan 22, 2009, 11:08:47 AM1/22/09
to capis...@googlegroups.com
The run() command does not return success/failure. If it succeeds, it
returns. If it fails, it raises an exception.

To get the result of a command, you can use the capture() method:

http://wiki.capify.org/article/Capture

Note, though, that it runs the command only on a single host, so if you
want the output of multiple hosts, you'll need to use run() and give it
a block, so you can process the output yourself:

http://wiki.capify.org/article/Run

To answer your question about one-command-per-task, you can definitely
put as many commands in as you want. As for conditionally running
commands, you can do that in a few ways.

First, if you have really complex conditional logic, it might be best to
put the entire task in a shell and run the script from capistrano, a la:

task :do_something_hard do
run "my_script"
end

And my_script could either be shell script, or ruby, whichever floats
your boat.

Alternatively, for simpler needs, you can use shell if conditions
directly in capistrano:

run "if [ some_command ]; then other_command; else last_command; fi"

However, it's really not feasible to test the run() command itself (via
exception rescuing, etc.) because just because the command fails on one
server, doesn't mean it failed on all servers. Consider:

begin
run "something that might fail"
rescue Exception
run "something assuming the first failed"
end

If you run this task against more than one server, then it could be that
one server fails while the others succeed. In that event, an exception
would still be raised, resulting in the second run() being executed
against ALL SERVERS, not just the one(s) that failed.

Hope that makes sense,

Jamis

Gerhardus Geldenhuis

unread,
Jan 22, 2009, 11:21:31 AM1/22/09
to Capistrano
On Jan 22, 4:08 pm, Jamis Buck <ja...@37signals.com> wrote:
> The run() command does not return success/failure. If it succeeds, it
> returns. If it fails, it raises an exception.
>
> To get the result of a command, you can use the capture() method:
>
>  http://wiki.capify.org/article/Capture
>
> Note, though, that it runs the command only on a single host, so if you
> want the output of multiple hosts, you'll need to use run() and give it
> a block, so you can process the output yourself:
>
>  http://wiki.capify.org/article/Run
>
> To answer your question about one-command-per-task, you can definitely
> put as many commands in as you want. As for conditionally running
> commands, you can do that in a few ways.
>
> First, if you have really complex conditional logic, it might be best to
> put the entire task in a shell and run the script from capistrano, a la:
>
>   task :do_something_hard do
>     run "my_script"
>   end

I am in two minds about this. I want as little as possible "scripts"
on my servers. I believe that all/most logic should sit on
"management" server. This also makes building new boxes more simple.
On the other hand one can just just capistrano to distribute the
scripts or whichever other tool.

>
> And my_script could either be shell script, or ruby, whichever floats
> your boat.
>
> Alternatively, for simpler needs, you can use shell if conditions
> directly in capistrano:
>
>   run "if [ some_command ]; then other_command; else last_command; fi"
>
> However, it's really not feasible to test the run() command itself (via
> exception rescuing, etc.) because just because the command fails on one
> server, doesn't mean it failed on all servers. Consider:
>
>   begin
>     run "something that might fail"
>   rescue Exception
>     run "something assuming the first failed"
>   end
>
> If you run this task against more than one server, then it could be that
> one server fails while the others succeed. In that event, an exception
> would still be raised, resulting in the second run() being executed
> against ALL SERVERS, not just the one(s) that failed.
>
> Hope that makes sense,

It does now. :-)
One needs to remember that a task executed against a group of servers
will be considered a "single entity" eg I create a directory on my
test servers. if one fails then the task evaluate false in a true
statement, but if you have exception handling then the individual
server would still be taking care off.

Regards

Lee Hambley

unread,
Jan 22, 2009, 12:39:29 PM1/22/09
to capis...@googlegroups.com
I almost daren't link it as it caused a little controversy last week --
but here's a wiki page I wrote to deal with how the Bash & Capistrano tasks fit together:
- Lee

2009/1/22 Gerhardus Geldenhuis <Gerhardus....@gmail.com>
Reply all
Reply to author
Forward
0 new messages