From: Damphyr Date: 2006-04-04T20:28:04+09:00 Subject: Re: Ruby for system administration Tassilo Horn wrote: > 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 :output 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 @success=@cmd.success? @output=@cmd.output @exec_time=@cmd.exec_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 :output,: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.