- #!/usr/bin/env ruby
- #
- # Wrapping script to launch both nginx and unicorn for Helix Web Services.
- #
- require 'hws_settings'
- require 'socket'
- require 'fileutils'
- #=============================================================================
- # Primary Helper Methods
- #=============================================================================
- # If the nginx server is not running, start it.
- #
- # Files created /var/run/perforce/helix-web-services/:
- #
- # - nginx.pid
- # - nginx.conf
- #
- def start_nginx
- create_nginx_config
- spawn_nginx
- end
- # If the unicorn server is not running, start it.
- #
- # This should block until unicorn is ready to respond.
- def start_unicorn
- create_unicorn_config
- spawn_unicorn
- end
- def stop_nginx
- if process_running?(nginx_pid)
- Process.kill('QUIT', nginx_pid)
- end
- end
- def stop_unicorn
- if process_running?(unicorn_pid)
- Process.kill('QUIT', unicorn_pid)
- end
- end
- # This should let you know what processes we're running nginx and unicorn at.
- # Or if they're shut down.
- def check_status
- if process_running?(nginx_pid)
- puts 'nginx running'
- else
- puts 'nginx not running'
- end
- if process_running?(unicorn_pid)
- puts 'unicorn running'
- else
- puts 'unicorn not running'
- end
- end
- # This will pause until the local nginx server is capable of returning
- # responses from the web application.
- def wait_for_response
- attempts = 150 # wait up to 15 seconds
- connected = false
- while !(connected = connect_to_server(HWSSettings.system.NGINX_PORT))
- sleep(0.1)
- end
- connected
- end
- def connect_to_server(port)
- begin
- s = TCPSocket.new 'localhost', port
- s.close
- return true
- rescue Exception => e
- return false
- end
- end
- #=============================================================================
- # Secondary Helper Methods
- #=============================================================================
- # These are methods used by the primary methods but aren't really the main API
- def spawn_nginx
- return if process_running?(nginx_pid)
- # Note: this variation of Process.spawn() does *not* execute within a
- # standard shell
- nginx_pid = Process.spawn(HWSSettings.system.NGINX_COMMAND,
- '-c',
- HWSSettings.system.NGINX_CONFIG_PATH)
- # Note: We set the pid file via config, so this PID may not be the master
- # process ID
- Process.detach(nginx_pid)
- end
- def spawn_unicorn
- # Note: this launch PID is *not* the unicorn master pid, which is set in
- # the config file process.
- launch_pid = Process.spawn(HWSSettings.system.UNICORN_COMMAND,
- '-D',
- '-c',
- HWSSettings.system.UNICORN_CONFIG_PATH,
- HWSSettings.system.RACKUP_CONFIG)
- Process.detach(launch_pid)
- end
- def nginx_pid
- read_pid(nginx_pid_file)
- end
- def nginx_pid_file
- File.join(HWSSettings.system.RUN_DIR, 'nginx.pid')
- end
- def unicorn_pid
- read_pid(unicorn_pid_file)
- end
- def read_pid(path)
- if File.exist?(path)
- IO.read(path).strip.to_i
- else
- nil
- end
- end
- def unicorn_pid_file
- File.join(HWSSettings.system.RUN_DIR, 'unicorn.pid')
- end
- # Note: sending signal 0 basically doesn't do anything, but validates that the
- # process exists (and we have access to it)
- def process_running?(pid)
- return false if pid.nil?
- begin
- Process.kill(0, pid)
- true
- rescue Errno::ESRCH
- false
- end
- end
- #=============================================================================
- # Local Config File Generation
- #=============================================================================
- # Both Unicorn and Nginx configuration are tuned for HWS only usage. We do
- # expose some parameters through the system configuration file.
- def create_nginx_config
- IO.write(HWSSettings.system.NGINX_CONFIG_PATH, <<-END.gsub(/^[ ]{4}/, '')
- pid #{nginx_pid_file};
- error_log #{HWSSettings.system.LOG_DIR}/nginx-error.log info;
- worker_processes 10;
- events {
- worker_connections #{HWSSettings.system.NGINX_WORKER_CONNECTIONS};
- }
- http {
- log_format main '$remote_addr - $remote_user [$time_local] $status '
- '"$request" $body_bytes_sent "$http_referer" '
- '"$http_user_agent" "$http_x_forwarded_for"';
- access_log #{HWSSettings.system.LOG_DIR}/nginx-access.log;
- upstream unicorn_server {
- server #{HWSSettings.system.UNICORN_CONNECTION};
- }
- server {
- listen #{HWSSettings.system.NGINX_PORT};
- #{nginx_ssl_settings}
- location / {
- proxy_pass http://unicorn_server;
- }
- }
- }
- END
- )
- end
- def nginx_ssl_settings
- if HWSSettings.system.ENABLE_HTTPS
- <<-END.gsub(/^[ ]{4}/, '')
- ssl on;
- ssl_certificate #{HWSSettings.system.SSL_CERTIFICATE_PATH};
- ssl_certificate_key #{HWSSettings.system.SSL_CERTIFICATE_KEY_PATH};
- END
- else
- ''
- end
- end
- def create_unicorn_config
- IO.write(HWSSettings.system.UNICORN_CONFIG_PATH, <<-END.gsub(/^[ ]{4}/, '')
- listen "#{HWSSettings.system.UNICORN_CONNECTION}"
- pid "#{unicorn_pid_file}"
- stdout_path "#{HWSSettings.system.LOG_DIR}/unicorn.log"
- stderr_path "#{HWSSettings.system.LOG_DIR}/unicorn.log"
- timeout #{HWSSettings.system.UNICORN_TIMEOUT}
- user "#{HWSSettings.system.SYSTEM_USER}"
- worker_processes #{HWSSettings.system.UNICORN_WORKER_PROCESSES}
- END
- )
- FileUtils.chown(HWSSettings.system.SYSTEM_USER,
- HWSSettings.system.SYSTEM_GROUP,
- HWSSettings.system.UNICORN_CONFIG_PATH
- )
- end
- #=============================================================================
- # Parse the command line and start
- #=============================================================================
- require 'thor'
- class CLI < Thor
- desc 'hws_launch start', 'Launch both nginx and unicorn'
- def start
- start_unicorn
- start_nginx
- wait_for_response
- end
- desc 'hws_launch stop', 'Stop nginx and unicorn'
- def stop
- stop_unicorn
- stop_nginx
- end
- desc 'hws_launch restart', 'Restart nginx and unicorn'
- def restart
- stop
- start
- end
- desc 'hws_launch status', 'Report status of nginx and unicorn'
- def status
- check_status
- end
- end
- CLI.start(ARGV)
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#2 | 16318 | Doug Scheirer | merge from main | 9 years ago | |
#1 | 16289 | Doug Scheirer | merge from main | 9 years ago | |
//guest/perforce_software/helix-web-services/main/source/helix_web_services/bin/hws_launch | |||||
#1 | 16285 | tjuricek | Deploy/install improvements - Include nginx in Omnibus distribution, do not conflict wit...h system nginx install - Use old-school sysvinit scripts - Create 'hws_launch' wrapper to initiate nginx and unicorn, which also reads system config file for settings « |
9 years ago |