This issue looks easy, but is actually complex.
On shell, you may run a command asynchronously just by adding
& at the end of command.
$ sleep 10 &  8048
You can obtain the process ID, so you can stop the command.
$ kill 8048
How can we run an external command on Ruby?
The easiest way to run an external command is
system 'sleep 10 &'
The return value of
system() is the exit code. In this case, the
system() returns true immediately after that ran, but it doesn't return process ID. To obtain the process ID, you can use
system 'sleep 10 &' p $? #=> 8050
But unfortunatelly the
$? is not the processs ID of
sh -c sleep 10. There is a cussion. You cannot obtain the process ID of
One more problem: the notation is available only in UNIX based platform.
system() without shell
system 'sleep 10' uses shell but
system 'sleep', '10' doesn't use shell. Separate the arguments. But
system 'sleep', '10', '&' is not available.
'&' feature, how about using Ruby's asynchronous features? Thread is the easiest way of that.
t = Thread.start do system 'sleep', '10' end t.kill
Looks good, but it doesn't work. Thread certainly will stop, but the external command booted by the thread will still alive.
How about using another way of booting an external command? There is
exec(), which roughly means the combination of
system 'ls' exit
So you think that the following code will work well.
t = Thread.start do exec 'sleep', '10' end t.kill
Unfortunatelly it doesn't work. You cannot use
exec() in a child thread.
Look for another way of supporting asynchronous feature on Ruby.
fork() copies the Ruby process itself.
pid = fork do exec 'sleep', '10' end Process.kill pid
fork() is awesome!
But there is a bad news.
Thread works on all platforms, but
fork works on only some platforms. I'm sorry Windows users and NetBSD users.
spawn = fork + exec.
spawn() works on all platforms! It's perfect! But... ruby 1.8 doesn't have
- Ruby 1.9 + UNIX: Use
exec, or use
- Ruby 1.8 + UNIX: Use
- Ruby 1.9 + Windows: Use
- Ruby 1.8 + Windows: Use other OS, other Ruby, or consider using this library