3

I have a requirement to start and stop servers within rake tasks. Each server gets a specific process id. I have created a number of tasks that start and stop each server (note that the servers may not always be unique and will start on different ports, so its unreasonable that I grep/search for processes by name and kill those). I have been unsuccessful in programmatically maintaining state between tasks (either by environment variables, class methods, instance methods, local or global variables). It is also not possible for me (at least with my current setup) to use rake task dependencies, for example:

Rakefile.rb

class Proc
    attr_accessor :process_id

    def start_server(port=4444)
        @process_id = spawn("node application -p #{port}", :chdir => "server_path")
    end
end

@proc = Proc.new

task :start_server_one do |t, args|
    @proc.start_server()
    p @proc.process_id
end

task :stop_server_one => :start_server_one do
    begin
        Process.kill(9, @proc.process_id)
    rescue => e
        p e
    end
end

On the command line I want to be able to run tasks at any given time, so I dont want the execution of one task to block any other tasks (hence the reason why Ive chosen spawn process). Unfortunately, this approach does not work.

On getting no luck with managing state between tasks my end solution was to use yaml files to serialise the process ids and remove them from the file as soon as I have killed the process successfully, similar to the following:

Initial yaml_file.yml contents:

---
server_one_process_id: 
server_two_process_id:
server_three_process_id:

Rakefile contents:

require 'yaml'
yaml_file_path = 'yaml_file_path.yml'
all_yaml_contents = YAML::load_file(yaml_file_path)

class Proc
    attr_accessor :process_id

    def start_server(port=4444)
        @process_id = spawn("node application -p #{port}", :chdir => "server_path")
    end
end

@proc = Proc.new

task :start_server_one do |t, args|
    @proc.start_server()
    p 'server started!'
    all_yaml_contents['server_one_process_id'] = @proc.process_id
    File.open(yaml_file_path, 'w') {|f| f.write all_yaml_contents.to_yaml}
    p @proc.process_id
end

task :stop_server_one do
    all_yaml_contents_updated = YAML::load_file(yaml_file_path)
    p "server process id: #{all_yaml_contents_updated['server_one_process_id']}"
    Process.kill(9, all_yaml_contents_updated['server_one_process_id'])
    all_yaml_contents_updated['server_one_process_id'] = nil
    File.open(yaml_file_path, 'w') {|f| f.write all_yaml_contents_updated.to_yaml}
    sleep 5
    p 'server killed!'
end

Now I can run the tasks independently, for example on command line I can run:

rake start_server_one
    #=> 'server started!'
    #=> 12892

rake stop_server_one
    #=> server process id: 12892
    #=> server killed!

and be sure that the tasks execute and the server starts and stops as I expected as the yaml file is now updated with the process id for the given server.

However, to me at least, it seems as though this is not the best approach and I really want a purely programmatic way of managing state between tasks; or even a suitable library that can help me achieve this.

aDiT
  • 95
  • 1
  • 5
  • 2
    Did you consider [`pid` files](https://stackoverflow.com/questions/8296170/what-is-a-pid-file-and-what-does-it-contain)? – spickermann Aug 11 '17 at 15:14
  • Looks like I will use a variation of this. Will use a yaml file as theres may services that need to start and I dont want to create many pid files. Thanks for the idea though it sparked my solution. – aDiT Aug 16 '17 at 10:57

0 Answers0