18

I have a shell script named test.sh. How can I trigger the test.sh from Ruby?

I want test.sh to run as a background process, what means in Ruby it is a ansync call.

STDERR and STDOUT also need to be written to a specific file.

Any ideas?

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
TheOneTeam
  • 25,806
  • 45
  • 116
  • 158

3 Answers3

38

@TanzeebKhalili's answer works, but you might consider Kernel.spawn(), which doesn't wait for the process to return:

pid = spawn("./test.sh")
Process.detach(pid)

Note that, according to the documentation, whether you use spawn() or manually fork() and system(), you should grab the PID and either Process.detach() or Process.wait() before exiting.

Regarding redirecting standard error and output, that's easy with spawn():

pid = spawn("./test.sh", :out => "test.out", :err => "test.err")
Process.detach(pid)
NVI
  • 14,907
  • 16
  • 65
  • 104
Darshan Rivka Whittle
  • 32,989
  • 7
  • 91
  • 109
  • Nice, also works in windows ! with multiple processes that write to test.out some lines are garbled though – peter Aug 16 '12 at 12:26
  • @peter Yeah, doing buffered writes to the same file simultaneously from multiple processes would indeed garble some lines. There are a number of solutions to that problem, but the simplest is just writing to a separate file from each process. Otherwise you'd probably want a separate process to multiplex the output. – Darshan Rivka Whittle Aug 16 '12 at 13:18
13

Try this:

Process.fork { system "./test.sh" }

Won't work on windows, for which you can use threading.

Tanzeeb Khalili
  • 7,324
  • 2
  • 23
  • 27
0

I think IO.popopen also deserves a mention here. Something like this would append the output from multiple runs of the command. to stdout.log and stderr.log

open('stdout.log', 'a') { |file|
  file.puts(
      IO.popen(["./test.sh"], :err => ["stderr.log", "a"]) { |result| 
          result.read 
      }
  )
end
Stuart Mclean
  • 407
  • 6
  • 7