2008-08-16

IO::popen

Today a short post about running external program from Ruby. I'll start with giving you a nice link: 6 Ways to Run Shell Commands in Ruby. Today I'm going to concentrate on only one of the methods described there:
IO::popen
.

A small Ruby program I use when I access a PostgreSQL database on my local machine. What it does (in order):
- ensure PostgreSQL server is not running
- start the server
- start the pgAdmin
- wait for the pgAdmin to finish
- stop the server.
POSTGRESQL_DIR="C:/Program Files/PostgreSQL/8.2"
SERVER_PATH="\"#{POSTGRESQL_DIR}/bin/pg_ctl.exe\""
DATA_DIR="\"#{POSTGRESQL_DIR}/data/\""

START_COMMAND="#{SERVER_PATH} start -D #{DATA_DIR}"
STOP_COMMAND="#{SERVER_PATH} stop -D #{DATA_DIR}"
ADMIN_PATH="\"#{POSTGRESQL_DIR}/bin/pgAdmin3.exe\""

Process.waitpid(IO::popen(STOP_COMMAND).pid)
puts "PostgreSQL Server stopped."
IO::popen(START_COMMAND)
puts "PostgreSQL Server started."
adm_pid=IO::popen(ADMIN_PATH).pid
puts "pgAdmin started."
puts "Waiting for pgAdmin to finish..."
Process.waitpid(adm_pid)
puts "pgAdmin closed."
Process.waitpid(IO::popen(STOP_COMMAND).pid)
puts "PostgreSQL Server stopped."
As you see, I use
IO::popen
to spawn a process, and also I get the process'
pid
to wait for it to finish using
Process.waidpid(pid)
.

One more thing I was trying to do is to redirect the Server console output to the program's own console. I succeeded with this, but for some reason I couldn't make the
Process::pid
work when I was redirecting the output. Anybody knows why?

Here's how I was redirecting output:
Thread::new(IO::popen(START_COMMAND))\
{ |srv|
until srv.eof?
print srv.readpartial(1024)
end
}
As I say, the redirection was working fine, but if there was no input from the server process and the pgAdmin finished at that time,
Process::pid
was still waiting (it interrupted when there came some input from the server console, though).

I tried to use several other variations with
sysread
,
readpartial
and
select
, but none was better, some even worse than this one. Thanks for any suggestions.

One day I'll post about how to connect to the database from Ruby, too.

No comments: