2

I have a program called main.rb which I would like to do the following:

system("ruby", "program1.rb")
sleep 60
system("ruby", "program2.rb")
sleep 60
system("ruby", "program3.rb")
sleep 60
system("ruby", "program4.rb")

puts "Programs are done running"

Is there a way to do the above without having program2 wait until program1 is finished and so forth? I'm thinking it might have to open a new CLI with each program? Also, I'd like to output the "Programs are done running" message only when all 4 are completed. Is there a way to do that? Thank you!

1
  • 2
    While this is doable, based on the comments made to various answers, it's going to take a lot of help to get you on the right path to be able to do what you want. You need to learn about threading, synchronizing output of threads, or capturing their output independently and then recombining it into a single message. That's beyond the scope of a single question on Stack Overflow. Commented Mar 22, 2013 at 22:36

4 Answers 4

6

It seems you want each program to run concurrently, but wish to wait 60 seconds between launching each subprogram, then wait for all to complete. Process::spawn is essentially system but backgrounds the subprocess returning its pid. This should get you what you want:

to_run = %w{program1.rb program2.rb program3.rb program4.rb}
pids = [ Process.spawn('ruby', to_run.first) ]
pids.concat to_run.drop(1).map{ |p| sleep(60); Process.spawn('ruby', p) }
Process.waitall
puts 'Everything done!'

If elsewhere you have spawned other child processes, waitall will wait for all of them. To only wait for the set you spawned here, replace Process.waitall above with looping over wait

pids.delete(wait) until pids.empty?
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you! However I get the following error: 'spawn': Exec format error - program1.rb (Errno::ENOEXEC)
@walterfaye apparently your ruby programs aren't marked as executable. change the spawn(foo) commands to spawn('ruby', foo) or make your ruby programs executable.
4

You can use Thread class for this. Specifically .new and #join. (http://www.ruby-doc.org/core-2.0/Thread.html)

Example:

runner.rb

threads = [1, 2, 3, 4].map do |time|
  Thread.new { system("ruby sleep.rb #{time}") }
end

threads.map(&:join)

puts "Everything done!"

sleep.rb

sleep ARGV[0].to_i

output

> time ruby runner.rb
Everything done!
ruby runner.rb  0.24s user 0.05s system 7% cpu 4.125 total

Comments

1

I think you want Process.spawn. If you want info on the termination status after you've spawned it, you use Process.wait. Here's the relevant documentation; probably worth a read to figure out exactly what you want to do.

Comments

1

If you want to have the processes run in parallel in Ruby, you'll need to investigate threads, or something more complex than using system.

You don't say what OS you're running on, but why don't you do this with a shell script? It's built-in and very easy:

#!/bin/sh

ruby program1.rb &
sleep 60
ruby program2.rb &
sleep 60
ruby program3.rb &
sleep 60
ruby program4.rb &

& puts a command into the background on Linux and Mac OS, so the script will immediately regain control and sleeps 60 seconds.

It doesn't make sense to say "Programs are done running" unless you're waiting for all of them to finish, which takes a bit more work.

2 Comments

I am on Windows 7. I need to wait for them all to finish because they all output results to one file which I then email to myself.
If you're writing to a file, and need the output to be sequential and grouped by job, you're going to have to do more than run threaded or in parallel or in the background. Jobs running independently can output at different times. If they're all trying to write to the same file, the output will be interwoven between all the jobs. Instead, you can have them write to their own output files, then concatenate those together into one file, in the order you expect, and send that.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.