# Ruby for system administration

**URL:** <https://www.ruby-forum.com/t/ruby-for-system-administration/56810>\
**Category:** Ruby\
**Created:** [April 4, 2006, 12:20pm UTC](https://www.ruby-forum.com/t/ruby-for-system-administration/56810 "2006-04-04T12:20:53Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Tassilo\_Horn](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/6f9a4e/32.png) [@Tassilo\_Horn](https://www.ruby-forum.com/u/Tassilo_Horn)\
**Post date:** [April 4, 2006, 12:20pm UTC](https://www.ruby-forum.com/t/ruby-for-system-administration/56810/1 "2006-04-04T12:20:53Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![Tassilo\_Horn](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/6f9a4e/32.png) [@Tassilo\_Horn](https://www.ruby-forum.com/u/Tassilo_Horn)\
**Post date:** [April 4, 2006, 12:36pm UTC](https://www.ruby-forum.com/t/ruby-for-system-administration/56810/2 "2006-04-04T12:36:15Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![Tassilo\_Horn](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/6f9a4e/32.png) [@Tassilo\_Horn](https://www.ruby-forum.com/u/Tassilo_Horn)\
**Post date:** [April 4, 2006, 2:21pm UTC](https://www.ruby-forum.com/t/ruby-for-system-administration/56810/3 "2006-04-04T14:21:24Z")

</div>

“Farrel L.” [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) writes:

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

---

<div class="post-metadata">

**Author:** ![Tassilo\_Horn](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/6f9a4e/32.png) [@Tassilo\_Horn](https://www.ruby-forum.com/u/Tassilo_Horn)\
**Post date:** [April 4, 2006, 1:29pm UTC](https://www.ruby-forum.com/t/ruby-for-system-administration/56810/4 "2006-04-04T13:29:11Z")

</div>

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 O.-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.braveworld.net/riva)

---

<div class="post-metadata">

**Author:** ![Tassilo\_Horn](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/6f9a4e/32.png) [@Tassilo\_Horn](https://www.ruby-forum.com/u/Tassilo_Horn)\
**Post date:** [April 5, 2006, 9:41am UTC](https://www.ruby-forum.com/t/ruby-for-system-administration/56810/5 "2006-04-05T09:41:43Z")

</div>

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?

system ‘my\_command’ does this.
