forever 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
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