No such file or directory error in service - ruby

I am a newbie to ruby and got stuck into one of the issues with the windows service I created (code is below). When the service runs, I get an error in test log that there is notsuch file or directory and it does not find any path to the logs with name QaTaTestExe.log.xml. This is the error I see in file.
***Daemon failure 2013-07-28 16:29:28 -0400 err=No such file or directory
However when I tried the code (which is after while running? ) in separate class it works. Am I missing anything in my configuration since the error is regarding Daemon?
LOG_FILE = 'C:\\test.log'
require "rubygems"
begin
require 'win32/daemon'
include Win32
class Daemon
def service_main
while running?
testresultpath = "Z:/Windows 2008 R2 - Exchange 2010 - Search"
file_path s =[]
Find.find(testresultpath) do |path|
file_paths << path if path =~ /.*\QaTaTestExe.log.xml$/
File.open("c:\\test.log", "a"){ |f| f.puts(path)}
end
sleep 30
File.open("c:\\test.log", "a"){ |f| f.puts "Service is running #{Time.now}" }
end
end
def service_stop
File.open("c:\\test.log", "a"){ |f| f.puts "***Service stopped #{Time.now}" }
exit!
end
end
Daemon.mainloop
rescue Exception => err
File.open(LOG_FILE,'a+'){ |f| f.puts " ***Daemon failure #{Time.now} err=#{err} " }
raise
end

Related

Declaring Ruby Methods along with a menu

I've been fooling around with Ruby lately, so i decided to write an sftp client.
require 'net/sftp'
require 'ostruct'
require 'optparse'
class Sftp
def parse(arguments)
ARGV << "-h" if ARGV.empty?
#options = OpenStruct.new
args = OptionParser.new do |args|
args.banner = "Usage: #{__FILE__} [options]"
args.on("--host HOST", String,
) do |host|
#options.host = host
end
args.on("--username USERNAME", String,
) do |username|
#options.username = username
end
args.on("--password PASSWORD", String,
) do |password|
#options.password = password
end
args.on("--port=PORT", Integer,
) do |port|
#options.port = port
end
args.on("--mkdir=MAKE DIRECTORY", String,
) do |mkdir|
#options.mkdir = mkdir
end
args.on("--rmdir=REMOVE DIRECTORY", String,
) do |rmdir|
#options.rmdir = rmdir
end
args.on("-h", "--help", "Show help and exit") do
puts args
exit
end
end
begin
args.parse!(arguments)
rescue OptionParser::MissingArgument => error
puts "[!] ".red + error.message.bold
exit
rescue OptionParser::InvalidOption => error
puts "[!] ".red + error.message.bold
exit
end
def connect
Net::SFTP.start(#options.host, #options.username, :password => #options.password, :port => #options.port) do |sftp|
sftp.mkdir(#options.mkdir)
puts "Creating Directory: #{#options.mkdir}"
sftp.rmdir(#options.rmdir)
puts "Deleting Directory: #{#options.rmdir}"
end
end
end
def run(arguments)
parse(arguments)
connect
end
end
sftp = Sftp.new
sftp.run(ARGV)
I want these two commands to be separated. For example when i pass
the argument mkdir I just want only this to run and if I want to run rmdir again I just wanna run only this command.
It has to do with methods, but I can't find a proper solution. And I'm really rusty.
Any recommendation?
A very simple approach could be to check if the required value is set before running the command, and skip the command if the value is not set.
def connect
Net::SFTP.start(#options.host, #options.username, password: #options.password, port: #options.port) do |sftp|
if #options.mkdir
sftp.mkdir(#options.mkdir)
puts "Creating Directory: #{#options.mkdir}"
end
if #options.rmdir
sftp.rmdir(#options.rmdir)
puts "Deleting Directory: #{#options.rmdir}"
end
end
end

Monitoring thread variables in ruby

I'm building a task runner where each task is built from a number of commands:
def run
begin
#Validating task params
set_progress "Validating params", "Validating params: #{#params}"
validate_params
#task_info["steps"].each do |step|
#log.info "Running command: #{step["description"]}"
set_progress step["description"]
command = Command.factory #params, step, #signature, #log
timeout = General.in_seconds step["timeout"]
command_res = Timeout.timeout(timeout) do
command.execute
end
end
set_progress "Completed"
rescue Exception => exception
#log.error exception.message + "\nBACK TRACE:\n" + exception.backtrace.join("\n")
set_progress #progress, "Failed, check logs. exception: #{exception.message}"
end
end
Now the command is ran by "command.execute", and there is a field inside the command class which is called "current_status" which i would like to monitor each X seconds and check the command status in order to update the user about the command status, how can i do it ? i probably need to run the command in a separate thread and then monitor it, but how can i monitor it ?
a quick and dirty methodology which might contain syntax errors :P
class JobManager
def initialize
#threads =[]
end
def registered_jobs
#registered_jobs ||= [Job1.new, Job2.new]
end
def start_jobs
registered_jobs.each {|j| #threads << Thread.new { j.run } }
end
def statuses?
registered_jobs.collect {|j| j.status? }
end
end
Usage:
manager = JobManager.new
manager.start_jobs
# elsewhere
manager.statuses? # returns [Job1.status?, Job2.status?]
This is the sort of idiom I'd use in my code. It's important to be aware that the status variables are subject to race conditions if they are not properly guarded against concurrent modification and access.

How to test adding line to error log by causing rescue statement in rspec

I have a this Foo class.
class Foo
def open_url
Net::HTTP.start("google.com") do |http|
# Do Something
end
rescue Exception => e
File.open("error.txt","a+"){|f| f.puts e.message }
end
end
And I want to test by this Rspec.
require_relative 'foo'
describe Foo do
describe "#open_url" do
it "should put error log if connection fails" do
Net::HTTP.stub(:start).and_return(Exception)
# Check if a line to error.txt is added.
end
end
end
How can I check if a line is inserted to error.txt?
You could read the file you are actually writing
describe Foo do
describe "#open_url" do
it "should put error log if connection fails" do
Net::HTTP.stub(:start).and_raise
Foo.open_url
file = File.open("error.txt", "r")
# ...
end
end
end
An alternative would be to check that the file is opened: something along the lines of this
File.should_receive(:open).with("error.txt", "a+", {|f| f.puts e.message })

Making RUBY Ocra work for library that requires include module

I have created a ruby executable in windows using OCRA. i am using it for few years now and works well no complains with it.
but today when i created and distributed a exe that contain Include module in the code it failed at the include module line.
is there a better way to write the code or compile the exe ?
in the below code the error occurs at include Mongo location. if i remove include module then the code does not work
require 'all the libs including mongo'
###############################################################
#### to insert the program parameters and the data to mongodb
###############################################################
def writedatatomongodb(toinsert, sname, dname, collname, lfile)
#Sampele params to insert {:command=>"get data", :servername=>"servname", :remotecommand=>"/user/home/somefile", :outputfile=>"filename123_YYYYMMDD.txt"}
include Mongo
#client = MongoClient.new(sname, 27017)
p "Copying parametrs to Mongodb"
##client = MongoClient.new('myservername', 27017)
#db = #client[dname]
#coll = #db[collname]
File.open(lfile, 'a'){ |f| f.puts "Copying params to Mongodb" }
id = #coll.insert(toinsert)
p "Copied parametrs to Mongodb"
rescue Exception => e
File.open(lfile, 'a'){ |f| f.puts "Error occured: #{e}" }
end

How to get exit status with Ruby's Net::SSH library?

I have a snippet of code, simply trying to execute a script on a remote server, in the event that it fails, I'd like to make a follow-up call, imagine this:
require 'rubygems'
require 'net/ssh'
require 'etc'
server = 'localhost'
Net::SSH.start(server, Etc.getlogin) do |ssh|
puts (ssh.exec("true") ? 'Exit Success' : "Exit Failure")
puts (ssh.exec("false") ? 'Exit Success' : "Exit Failure")
end
I would expect (ignoring that stdout and stderr are printed in my contrived example) - but first line should exit with 0 which I would expect Ruby would interperate as false and display "Exit Failure" (sure, so the logic is wrong, the ternary needs to be flipped) - but the second line should exit with the opposite status, and it doesn't.
I can't even find anything in the documentation about how to do this, and I'm a little worried that I might be doing it wrong?!
I find the following way of running processes with Net::SSH much more useful. It provides you with distinct stdout and stderr, exit code and exit signal.
require 'rubygems'
require 'net/ssh'
require 'etc'
server = 'localhost'
def ssh_exec!(ssh, command)
stdout_data = ""
stderr_data = ""
exit_code = nil
exit_signal = nil
ssh.open_channel do |channel|
channel.exec(command) do |ch, success|
unless success
abort "FAILED: couldn't execute command (ssh.channel.exec)"
end
channel.on_data do |ch,data|
stdout_data+=data
end
channel.on_extended_data do |ch,type,data|
stderr_data+=data
end
channel.on_request("exit-status") do |ch,data|
exit_code = data.read_long
end
channel.on_request("exit-signal") do |ch, data|
exit_signal = data.read_long
end
end
end
ssh.loop
[stdout_data, stderr_data, exit_code, exit_signal]
end
Net::SSH.start(server, Etc.getlogin) do |ssh|
puts ssh_exec!(ssh, "true").inspect
# => ["", "", 0, nil]
puts ssh_exec!(ssh, "false").inspect
# => ["", "", 1, nil]
end
Hope this helps.
Building on the answer by flitzwald - I've monkey patched my version of this into Net::SSH (Ruby 1.9+)
class Net::SSH::Connection::Session
class CommandFailed < StandardError
end
class CommandExecutionFailed < StandardError
end
def exec_sc!(command)
stdout_data,stderr_data = "",""
exit_code,exit_signal = nil,nil
self.open_channel do |channel|
channel.exec(command) do |_, success|
raise CommandExecutionFailed, "Command \"#{command}\" was unable to execute" unless success
channel.on_data do |_,data|
stdout_data += data
end
channel.on_extended_data do |_,_,data|
stderr_data += data
end
channel.on_request("exit-status") do |_,data|
exit_code = data.read_long
end
channel.on_request("exit-signal") do |_, data|
exit_signal = data.read_long
end
end
end
self.loop
raise CommandFailed, "Command \"#{command}\" returned exit code #{exit_code}" unless exit_code == 0
{
stdout:stdout_data,
stderr:stderr_data,
exit_code:exit_code,
exit_signal:exit_signal
}
end
end
For newer versions of Net::SSH, you can just pass a status hash to Net::SSH::Connection::Session#exec:
status = {}
Net::SSH.start(hostname, user, options) do |ssh|
channel = ssh.exec(command, status: status)
channel.wait # wait for the command to actually be executed
end
puts status.inspect
# {:exit_code=>0}
By default, exec streams its output to $stdout and $stderr. You can pass a block to exec to do something different, a la:
ssh.exec(command, status: status) do |ch, stream, data|
if stream == :stdout
do_something_with_stdout(data)
else
do_something_with_stderr(data)
end
end
This works on 6.1.0 - not sure about availability for older versions. See http://net-ssh.github.io/net-ssh/Net/SSH/Connection/Session.html#method-i-exec for more details.

Resources