try this - i haven't tested on windows but it can certainly be made to work:
harp:~ > cat a.rb
#!/usr/bin/env ruby
require 'rbconfig'
require 'thread'
class Spawn
CONFIG = Config::CONFIG
RUBY =
if system('ruby -e 42') # ruby is in our path
'ruby'
else # guess from rbconfig
File.join CONFIG['bindir'], CONFIG['ruby_install_name']
end
PROGRAM = "p $$;STDOUT.flush;STDERR.reopen(STDOUT);exec(*ARGV)"
ATTRIBUTES = %w[
mutex
out
exitstatus
exitstatus_q
cmd
pipe
pid
thread
]
ATTRIBUTES.each{|a| attr_accessor a}
def initialize *argv
@mutex = Mutex.new
@out = ''
@exitstatus = nil
@exitstatus_q = Queue.new
@cmd = "#{ RUBY } -e '#{ PROGRAM }' #{ argv.join(' ') }"
@pipe = IO.popen @cmd
@pid = @pipe.gets.to_i
at_exit{ Process.kill -9, @pid rescue nil }
@thread = Thread.new{
begin
while((line = @pipe.gets))
@mutex.synchronize{ @out << line }
end
ensure
@pipe.close rescue nil
exitstatus = $?.exitstatus
@exitstatus_q.push exitstatus
end
}
end
def out
@mutex.synchronize{ @out }
end
def exitstatus non_block = false
@exitstatus ||= @exitstatus_q.pop(non_block)
end
class << self; alias new; end
end
require 'yaml'
cmd = ARGV.join ' '
spawn = Spawn[ cmd ]
y 'spawn.cmd' => spawn.cmd
y 'spawn.pid' => spawn.pid
y 'spawn.exitstatus' => spawn.exitstatus
y 'spawn.out' => spawn.out
harp:~ > ruby a.rb date
spawn.cmd: ruby -e 'p $$;STDOUT.flush;STDERR.reopen(STDOUT);exec(*ARGV)' date
spawn.pid: 27232
spawn.exitstatus: 0
spawn.out: |
Tue Jul 11 10:31:22 MDT 2006
harp:~ > ruby a.rb no-exist
spawn.cmd: ruby -e 'p $$;STDOUT.flush;STDERR.reopen(STDOUT);exec(*ARGV)' no-exist
spawn.pid: 27235
spawn.exitstatus: 1
spawn.out: |
-e:1:in `exec': No such file or directory - no-exist (Errno::ENOENT)
from -e:1
regards.
-a
···
On Wed, 12 Jul 2006, Name Name wrote:
I would like to run a process concurrently (thus if the process goes to
sleep or runs forever, I can still run other code from my main process) and
have all standard out of that process be put into a text file. I would also
like this code to be portable. And finally, I would like to be able to kill
this process at any time (So I will need the pid)
This thus eliminates the use of fork. Also, I have tried:
a=IO.popen("program > logfile"), but on Windows this creates two
processes, cmd.exe and program. a.pid only gives the pid of cmd.exe.
And the behavior on *nix seems to be just the program (although I can be
wrong).
So I require portability in that sense.
Is this possible?
thanks
--
suffering increases your inner strength. also, the wishing for suffering
makes the suffering disappear.
- h.h. the 14th dali lama