Error Exception if script doesn't run

I need to know if my script fails to run for any reason and capture the
exception. I know how to use "rescue" for small pieces of code but how
can I capture the stderr for anything in the script?

thanks

jack

···

--
Posted via http://www.ruby-forum.com/.

jackster the jackle wrote:

I need to know if my script fails to run for any reason and capture the
exception. I know how to use "rescue" for small pieces of code but how
can I capture the stderr for anything in the script?

If you want to capture only an *exception* then wrap it like this:

begin

  .. rest of script

rescue Exception => e
  .. do something with e, e.g. write it to a log file
end

However if you want to capture everything written to stderr then that's
a different problem. That's the responsibility of whoever started the
Ruby process, since it would have passed it an open file descriptor for
stderr (fd 2). For example, if you are starting ruby from a shell, then

    $ ruby foo.rb 2>errors.log

But if you were launching it from another Ruby process, then look at
open3.rb in the standard library.

···

--
Posted via http://www.ruby-forum.com/\.

that does exactly what I had hoped....thanks alot!

jack

···

--
Posted via http://www.ruby-forum.com/.

I notice that any shell commands that I have in the script that fail do
not trigger a Ruby exception, how do I get my Ruby script to send these?

thanks

jack

Brian Candler wrote:

···

jackster the jackle wrote:

I need to know if my script fails to run for any reason and capture the
exception. I know how to use "rescue" for small pieces of code but how
can I capture the stderr for anything in the script?

If you want to capture only an *exception* then wrap it like this:

begin

  .. rest of script

rescue Exception => e
  .. do something with e, e.g. write it to a log file
end

However if you want to capture everything written to stderr then that's
a different problem. That's the responsibility of whoever started the
Ruby process, since it would have passed it an open file descriptor for
stderr (fd 2). For example, if you are starting ruby from a shell, then

    $ ruby foo.rb 2>errors.log

But if you were launching it from another Ruby process, then look at
open3.rb in the standard library.

--
Posted via http://www.ruby-forum.com/\.

jackster the jackle wrote:

I notice that any shell commands that I have in the script that fail do not trigger a Ruby exception, how do I get my Ruby script to send these?

Check the return value of #system, like this:

irb(main):002:0> unless system "false"; puts "failed!"; end
failed!
=> nil

···

--
       vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

It seems to work but not for this command, perhaps since scp gets
executed (but does not complete) the system variable is not false?

[code]
`scp -i /home/jsmith/.ssh/id_rsa /files*.tar jsmith@172.20.1.1:`
[/code]

The error code I get when I run the script manually is as follows
because 172.20.1.1 is no longer on the network:

   ssh: connect to host 172.20.1.1 port 22: No route to host
   lost connection

I was hoping the system variable would trip when this command fails?

jack

Joel VanderWerf wrote:

···

jackster the jackle wrote:

I notice that any shell commands that I have in the script that fail do
not trigger a Ruby exception, how do I get my Ruby script to send these?

Check the return value of #system, like this:

irb(main):002:0> unless system "false"; puts "failed!"; end
failed!
=> nil

--
Posted via http://www.ruby-forum.com/\.

jackster the jackle wrote:

It seems to work but not for this command, perhaps since scp gets executed (but does not complete) the system variable is not false?

[code]
`scp -i /home/jsmith/.ssh/id_rsa /files*.tar jsmith@172.20.1.1:`
[/code]

The error code I get when I run the script manually is as follows because 172.20.1.1 is no longer on the network:

   ssh: connect to host 172.20.1.1 port 22: No route to host
   lost connection

I was hoping the system variable would trip when this command fails?

jack

In the general case, when a command succeeds it returns 0 and when it fails it returns something else. However, this is a convention, not a rule. It is entirely possible for a command to fail and still return 0. If so, you can't determine if it fails by simply checking the return code. I have no idea whether or not scp returns non-0 on failure. You can check by running it yourself in a shell. Immediately after it fails enter 'echo $?'. This will show you the exit status. For example:

~$ ls test.rb
test.rb
~$ echo $?
0
~$ ls nothere
ls: nothere: No such file or directory
~$ echo $?
1

If your scp command returns 0 in this case then the only way to detect that it failed is to inspect the message, which it probably is writing to stderr.

More information about exit status and $? can be found on the Internet.

···

--
RMagick: http://rmagick.rubyforge.org/

I would recommend using rsync instead of scp.
You could do first an rsync and then perform a --dry-run to confirm that
your
data has been transferred correctly.

-drd

···

On Fri, Oct 17, 2008 at 6:11 PM, jackster the jackle < johnsheahan@sflistdb.com> wrote:

It seems to work but not for this command, perhaps since scp gets
executed (but does not complete) the system variable is not false?

[code]
`scp -i /home/jsmith/.ssh/id_rsa /files*.tar jsmith@172.20.1.1:`
[/code]

Tim Hunter wrote:

~$ ls test.rb
test.rb
~$ echo $?
0
~$ ls nothere
ls: nothere: No such file or directory
~$ echo $?
1

Based on what you have described, I think I have figured out a way to
make it work...but I still have one question.

When the following command completes successfully:
   y= `cp /home/jsmith/js.txt /home/jsmith/js2.txt`
   puts $?

$? equals 0, however if I change the path to js.txt to something that
doesn't exist in order to make it fail, $? has a value of 256.

I thought $? should always have a value of 1 when it fails? Why is it
256?

thanks
jack

···

--
Posted via http://www.ruby-forum.com/\.

It is an error code, so it's sometimes other values than 1. Success is always 0.

···

On Sat, Oct 18, 2008 at 2:48 PM, jackster the jackle <johnsheahan@sflistdb.com> wrote:

Tim Hunter wrote:

~$ ls test.rb
test.rb
~$ echo $?
0
~$ ls nothere
ls: nothere: No such file or directory
~$ echo $?
1

Based on what you have described, I think I have figured out a way to
make it work...but I still have one question.

When the following command completes successfully:
  y= `cp /home/jsmith/js.txt /home/jsmith/js2.txt`
  puts $?

$? equals 0, however if I change the path to js.txt to something that
doesn't exist in order to make it fail, $? has a value of 256.

I thought $? should always have a value of 1 when it fails? Why is it
256?

jackster the jackle wrote:

$? equals 0, however if I change the path to js.txt to something that
doesn't exist in order to make it fail, $? has a value of 256.

That's because the low-order 8 bits of $? encode something different;
the next 7 bits are the exit code (0 to 127). Use $?.exitstatus to get
that.

http://www.ruby-doc.org/core/classes/Process/Status.html

I thought $? should always have a value of 1 when it fails? Why is it
256?

The exit status in this case is 256 >> 8, which is 1.

···

--
Posted via http://www.ruby-forum.com/\.

Brian Candler wrote:

jackster the jackle wrote:

$? equals 0, however if I change the path to js.txt to something that
doesn't exist in order to make it fail, $? has a value of 256.

That's because the low-order 8 bits of $? encode something different;
the next 7 bits are the exit code (0 to 127). Use $?.exitstatus to get
that.

http://www.ruby-doc.org/core/classes/Process/Status.html

I thought $? should always have a value of 1 when it fails? Why is it
256?

The exit status in this case is 256 >> 8, which is 1.

this code seems to work well for what I need:

`cp /xhome/jsmith/js.txt /home/jsmith/js2.txt`
unless $?.success?; raise "error with: #{$0}" ; end

I would like to be able to add the line number of the file into the
error message with the file name ($0) but when I try other global
variables such as $@ or $. I don't get the line number of the script
that failed?

jack

···

--
Posted via http://www.ruby-forum.com/\.

Look into __LINE__

HTH,
Michael Guterl

···

On Sun, Oct 19, 2008 at 1:19 PM, jackster the jackle <johnsheahan@sflistdb.com> wrote:

Brian Candler wrote:

jackster the jackle wrote:

$? equals 0, however if I change the path to js.txt to something that
doesn't exist in order to make it fail, $? has a value of 256.

That's because the low-order 8 bits of $? encode something different;
the next 7 bits are the exit code (0 to 127). Use $?.exitstatus to get
that.

class Process::Status - RDoc Documentation

I thought $? should always have a value of 1 when it fails? Why is it
256?

The exit status in this case is 256 >> 8, which is 1.

this code seems to work well for what I need:

`cp /xhome/jsmith/js.txt /home/jsmith/js2.txt`
unless $?.success?; raise "error with: #{$0}" ; end

I would like to be able to add the line number of the file into the
error message with the file name ($0) but when I try other global
variables such as $@ or $. I don't get the line number of the script
that failed?

jackster the jackle wrote:

I would like to be able to add the line number of the file into the
error message with the file name ($0) but when I try other global
variables such as $@ or $. I don't get the line number of the script
that failed?

Use __FILE__ and __LINE__

You probably don't want $0, although it will work if all your code is in
one file; if your script was called foo.rb but it did "require 'bar'"
and the error was in bar.rb, then __FILE__ would be bar.rb but $0 would
be foo.rb

But in any case, you don't need this because

   raise "Hell"

gives you a stack backtrace anyway, the first line of which is the line
where the raise occurred.

begin
  raise "Hell"
rescue Exception => e
  puts "Error: #{e.message} at #{e.backtrace.first}"
end

···

--
Posted via http://www.ruby-forum.com/\.

That really helps clear things up..thanks.

I am almost there but have been struggling to get my e.message into my
sendmail statement.

This code works perfectly but does not contain the value of e in my
email:

rescue Exception => e
   #puts e.message ->prints out correctly
   #puts e.backtrace.first -> prints out correctly
      if e
        `echo "Subject:Error Message\n" | /usr/sbin/sendmail -f
my_server\@server.com john.smith\@email.com`
      end
end

When I try to add the value of e into my email message, it won't send:

`echo "Subject:Error Message\n #{e.message}" | /usr/sbin/sendmail -f
my_server\@server.com john.smith\@email.com`

I think it has something to do with the ` and " characters but I have
tried every possible combination and I can't figure out why doesn't
work?

thanks

jack

Brian Candler wrote:

···

jackster the jackle wrote:

I would like to be able to add the line number of the file into the
error message with the file name ($0) but when I try other global
variables such as $@ or $. I don't get the line number of the script
that failed?

Use __FILE__ and __LINE__

You probably don't want $0, although it will work if all your code is in
one file; if your script was called foo.rb but it did "require 'bar'"
and the error was in bar.rb, then __FILE__ would be bar.rb but $0 would
be foo.rb

But in any case, you don't need this because

   raise "Hell"

gives you a stack backtrace anyway, the first line of which is the line
where the raise occurred.

begin
  raise "Hell"
rescue Exception => e
  puts "Error: #{e.message} at #{e.backtrace.first}"
end

--
Posted via http://www.ruby-forum.com/\.

I finally figured out the last problem which was why some of my Ruby
generated errors that were were not able to be included in my sendmail
command. The problem was the error that was contained in my "e" value
had some text with ` and ' characters in them as follows:

  undefined local variable or method `bad_code_here' for main:Object

Once I added some gsub code to remove those characters, all is working
well and I get an email with the error regardless of whether a shell
command or ruby code were the cause of the error. Here is my final code
which I will now implement in all my scripts (unless someone sees
another problem) so I'm no longer blind sided by know-it-alls here at
work that come to me with "you know your scripts have failed, don't
you?" :slight_smile:

[code]
begin

z = `cp /home/jsmith/js.txt /home/jsmith/js2.txt`
unless $?.success?; raise "Shell Command Failure for line #{__LINE__} in
#{__FILE__}" ; end

# The following line of code will cause Ruby to generate an error
bad_code_here

rescue Exception => e
   if e
     puts e
     e.to_s.gsub!("'","-")
     e.to_s.gsub!("`","-")
     %x{echo "Subject: Script Error: #{__FILE__}:#{__LINE__}\n\n#{e}" |
/usr/sbin/sendmail -f my_server\@gmail.com john.smith\@email.com}
   end
end
[/code]

Thanks to everyone for all the help, I learned alot.
jack

···

--
Posted via http://www.ruby-forum.com/.

Hi,

At Tue, 21 Oct 2008 03:30:44 +0900,
jackster the jackle wrote in [ruby-talk:318164]:

Once I added some gsub code to remove those characters, all is working
well and I get an email with the error regardless of whether a shell
command or ruby code were the cause of the error. Here is my final code
which I will now implement in all my scripts (unless someone sees
another problem) so I'm no longer blind sided by know-it-alls here at
work that come to me with "you know your scripts have failed, don't
you?" :slight_smile:

I'd rather use popen.

rescue Exception => e
   if e
     puts e

       IO.popen("-", "w") do |mail|
         mail or exec(*%w"/usr/sbin/sendmail -f my_server@gmail.com john.smith@email.com")
         mail.puts "Subject: Script Error: #{e.backtrace[0]}"
         mail.puts
         mail.puts e
   # and anything what you want to send
       end

···

   end
end

--
Nobu Nakada

Nobuyoshi Nakada wrote:

I'd rather use popen.

rescue Exception => e
   if e
     puts e

       IO.popen("-", "w") do |mail|
         mail or exec(*%w"/usr/sbin/sendmail -f my_server@gmail.com
john.smith@email.com")
         mail.puts "Subject: Script Error: #{e.backtrace[0]}"
         mail.puts
         mail.puts e
   # and anything what you want to send
       end

wow! so much better!

thanks alot for showing me that

jack

···

--
Posted via http://www.ruby-forum.com/\.

Nobuyoshi Nakada wrote:

I'd rather use popen.

rescue Exception => e
   if e
     puts e

       IO.popen("-", "w") do |mail|
         mail or exec(*%w"/usr/sbin/sendmail -f my_server@gmail.com
john.smith@email.com")
         mail.puts "Subject: Script Error: #{e.backtrace[0]}"
         mail.puts
         mail.puts e
   # and anything what you want to send
       end

Would you happen to know how to send an attachment using the popen code?

thanks

jack

···

--
Posted via http://www.ruby-forum.com/\.

Hi,

At Wed, 22 Oct 2008 03:55:39 +0900,
jackster the jackle wrote in [ruby-talk:318263]:

Would you happen to know how to send an attachment using the popen code?

See RFC5322 and RFC2387.

···

--
Nobu Nakada