Search code examples
windowsrubyexecreloadrestart

Can a standalone ruby script (windows and mac) reload and restart itself?


I have a master-workers architecture where the number of workers is growing on a weekly basis. I can no longer be expected to ssh or remote console into each machine to kill the worker, do a source control sync, and restart. I would like to be able to have the master place a message out on the network that tells each machine to sync and restart.

That's where I hit a roadblock. If I were using any sane platform, I could just do:

exec('ruby', __FILE__)

...and be done. However, I did the following test:

p Process.pid
sleep 1
exec('ruby', __FILE__)

...and on Windows, I get one ruby instance for each call to exec. None of them die until I hit ^C on the window in question. On every platform I tried this on, it is executing the new version of the file each time, which I have verified this by making simple edits to the test script while the test marched along.

The reason I'm printing the pid is to double-check the behavior I'm seeing. On windows, I am getting a different pid with each execution - which I would expect, considering that I am seeing a new process in the task manager for each run. The mac is behaving correctly: the pid is the same for every system call and I have verified with dtrace that each run is trigging a call to the execve syscall.

So, in short, is there a way to get a windows ruby script to restart its execution so it will be running any code - including itself - that has changed during its execution? Please note that this is not a rails application, though it does use activerecord.


Solution

  • After trying a number of solutions (including the one submitted by Byron Whitlock, which ultimately put me onto the path to a satisfactory end) I settled upon:

    IO.popen("start cmd /C ruby.exe #{$0} #{ARGV.join(' ')}")
    sleep 5
    

    I found that if I didn't sleep at all after the popen, and just exited, the spawn would frequently (>50% of the time) fail. This is not cross-platform obviously, so in order to have the same behavior on the mac:

    IO.popen("xterm -e \"ruby blah blah blah\"&")