Error Exception if script doesn't run

  • Thread starter jackster the jackle
  • Start date
J

jackster the jackle

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
 
B

Brian Candler

jackster said:
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.
 
J

jackster the jackle

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
 
J

Joel VanderWerf

jackster said:
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
 
J

jackster the jackle

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 [email protected]:`

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
 
T

Tim Hunter

jackster said:
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 [email protected]:`

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.
 
J

jackster the jackle

Tim said:
~$ 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
 
H

Henrik Nyh

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?

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

David Rio

[Note: parts of this message were removed to make it a legal post.]

On Fri, Oct 17, 2008 at 6:11 PM, jackster the jackle <
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 [email protected]:`

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
 
B

Brian Candler

jackster said:
$? 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.
 
J

jackster the jackle

Brian said:
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


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
 
M

Michael Guterl

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?
Look into __LINE__

HTH,
Michael Guterl
 
B

Brian Candler

jackster said:
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
 
J

jackster the jackle

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
 
J

jackster the jackle

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

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

Nobuyoshi Nakada

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 (e-mail address removed) (e-mail address removed)")
mail.puts "Subject: Script Error: #{e.backtrace[0]}"
mail.puts
mail.puts e
# and anything what you want to send
end
 
J

jackster the jackle

Nobuyoshi said:
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 (e-mail address removed)
(e-mail address removed)")
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
 
J

jackster the jackle

Nobuyoshi said:
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 (e-mail address removed)
(e-mail address removed)")
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
 
N

Nobuyoshi Nakada

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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top