forever 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.md CHANGED
@@ -1,9 +1,13 @@
1
- # Forever
1
+ # Ruby Forever
2
2
 
3
3
  Small daemon framework **for ruby**, with logging, error handler watcher and much more.
4
4
 
5
5
  The idea of the name and some concepts was taken by [forever for node.js](https://raw.github.com/indexzero/forever) written by Charlie Robbins.
6
6
 
7
+ Please don't consider this gem as a port because is not.
8
+
9
+ The executable name it's called ```foreverb``` to prevent collisions.
10
+
7
11
  ## Why?
8
12
 
9
13
  There are a lot of alternatives, one of the best is [resque](https://github.com/defunkt/resque), so why another daemons framework?
@@ -100,7 +104,7 @@ $ bin/foo stop
100
104
  List daemons:
101
105
 
102
106
  ``` sh
103
- $ forever list
107
+ $ foreverb list
104
108
  PID RSS CPU CMD
105
109
  19838 32512 1.6 Forever: bin/githubwatcher
106
110
  ```
@@ -108,7 +112,7 @@ PID RSS CPU CMD
108
112
  Stop daemon(s):
109
113
 
110
114
  ``` sh
111
- $ forever stop foo
115
+ $ foreverb stop foo
112
116
  Do you want really stop Forever: bin/foo with pid 19538? y
113
117
  Killing process Forever: bin/foo with pid 19538...
114
118
  ```
@@ -1,34 +1,2 @@
1
1
  #!/usr/bin/ruby
2
- require 'rubygems' unless defined?(Gem)
3
- require File.expand_path('../../lib/forever/version.rb', __FILE__)
4
- require 'thor'
5
-
6
- class CLI < Thor
7
- desc "list", "List Forever daemons"
8
- def list
9
- say "PID\tRSS\tCPU\tCMD", :green
10
- puts daemons.join("\n")
11
- end
12
-
13
- desc "stop [DAEMON]", "Stop a specified daemon"
14
- def stop(daemon)
15
- found = daemons.find_all { |d| d=~/#{daemon}/i }
16
- say "Daemon(s) matching '#{daemon}' not found", :red if found.empty?
17
- found.each do |daemon|
18
- daemon = daemon.split("\t")
19
- if yes? "Do you want really stop #{daemon[-1]} with pid #{daemon[0]}?"
20
- say "Killing process #{daemon[-1]} with pid #{daemon[0]}...", :green
21
- result = `kill #{daemon[0]}`.strip
22
- say result, :red if result != ""
23
- end
24
- end
25
- end
26
-
27
- private
28
- def daemons
29
- `ps axo pid,rss,pcpu,command | grep -vE "^USER|grep" | grep Forever: | awk '{print $1"\t"$2"\t"$3"\t"$4" "$5" "$6}'`.chomp.split("\n")
30
- end
31
- end
32
-
33
- ARGV << "-h" if ARGV.empty?
34
- CLI.start(ARGV)
2
+ warn "Use foreverb, this one is deprecated"
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/ruby
2
+ require 'rubygems' unless defined?(Gem)
3
+ require File.expand_path('../../lib/forever/version.rb', __FILE__)
4
+ require 'thor'
5
+
6
+ class CLI < Thor
7
+ desc "list", "List Forever daemons"
8
+ def list
9
+ say "PID\tRSS\tCPU\tCMD", :green
10
+ puts daemons.join("\n")
11
+ end
12
+
13
+ desc "stop [DAEMON]", "Stop a specified daemon"
14
+ def stop(daemon)
15
+ found = daemons.find_all { |d| d=~/#{daemon}/i }
16
+ say "Daemon(s) matching '#{daemon}' not found", :red if found.empty?
17
+ found.each do |daemon|
18
+ daemon = daemon.split("\t")
19
+ if yes? "Do you want really stop #{daemon[-1]} with pid #{daemon[0]}?"
20
+ say "Killing process #{daemon[-1]} with pid #{daemon[0]}...", :green
21
+ result = `kill #{daemon[0]}`.strip
22
+ say result, :red if result != ""
23
+ end
24
+ end
25
+ end
26
+
27
+ private
28
+ def daemons
29
+ `ps axo pid,rss,pcpu,command | grep -vE "^USER|grep" | grep Forever: | awk '{print $1"\t"$2"\t"$3"\t"$4" "$5" "$6}'`.chomp.split("\n")
30
+ end
31
+ end
32
+
33
+ ARGV << "-h" if ARGV.empty?
34
+ CLI.start(ARGV)
@@ -5,12 +5,137 @@ module Forever
5
5
  def initialize(options={}, &block)
6
6
  options.each { |k,v| send(k, v) }
7
7
 
8
+ instance_eval(&block)
9
+
8
10
  Dir.chdir(dir) if exists?(dir)
9
11
  Dir.mkdir(File.dirname(log)) if log && !File.exist?(File.dirname(log))
10
12
  Dir.mkdir(File.dirname(pid)) if pid && !File.exist?(File.dirname(pid))
11
13
 
14
+ stop!
15
+
16
+ return if ARGV[0] == "stop" || on_ready.nil?
17
+
18
+ fork do
19
+ $0 = "Forever: #{$0}"
20
+ puts "=> Process demonized with pid #{Process.pid}"
21
+
22
+ %w(INT TERM KILL).each { |signal| trap(signal) { stop! } }
23
+
24
+ File.open(pid, "w") { |f| f.write(Process.pid.to_s) } if pid
25
+
26
+ stream = log ? File.new(log, "w") : File.open('/dev/null', 'w')
27
+ stream.sync = true
28
+
29
+ STDOUT.reopen(stream)
30
+ STDERR.reopen(STDOUT)
31
+
32
+ begin
33
+ on_ready.call
34
+ rescue Exception => e
35
+ Thread.list.reject { |t| t==Thread.current }.map(&:kill)
36
+ on_error[e] if on_error
37
+ stream.print "\n\n%s\n %s\n\n" % [e.message, e.backtrace.join("\n ")]
38
+ sleep 30
39
+ retry
40
+ end
41
+ end
42
+ end
43
+
44
+ ##
45
+ # Caller file
46
+ #
47
+ def file(value=nil)
48
+ value ? @_file = value : @_file
49
+ end
50
+
51
+ ##
52
+ # Base working Directory
53
+ #
54
+ def dir(value=nil)
55
+ value ? @_dir = value : @_dir
56
+ end
57
+
58
+ ##
59
+ # File were we redirect STOUT and STDERR, can be false.
60
+ #
61
+ # Default: dir + 'log/[process_name].log'
62
+ #
63
+ def log(value=nil)
64
+ @_log ||= File.join(dir, "log/#{File.basename(file)}.log") if exists?(dir, file)
65
+ value ? @_log = value : @_log
66
+ end
67
+
68
+ ##
69
+ # File were we store pid
70
+ #
71
+ # Default: dir + 'tmp/[process_name].pid'
72
+ #
73
+ def pid(value=nil)
74
+ @_pid ||= File.join(dir, "tmp/#{File.basename(file)}.pid") if exists?(dir, file)
75
+ value ? @_pid = value : @_pid
76
+ end
77
+
78
+ ##
79
+ # Search if there is a running process and stop it
80
+ #
81
+ def stop!(kill=true)
82
+ if exists?(pid)
83
+ _pid = File.read(pid).to_i
84
+ puts "=> Found pid #{_pid}..."
85
+ FileUtils.rm_f(pid)
86
+ begin
87
+ puts "=> Killing process #{_pid}..."
88
+ Process.kill(:KILL, _pid)
89
+ rescue Errno::ESRCH => e
90
+ puts "=> #{e.message}"
91
+ end
92
+ else
93
+ puts "=> Pid not found, process seems don't exist!"
94
+ end
95
+ end
96
+
97
+ ##
98
+ # Callback raised when an error occour
99
+ #
100
+ def on_error(&block)
101
+ block_given? ? @_on_error = block : @_on_error
102
+ end
103
+
104
+ ##
105
+ # Callback to fire when the daemon start
106
+ #
107
+ def on_ready(&block)
108
+ block_given? ? @_on_error = block : @_on_error
109
+ end
110
+
111
+ def to_s
112
+ "#<Forever dir:#{dir}, file:#{file}, log:#{log}, pid:#{pid}>"
113
+ end
114
+ alias :inspect :to_s
115
+
116
+ def config
117
+ { :dir => dir, :file => file, :log => log, :pid => pid }.to_yaml
118
+ end
119
+ alias :to_yaml :config
120
+
121
+ private
122
+ def exists?(*values)
123
+ values.all? { |value| value && File.exist?(value) }
124
+ end
125
+ end # Base
126
+ end # Foreverrequire 'fileutils'
127
+
128
+ module Forever
129
+ class Base
130
+ def initialize(options={}, &block)
131
+ options.each { |k,v| send(k, v) }
132
+
12
133
  instance_eval(&block)
13
134
 
135
+ Dir.chdir(dir) if exists?(dir)
136
+ Dir.mkdir(File.dirname(log)) if log && !File.exist?(File.dirname(log))
137
+ Dir.mkdir(File.dirname(pid)) if pid && !File.exist?(File.dirname(pid))
138
+
14
139
  stop!
15
140
 
16
141
  return if ARGV[0] == "stop" || on_ready.nil?
@@ -1,3 +1,3 @@
1
1
  module Forever
2
- VERSION = "0.1.1"
2
+ VERSION = "0.1.2"
3
3
  end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 1
8
- - 1
9
- version: 0.1.1
8
+ - 2
9
+ version: 0.1.2
10
10
  platform: ruby
11
11
  authors:
12
12
  - DAddYE
@@ -36,6 +36,7 @@ email:
36
36
  - d.dagostino@lipsiasoft.com
37
37
  executables:
38
38
  - forever
39
+ - foreverb
39
40
  extensions: []
40
41
 
41
42
  extra_rdoc_files: []
@@ -46,6 +47,7 @@ files:
46
47
  - README.md
47
48
  - Rakefile
48
49
  - bin/forever
50
+ - bin/foreverb
49
51
  - forever.gemspec
50
52
  - lib/forever.rb
51
53
  - lib/forever/base.rb