Ruby for system administration

T

Tassilo Horn

Hi,

since I don't like bash or other shell languages too much, I've started
writing more and more system administration scripts in ruby, which works
great and saves much time. I invoke the commands which should be
executed with 'Kernel.`'.

But there's one problem with that. If my_command produces output when
being executed directly from the shell prompt, I won't see it when I
call it in a ruby script with `my_command`.

To get along this I normally use

$stdout << `my_command`

but then the output will not be shown until my_command finishes. If
my_command takes some time, the user running the script will have no
feedback.

Is there a way to directly redirect my_command's output to stdout? Or
are there other ways to work arround this?

Much thanks in advance,
Tassilo
 
F

Farrel Lifson

You might want to look at IO.popen. It allows you to run a command and
communicate with it (and receive output) via pipes which to your
script will just be an IO object with all the associated methods like
readlines,puts etc etc. I'm using it in a project currently and it's
quite easy to use.

Farrel
 
T

Tassilo Horn

Hi Farrel,
You might want to look at IO.popen. [...]

I'll have a look at it later this day. But the things you mentioned
sound quite good, I think.

Thanks,
Tassilo
 
D

Damphyr

Tassilo said:
Is there a way to directly redirect my_command's output to stdout? Or
are there other ways to work arround this?
I use IO.popen and Observer to get progress reports for commands.
I have been building an automation framework together with what I call a
test integration framework for my current project.
At th emoment the project is in full steam and there is absolutely no
chance to release the code for public consumption (meaning there is no
time to remove project specific stuff and wrap the whole thing as a
public library that is half-way stable).
Just so, here's what I have done in the lowest level. A Command module
to define a stable interface and DOSCommand which I use to execute
commands on a windows shell (which in turn uses the class that led to
this whole Command thing and which actually is my answer to your
question :) ).
I have several commands, my favorite being the PressAnyKeyCommand :)


#This module is the interface for execution of arbitrary commands where we
#need access to the success status, output and execution time for a
command
#
#Check DOSCommand and RubyCommand for some implementations
module Command
attr_writer :eek:utput
def name
return @name
end
def output
init
return @output
end
def working_directory
init
return @working_directory
end
def exec_time
init
return @exec_time
end
def success?
init
return @success
end
def run?
init
return @run
end

def run
init
@run=true
end

def status verbose=false
init
msg=""
if run?
st="succeeded"
st="failed" unless @success
msg+="#{@name} #{st} in #{@exec_time}s\n"
else
msg+="#{@name} was not executed\n"
end
msg+="Working directory:
#{@working_directory}\nLog:\n#{@output}\n" if (!success?||verbose)
return msg
end
#This method initializes the module members with sane values.
#
#It also checks that _working_directory_ is a directory (it
raises RuntimeError if it isn't)
#
#It's a good idea to use this method in the initialize method of
any objects including this module
#but it isn't necessary.
def init name="",working_directory=nil
begin
@name=name
@output="" unless @output
@exec_time=0 unless @exec_time
@working_directory=working_directory
@working_directory=Dir.pwd unless @working_directory
raise "Non-existent working directory: #{working_directory}"
unless File.directory?(@working_directory)
@run=false unless @run
@success=false unless @success
end unless @name
end
end
#Class that wraps the execution of a command in a command shell.
class DOSCommand
include Command
attr_reader:command_line
#If _working_directory_ is specified then the command will be
executed in that directory.
def initialize name,command_line,working_directory=nil
init(name,working_directory)
@command_line=command_line
@cmd=RivaLib::Win::ExecCmd.new(@command_line)
end

#Runs the command.
def run
@run=true
prev_dir=Dir.pwd
begin
Dir.chdir(@working_directory) if @working_directory
@cmd.run
@[email protected]?
@[email protected]
@[email protected]_time
return @success
rescue SystemCallError
return false
ensure
Dir.chdir(prev_dir)
end
end

#Executes a command on a dos shell, redirecting stderr to stdout ("2>&1")
#
#You can then access the output and the return value for the command.
#
#This is meant as a last-resort replacement for popen3 (because of
problems with VC++6.0 and the Ruby One-Click Installer).
#
#_exec_time_ provides the Time spent running the command.
class ExecCmd
attr_reader :eek:utput,:cmd,:exec_time
#When a block is given, the command runs before yielding
def initialize cmd
@output=""
@exec_time=0
@cmd=cmd
@cmd_run=cmd+" 2>&1" unless cmd=~/2>&1/
if block_given?
run
yield self
end
end

#Runs the command
def run
t1=Time.now
IO.popen(@cmd_run){|f|
@output=f.read
@process=Process.waitpid2(f.pid)[1]
}
@exec_time=Time.now-t1
end
#Returns false if the command hasn't been executed yet
def run?
return false unless @process
return true
end
#Returns the exit code for the command.
#
#Returns nil if the command hasn't run yet.
def exitcode
return @process.exitstatus if @process
return nil
end
#Returns true if the command was succesfull.
#
#Will return false if the command hasn't been executed
def success?
return @process.success? if @process
return false
end
end


--
http://www.braveworld.net/riva

____________________________________________________________________
http://www.freemail.gr - äùñåÜí õðçñåóßá çëåêôñïíéêïý ôá÷õäñïìåßïõ.
http://www.freemail.gr - free email service for the Greek-speaking.
 
F

Florian Frank

Tassilo said:
Is there a way to directly redirect my_command's output to stdout? Or
are there other ways to work arround this?
system 'my_command' does this.
 

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,995
Messages
2,570,228
Members
46,818
Latest member
SapanaCarpetStudio

Latest Threads

Top