KeeperPat-feedupdater 0.2.6

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.
@@ -0,0 +1,265 @@
1
+ #--
2
+ ###############################################################################
3
+ # daemonize.rb is a slightly modified version of daemonize.rb was #
4
+ # from the Daemonize Library written by Travis Whitton #
5
+ # for details, read the notice below #
6
+ ###############################################################################
7
+ #++
8
+ #
9
+ #
10
+ # =Daemonize Library
11
+ #
12
+ # February. 4, 2005 Travis Whitton <whitton@atlantic.net>
13
+ #
14
+ # Daemonize allows you to easily modify any existing Ruby program to run
15
+ # as a daemon. See README.rdoc for more details.
16
+ #
17
+ # == How to install
18
+ # 1. su to root
19
+ # 2. ruby install.rb
20
+ # build the docs if you want to
21
+ # 3. rdoc --main README.rdoc daemonize.rb README.rdoc
22
+ #
23
+ # == Copying
24
+ # The Daemonize extension module is copywrited free software by Travis Whitton
25
+ # <whitton@atlantic.net>. You can redistribute it under the terms specified in
26
+ # the COPYING file of the Ruby distribution.
27
+ #
28
+ # == WARRANTY
29
+ # THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
30
+ # IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
31
+ # WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
32
+ # PURPOSE.
33
+ #
34
+ #
35
+ # ----
36
+ #
37
+ # == Purpose
38
+ #
39
+ # Daemonize is a module derived from Perl's Proc::Daemon module. This module
40
+ # allows you to easily modify any existing Ruby program to run as a daemon.
41
+ # A daemon is a process that runs in the background with no controlling terminal.
42
+ # Generally servers (like FTP and HTTP servers) run as daemon processes.
43
+ # Note, do not make the mistake that a daemon == server. Converting a program
44
+ # to a daemon by hand is a relatively simple process; however, this module will
45
+ # save you the effort of repeatedly looking up the procedure, and it will also
46
+ # insure that your programs are daemonized in the safest and most corrects
47
+ # fashion possible.
48
+ #
49
+ # == Procedure
50
+ #
51
+ # The Daemonize module does the following:
52
+ #
53
+ # Forks a child and exits the parent process.
54
+ #
55
+ # Becomes a session leader (which detaches the program from
56
+ # the controlling terminal).
57
+ #
58
+ # Forks another child process and exits first child. This prevents
59
+ # the potential of acquiring a controlling terminal.
60
+ #
61
+ # Changes the current working directory to "/".
62
+ #
63
+ # Clears the file creation mask.
64
+ #
65
+ # Closes file descriptors.
66
+ #
67
+ # == Example usage
68
+ #
69
+ # Using the Daemonize module is extremely simple:
70
+ #
71
+ # require 'daemonize'
72
+ #
73
+ # class TestDaemon
74
+ # include Daemonize
75
+ #
76
+ # def initialize
77
+ # daemonize()
78
+ # loop do
79
+ # # do some work here
80
+ # end
81
+ # end
82
+ # end
83
+ #
84
+ # == Credits
85
+ #
86
+ # Daemonize was written by Travis Whitton and is based on Perl's
87
+ # Proc::Daemonize, which was written by Earl Hood. The above documentation
88
+ # is also partially borrowed from the Proc::Daemonize POD documentation.
89
+
90
+
91
+
92
+ module Daemonize
93
+ VERSION = "0.1.1m"
94
+
95
+ # Try to fork if at all possible retrying every 5 sec if the
96
+ # maximum process limit for the system has been reached
97
+ def safefork
98
+ tryagain = true
99
+
100
+ while tryagain
101
+ tryagain = false
102
+ begin
103
+ if pid = fork
104
+ return pid
105
+ end
106
+ rescue Errno::EWOULDBLOCK
107
+ sleep 5
108
+ tryagain = true
109
+ end
110
+ end
111
+ end
112
+ module_function :safefork
113
+
114
+
115
+ def simulate(logfile_name = nil)
116
+ # NOTE: STDOUT and STDERR will not be redirected to the logfile!
117
+
118
+ Dir.chdir "/" # Release old working directory
119
+ File.umask 0000 # Insure sensible umask
120
+
121
+ # Make sure all file descriptors are closed
122
+ ObjectSpace.each_object(IO) do |io|
123
+ unless [STDIN, STDOUT, STDERR].include?(io)
124
+ begin
125
+ unless io.closed?
126
+ io.close
127
+ end
128
+ rescue ::Exception
129
+ end
130
+ end
131
+ end
132
+
133
+ # Free file descriptors and
134
+ # point them somewhere sensible
135
+ # STDOUT/STDERR should go to a logfile
136
+
137
+ STDIN.reopen "/dev/null" rescue nil
138
+ end
139
+ module_function :simulate
140
+
141
+
142
+ def call_as_daemon(block, logfile_name = nil, oldmode = 0)
143
+ rd, wr = IO.pipe
144
+
145
+ if tmppid = safefork
146
+ # parent
147
+ wr.close
148
+ pid = rd.read.to_i
149
+ rd.close
150
+
151
+ Process.waitpid(tmppid)
152
+
153
+ return pid
154
+ else
155
+ rd.close
156
+
157
+ # Detach from the controlling terminal
158
+ unless sess_id = Process.setsid
159
+ raise Daemons.RuntimeException.new('cannot detach from controlling terminal')
160
+ end
161
+
162
+ # Prevent the possibility of acquiring a controlling terminal
163
+ if oldmode.zero?
164
+ trap 'SIGHUP', 'IGNORE'
165
+ exit if pid = safefork
166
+ end
167
+
168
+ wr.write Process.pid
169
+ wr.close
170
+
171
+ Dir.chdir "/" # Release old working directory
172
+ File.umask 0000 # Insure sensible umask
173
+
174
+ # Make sure all file descriptors are closed
175
+ ObjectSpace.each_object(IO) do |io|
176
+ unless [STDIN, STDOUT, STDERR].include?(io)
177
+ begin
178
+ unless io.closed?
179
+ io.close
180
+ end
181
+ rescue ::Exception
182
+ end
183
+ end
184
+ end
185
+
186
+ # Free file descriptors and
187
+ # point them somewhere sensible
188
+ # STDOUT/STDERR should go to a logfile
189
+
190
+ STDIN.reopen "/dev/null" rescue nil
191
+
192
+ if logfile_name
193
+ begin
194
+ STDOUT.reopen logfile_name, "a"
195
+ rescue ::Exception
196
+ STDOUT.reopen "/dev/null" rescue nil
197
+ end
198
+ else
199
+ STDOUT.reopen "/dev/null" rescue nil
200
+ end
201
+
202
+ STDERR.reopen STDOUT rescue nil
203
+
204
+ block.call
205
+
206
+ exit
207
+ end
208
+ end
209
+ module_function :call_as_daemon
210
+
211
+
212
+ # This method causes the current running process to become a daemon
213
+ def daemonize(logfile_name = nil, oldmode=0)
214
+ srand # Split rand streams between spawning and daemonized process
215
+ safefork and exit # Fork and exit from the parent
216
+
217
+ # Detach from the controlling terminal
218
+ unless sess_id = Process.setsid
219
+ raise Daemons.RuntimeException.new('cannot detach from controlling terminal')
220
+ end
221
+
222
+ # Prevent the possibility of acquiring a controlling terminal
223
+ if oldmode.zero?
224
+ trap 'SIGHUP', 'IGNORE'
225
+ exit if pid = safefork
226
+ end
227
+
228
+ Dir.chdir "/" # Release old working directory
229
+ File.umask 0000 # Insure sensible umask
230
+
231
+ # Make sure all file descriptors are closed
232
+ ObjectSpace.each_object(IO) do |io|
233
+ unless [STDIN, STDOUT, STDERR].include?(io)
234
+ begin
235
+ unless io.closed?
236
+ io.close
237
+ end
238
+ rescue ::Exception
239
+ end
240
+ end
241
+ end
242
+
243
+ # Free file descriptors and
244
+ # point them somewhere sensible
245
+ # STDOUT/STDERR should go to a logfile
246
+
247
+ STDIN.reopen "/dev/null" rescue nil
248
+
249
+ if logfile_name
250
+ begin
251
+ STDOUT.reopen logfile_name, "a"
252
+ rescue ::Exception
253
+ STDOUT.reopen "/dev/null" rescue nil
254
+ end
255
+ else
256
+ STDOUT.reopen "/dev/null" rescue nil
257
+ end
258
+
259
+ STDERR.reopen STDOUT rescue nil
260
+
261
+ return oldmode ? sess_id : 0 # Return value is mostly irrelevant
262
+ end
263
+ module_function :daemonize
264
+
265
+ end
@@ -0,0 +1,28 @@
1
+
2
+ module Daemons
3
+
4
+ class Exception < ::RuntimeError
5
+ end
6
+
7
+ class RuntimeException < Exception
8
+ end
9
+
10
+ class CmdException < Exception
11
+ end
12
+
13
+ class Error < Exception
14
+ end
15
+
16
+ class SystemError < Error
17
+
18
+ attr_reader :system_error
19
+
20
+ def initialize(msg, system_error)
21
+ super(msg)
22
+
23
+ @system_error = system_error
24
+ end
25
+
26
+ end
27
+
28
+ end
@@ -0,0 +1,126 @@
1
+
2
+ module Daemons
3
+
4
+ require 'daemons/daemonize'
5
+
6
+ class Monitor
7
+
8
+ def self.find(dir, app_name)
9
+ pid = PidFile.find_files(dir, app_name)[0]
10
+
11
+ if pid
12
+ pid = PidFile.existing(pid)
13
+
14
+ unless PidFile.running?(pid.pid)
15
+ pid.cleanup rescue nil
16
+ return
17
+ end
18
+
19
+ monitor = self.allocate
20
+
21
+ monitor.instance_variable_set(:@pid, pid)
22
+
23
+ return monitor
24
+ end
25
+
26
+ return nil
27
+ end
28
+
29
+
30
+ def initialize(an_app)
31
+ if an_app.pidfile_dir
32
+ @pid = PidFile.new(an_app.pidfile_dir, an_app.group.app_name + '_monitor', false)
33
+ else
34
+ @pid = PidMem.new
35
+ end
36
+ end
37
+
38
+ def watch(applications)
39
+ sleep(30)
40
+
41
+ loop do
42
+ applications.each {|a|
43
+ sleep(10)
44
+
45
+ unless a.running?
46
+ a.zap!
47
+
48
+ Process.detach(fork { a.start })
49
+
50
+ sleep(10)
51
+ end
52
+ }
53
+
54
+ sleep(30)
55
+ end
56
+ end
57
+ private :watch
58
+
59
+
60
+ def start_with_pidfile(applications)
61
+ fork do
62
+ Daemonize.daemonize
63
+
64
+ begin
65
+ @pid.pid = Process.pid
66
+
67
+ # at_exit {
68
+ # @pid.cleanup rescue nil
69
+ # }
70
+
71
+ # This part is needed to remove the pid-file if the application is killed by
72
+ # daemons or manually by the user.
73
+ # Note that the applications is not supposed to overwrite the signal handler for
74
+ # 'TERM'.
75
+ #
76
+ # trap('TERM') {
77
+ # @pid.cleanup rescue nil
78
+ # exit
79
+ # }
80
+
81
+ watch(applications)
82
+ rescue ::Exception => e
83
+ begin
84
+ File.open(File.join(@pid.dir, @pid.progname + '.log'), 'a') {|f|
85
+ f.puts Time.now
86
+ f.puts e
87
+ f.puts e.backtrace.inspect
88
+ }
89
+ ensure
90
+ @pid.cleanup rescue nil
91
+ exit!
92
+ end
93
+ end
94
+ end
95
+ end
96
+ private :start_with_pidfile
97
+
98
+ def start_without_pidfile(applications)
99
+ Thread.new { watch(applications) }
100
+ end
101
+ private :start_without_pidfile
102
+
103
+
104
+
105
+ def start(applications)
106
+ return if applications.empty?
107
+
108
+ if @pid.kind_of?(PidFile)
109
+ start_with_pidfile(applications)
110
+ else
111
+ start_without_pidfile(applications)
112
+ end
113
+ end
114
+
115
+
116
+ def stop
117
+ Process.kill('TERM', @pid.pid) rescue nil
118
+
119
+ # We try to remove the pid-files by ourselves, in case the application
120
+ # didn't clean it up.
121
+ @pid.cleanup rescue nil
122
+ end
123
+
124
+ end
125
+
126
+ end
@@ -0,0 +1,61 @@
1
+
2
+ module Daemons
3
+
4
+ class Pid
5
+
6
+ def Pid.running?(pid, additional = nil)
7
+ output = `ps ax`
8
+ return (/#{pid} / =~ output and (additional ? /#{additional}/ =~ output : true))
9
+ end
10
+
11
+
12
+ # Returns the directory that should be used to write the pid file to
13
+ # depending on the given mode.
14
+ #
15
+ # Some modes may require an additionaly hint, others may determine
16
+ # the directory automatically.
17
+ #
18
+ # If no valid directory is found, returns nil.
19
+ #
20
+ def Pid.dir(dir_mode, dir, script)
21
+ # nil script parameter is allowed so long as dir_mode is not :script
22
+ return nil if dir_mode == :script && script.nil?
23
+
24
+ case dir_mode
25
+ when :normal
26
+ return File.expand_path(dir)
27
+ when :script
28
+ return File.expand_path(File.join(File.split(script)[0],dir))
29
+ when :system
30
+ return '/var/run'
31
+ else
32
+ raise Error.new("pid file mode '#{dir_mode}' not implemented")
33
+ end
34
+ end
35
+
36
+ # Initialization method
37
+ def initialize
38
+ end
39
+
40
+
41
+ # Get method
42
+ def pid
43
+ end
44
+
45
+ # Set method
46
+ def pid=(p)
47
+ end
48
+
49
+ # Cleanup method
50
+ def cleanup
51
+ end
52
+
53
+ # Exists? method
54
+ def exists?
55
+ true
56
+ end
57
+
58
+ end
59
+
60
+
61
+ end
@@ -0,0 +1,99 @@
1
+ require 'daemons/pid'
2
+
3
+
4
+ module Daemons
5
+
6
+ # === What is a Pid-File?
7
+ # A <i>Pid-File</i> is a file containing the <i>process identification number</i>
8
+ # (pid) that is stored in a well-defined location of the filesystem thus allowing other
9
+ # programs to find out the pid of a running script.
10
+ #
11
+ # Daemons needs the pid of the scripts that are currently running in the background
12
+ # to send them so called _signals_. Daemons uses the +TERM+ signal to tell the script
13
+ # to exit when you issue a +stop+ command.
14
+ #
15
+ # === How does a Pid-File look like?
16
+ #
17
+ # Pid-Files generated by Daemons have to following format:
18
+ # <scriptname>.rb<number>.pid
19
+ # (Note that <tt><number></tt> is omitted if only one instance of the script can
20
+ # run at any time)
21
+ #
22
+ # Each file just contains one line with the pid as string (for example <tt>6432</tt>).
23
+ #
24
+ # === Where are Pid-Files stored?
25
+ #
26
+ # Daemons is configurable to store the Pid-Files relative to three different locations:
27
+ # 1. in a directory relative to the directory where the script (the one that is supposed to run
28
+ # as a daemon) resides
29
+ # 2. in a directory relative to the current directory or the filesystem root
30
+ # 3. in the preconfigured directory <tt>/var/run</tt>
31
+ #
32
+ class PidFile < Pid
33
+
34
+ attr_reader :dir, :progname, :multiple, :number
35
+
36
+ def PidFile.find_files(dir, progname)
37
+ files = Dir[File.join(dir, "#{progname}*.pid")]
38
+
39
+ files.delete_if {|f| not (File.file?(f) and File.readable?(f))}
40
+
41
+ return files
42
+ end
43
+
44
+ def PidFile.existing(path)
45
+ new_instance = PidFile.allocate
46
+
47
+ new_instance.instance_variable_set(:@path, path)
48
+
49
+ def new_instance.filename
50
+ return @path
51
+ end
52
+
53
+ return new_instance
54
+ end
55
+
56
+ def initialize(dir, progname, multiple = false)
57
+ @dir = File.expand_path(dir)
58
+ @progname = progname
59
+ @multiple = multiple
60
+ @number = 0 if multiple
61
+ end
62
+
63
+ def filename
64
+ File.join(@dir, "#{@progname}#{ @number or '' }.pid")
65
+ end
66
+
67
+ def exists?
68
+ File.exists? filename
69
+ end
70
+
71
+ def pid=(p)
72
+ if multiple
73
+ while File.exists?(filename) and @number < 1024
74
+ @number += 1
75
+ end
76
+
77
+ if @number == 1024
78
+ raise RuntimeException('cannot run more than 1024 instances of the application')
79
+ end
80
+ end
81
+
82
+ File.open(filename, 'w') {|f|
83
+ f.puts p #Process.pid
84
+ }
85
+ end
86
+
87
+ def cleanup
88
+ File.delete(filename)
89
+ end
90
+
91
+ def pid
92
+ File.open(filename) {|f|
93
+ return f.gets.to_i
94
+ }
95
+ end
96
+
97
+ end
98
+
99
+ end
@@ -0,0 +1,10 @@
1
+ require 'daemons/pid'
2
+
3
+
4
+ module Daemons
5
+
6
+ class PidMem < Pid
7
+ attr_accessor :pid
8
+ end
9
+
10
+ end