Handling Errno::ETIMEDOUT exception in capistrano - ruby

I am using a block to dynamically generate a list of servers I want to push code to. Occasionally a few of the machines are unreachable, resulting in a "Errno::ETIMEDOUT". This stop the entire deployment process. How do I rescue this and run some custom code using capistrano?

You'd have to wrap your server list generator with a try catch block.
begin
# ... Get server list
rescue Errno::ETIMEDOUT
# ... Handle cases when connection times out
end

Related

Skip if it doesn't respond in a certain amount of time

I've created a program that pulls websites off of google and then strips them down to their basic url: example http://google.com/search/owie/weikw => http://google.com. It then saves these to a file.
After that it runs a .each_line on the file then runs a whois command, what I want to do is if the command doesn't respond in a certain amount of time, skip that line of the file and go to the next one, is there a way I can do this?
Use the Timeout Module
If your scraper or whois doesn't support timeout natively, you can use Timeout::timeout to set an upper bound in seconds. For example:
require 'timeout'
MAX_SECONDS = 10
begin
Timeout::timeout(MAX_SECONDS) do
# run your whois
end
rescue Timeout::Error
# handle the exception
end
By default, this will raise a Timeout::Error exception if the block exceeds the time limit, but you can have the method raise other exceptions if you prefer. How you handle the exceptions is then up to you.

Prevent exceptions in Rubygem that cannot communicate with its associated web service?

I am using a RubyGem (DeathByCaptcha) that makes HTTP calls to deathbycaptcha.com. Every so often the HTTP request times out or fails for some other unknown reason, and my Ruby scripts exits with an exception. I am trying to automate repeated instances of this method ("decode") and I am trying to determine if there is a way to prevent an error in this method from exiting the whole script.
EDIT: Since I'm bound to get flamed on here, I will mention upfront that the purpose of this is to determine the effectiveness of different captcha options on my website's registration page with common captcha-breakers, because I have had problems with spam signups.
Here is how to prevent the exception from exiting the script.
tries = 0
begin
# risky failing code
rescue
sleep(1) # sleep n seconds
tries += 1
retry if tries <= 3 # retry the risky code again
end
You would need to catch the exception that is raised and somehow handle it.
You are looking for something like
begin
# Send HTTP request
rescue WhateverExceptionClassYouGet > error
# Do something with the error
end

How to capture Chef exceptions

I'm working on a Chef recipe right now and I need to update a data bag with some information depending on the result of a code. Basically I need to update a data bag with succeed or failed.
The code looks like this:
begin
node[:fileDeploy].each do |f|
if f[:deploy]
cookbook_file "#{f[:subdirectory]}/#{f[:targetFilename]}" do
owner users['tomcatUser']
group users['tomcatGroup']
mode "0755"
cookbook node[:cookbookName]
source "#{f[:sourceFilename]}"
end
end
end
# Update data bag: succeeded
rescue Chef::Exceptions::FileNotFound => e
# Update data bag: failed
end
The problem is that even though there is a missing file, the rescue block is not excecuted and the data bag is not updated accordingly.
So, when I run the command sudo chef-client on the server, it ends up with the exception Chef::Exceptions::FileNotFound but it is not being handled by the rescue block. does it make sense? Any help?
Your rescue block doesn't catch the exception because the code raising the exception is not executed in the scope of the exception handler.
In your code, you declare a cookbook_file resource. The declaration goes fine and the resource is scheduled for execution during the convergence phase. Your rescue block could catch an exception that would occur during declaration of the resource, not when it is actually executed.
Please see About the chef-client Run to learn more about the two phases of a chef run, namely the generation of the resource collection and the later convergence.
Now for your desired result, you could check the condition that the source file exists during convergence and decide accordingly.
Generally, handling errors is rather hard in Chef. This is by design, as you generally should design your system that it is rather independent from other parts. So if you need a directory or file to be present, you ought to create that one explicitly using the appropriate resource. You can then use notifications to notify other resources to run a certain action if the current resource "changed" (whatever that means for the specific resource).
The code below tries to achieve something similar to what you apparently want. It still doesn't catch an exception during convergence but tries to not raise one in the first place but checks the required conditions and runs the appropriate resources.
node[:fileDeploy].each do |f|
if f[:deploy]
cookbook_file "#{f[:subdirectory]}/#{f[:targetFilename]}" do
owner users['tomcatUser']
group users['tomcatGroup']
mode "0755"
cookbook node[:cookbookName]
source f[:sourceFilename]
only_if{ Dir.exist?(File.base_name(f[:sourceFilename]) }
notifies :run, "execute[success #{f[:sourceFilename]}]", :immediately
end
# This one gets notified (and run) when the cookbook_file is successful
execute "success #{f[:sourceFilename]}" do
action :nothing
command "do whatever you like"
end
# This one runs only if the created file doesn't exist by now
execute "error #{f[:subdirectory]}/#{f[:targetFilename]}" do
action :run
command "do whatever you like"
creates "#{f[:subdirectory]}/#{f[:targetFilename]}"
end
end
end

How to catch top level failures on an EventMachine server?

I have an EventMachine server that I am monitoring with monit. Sometimes it crashes, and I am trying to figure out why, but it is unclear to me how I can just log all top level failures. I tried code like this:
begin
EventMachine::run do
EventMachine::start_server('0.0.0.0', PORT, MyServer)
end
rescue Exception => e
puts "FAILURE: #{e.class}: #{e}"
end
but that does not seem to ever catch errors. I suspect it might be something like running out of memory, which I am tracking separately, but still I would like this server to log its proximate cause of failure if possible.
If you want a catch-all error handler, try EM.error_handler. Example from the docs:
EM.error_handler{ |e|
puts "Error raised during event loop: #{e.message}"
}
You may also want more fine-grained error handling, in which case you can use the errback mechanism (see Deferrable). So for example you could have in your reactor loop:
EventMachine::run do
server = EventMachine::start_server('0.0.0.0', PORT, MyServer)
server.errback { # handle error thrown by server here }
end
For this to work, include Deferrable in your MyServer, then whenever you want to raise an error, call fail.

'Who's online?' Ruby Network Program

I have several embedded linux systems that I want to write a 'Who's Online?' network service in Ruby. Below is related part of my code:
mySocket = UDPSocket.new
mySocket.bind("<broadcast>", 50050)
loop do
begin
text, sender = mySocket.recvfrom(1024)
puts text
if text =~ /KNOCK KNOCK/ then
begin
sock = UDPSocket.open
sock.send(r.ipaddress, 0, sender[3], 50051)
sock.close
rescue
retry
end
end
rescue Exception => inLoopEx
puts inLoopEx.message
puts inLoopEx.backtrace.inspect
retry
end
end
I send the 'KNOCK KNOCK' command from a PC. Now, the problem is since they all receive the message at the same time, they try to respond at the same time too, which causes a Broken Pipe exception (which is the reason of my 'rescue retry' code). This code works OK sometimes but; other times the rescue retry part of the code (which is waked by Broken Pipe exception from sock.send) causes one or more systems to respond after 5 seconds or so.
Is there a better way of doing this since I assume I cant escape the Broken Pipe exception?
I have found that exception was caused by the 'r.ipaddress' part in the send command, which is related to my embedded system's internals...

Resources