Forum: Ruby Error Exception if script doesn't run

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
B28a3426b4a8ae5ad2302fdf1c6674e8?d=identicon&s=25 Jackster The jackle (jackster)
on 2008-10-17 17:30
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
753dcb78b3a3651127665da4bed3c782?d=identicon&s=25 Brian Candler (candlerb)
on 2008-10-17 17:39
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.
B28a3426b4a8ae5ad2302fdf1c6674e8?d=identicon&s=25 Jackster The jackle (jackster)
on 2008-10-17 19:11
that does exactly what I had hoped....thanks alot!

jack
B28a3426b4a8ae5ad2302fdf1c6674e8?d=identicon&s=25 Jackster The jackle (jackster)
on 2008-10-17 23:46
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.
47b1910084592eb77a032bc7d8d1a84e?d=identicon&s=25 Joel VanderWerf (Guest)
on 2008-10-18 00:27
(Received via mailing list)
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
B28a3426b4a8ae5ad2302fdf1c6674e8?d=identicon&s=25 Jackster The jackle (jackster)
on 2008-10-18 01:12
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
3afd3e5e05dc9310c89aa5762cc8dd1d?d=identicon&s=25 Tim Hunter (Guest)
on 2008-10-18 02:01
(Received via mailing list)
jackster the jackle wrote:
>    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.
B28a3426b4a8ae5ad2302fdf1c6674e8?d=identicon&s=25 Jackster The jackle (jackster)
on 2008-10-18 14:49
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
4a551074ddba4460f95d011c47190d0e?d=identicon&s=25 Henrik --- (malesca)
on 2008-10-18 15:03
(Received via mailing list)
On Sat, Oct 18, 2008 at 2:48 PM, jackster the jackle
<johnsheahan@sflistdb.com> wrote:
> Based on what you have described, I think I have figured out a way to
> 256?
It is an error code, so it's sometimes other values than 1. Success is
always 0.
60c6b87c4cc2716c83a737e0ba2d3bc0?d=identicon&s=25 David Rio (Guest)
on 2008-10-18 23:22
(Received via mailing list)
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]
>

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
753dcb78b3a3651127665da4bed3c782?d=identicon&s=25 Brian Candler (candlerb)
on 2008-10-19 10:28
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.
B28a3426b4a8ae5ad2302fdf1c6674e8?d=identicon&s=25 Jackster The jackle (jackster)
on 2008-10-19 19:20
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
D337e2cf7c6d03caac6988d83e0e7f66?d=identicon&s=25 Michael Guterl (mguterl)
on 2008-10-19 19:33
(Received via mailing list)
On Sun, Oct 19, 2008 at 1:19 PM, jackster the jackle
<johnsheahan@sflistdb.com> 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?
>
Look into __LINE__

HTH,
Michael Guterl
753dcb78b3a3651127665da4bed3c782?d=identicon&s=25 Brian Candler (candlerb)
on 2008-10-20 17:25
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
B28a3426b4a8ae5ad2302fdf1c6674e8?d=identicon&s=25 Jackster The jackle (jackster)
on 2008-10-20 17:40
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
B28a3426b4a8ae5ad2302fdf1c6674e8?d=identicon&s=25 Jackster The jackle (jackster)
on 2008-10-20 20:31
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?" :-)

[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
F1d6cc2b735bfd82c8773172da2aeab9?d=identicon&s=25 Nobuyoshi Nakada (nobu)
on 2008-10-21 05:52
(Received via mailing list)
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?" :-)

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
B28a3426b4a8ae5ad2302fdf1c6674e8?d=identicon&s=25 Jackster The jackle (jackster)
on 2008-10-21 12:38
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
B28a3426b4a8ae5ad2302fdf1c6674e8?d=identicon&s=25 Jackster The jackle (jackster)
on 2008-10-21 20:23
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
F1d6cc2b735bfd82c8773172da2aeab9?d=identicon&s=25 Nobuyoshi Nakada (nobu)
on 2008-10-22 06:42
(Received via mailing list)
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.
This topic is locked and can not be replied to.