#!/usr/bin/env ruby require 'thor' require 'hirb' require 'json' require File.expand_path('../lib/srv_manager', File.dirname(__FILE__)) module SrvManager class CLI < Thor desc 'version', 'Show SrvManager version number' def version puts SrvManager::VERSION end option :dir, aliases: :d option :processes, aliases: :p, type: :numeric option :auto, type: :boolean option :rvm, type: :boolean option :env, type: :hash desc 'add ', 'Add new service' def add(name, command) Context.scoped do |ctx| ctx.services << Service.new(name, command, options) end end desc 'rm ', 'Remove service' def rm(name) Context.scoped do |ctx| service = find_service name, ctx if service service.stop ctx.services.delete service end end end desc 'start ', 'Start service' def start(name) Context.scoped(safe: true) do |ctx| service = find_service name, ctx service.start end end desc 'stop ', 'Stop service' def stop(name) Context.scoped(safe: true) do |ctx| service = find_service name, ctx service.stop end end desc 'restart ', 'Restart service' def restart(name) Context.scoped(safe: true) do |ctx| service = find_service name, ctx service.restart end end desc 'ps ', 'Show service processes' def ps(name) Context.scoped do |ctx| service = find_service name, ctx return if service.processes.empty? processes = service.processes.map do |process| { PID: process.id, Status: process.alive? ? 'Running' : 'Killed' } end puts Hirb::Helpers::AutoTable.render(processes, unicode: true, fields: [:PID, :Status]) end end option :start, type: :boolean option :stop, type: :boolean desc 'monitor', 'Start service monitor' def monitor Context.scoped do |ctx| if options[:stop] if ctx.monitor.alive? ctx.monitor.stop puts 'Monitor stoped' end elsif options[:start] if ctx.monitor.alive? puts "Monitor already started (PID: #{ctx.monitor.pid})" else ctx.monitor.start puts "Monitor started (PID: #{ctx.monitor.pid})" end else if ctx.monitor.alive? puts "Monitor running (PID: #{ctx.monitor.pid})" else puts 'Monitor not running' end end end end desc 'logs', 'Show logs' def logs puts `tail #{LOG_FILE}` end option :dir, type: :boolean, aliases: :d option :env, type: :boolean, aliases: :e desc 'ls', 'List configured services' def ls Context.scoped do |ctx| return if ctx.services.empty? services = ctx.services.sort_by(&:name).map do |service| { Service: service.name, Status: service.started? ? 'Started' : 'Stoped', Alive: service.processes.select(&:alive?).count, Dead: service.processes.reject(&:alive?).count, Command: service.command.text, Env: service.command.env.map{|k,v| "#{k}=#{v}"}, Dir: service.command.dir } end fields = [:Service, :Status, :Alive, :Dead, :Command] fields << :Env if options[:env] fields << :Dir if options[:dir] puts Hirb::Helpers::AutoTable.render(services, unicode: true, fields: fields) end end desc 'clean', 'Remove all services' def clean Context.scoped(safe: true) do |ctx| ctx.clean end end desc 'dump', 'Dump service configuration' def dump Context.scoped do |ctx| puts JSON.pretty_generate(ctx.to_hash) end end desc 'load', 'Load service configuration' def load(filename) json = JSON.parse(File.read(filename)) Context.scoped do |ctx| ctx.load json end end private def find_service(name, context) service = context.services.detect { |s| s.name == name } unless service puts "Service not found: #{name}" exit 1 end service end end end SrvManager::CLI.start