rib_fix 0.1.2-x86-mingw32

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,433 @@
1
+ # Author: Genady Petelko (nukegluk@gmail.com)
2
+ # Description: The file contains implementation of 'RunInBackground' module.
3
+
4
+ require 'params'
5
+ require 'log'
6
+
7
+ module BBFS
8
+ # This library provides a basic cross-platform functionality to run arbitrary ruby scripts
9
+ # in background and control them. <br>Supported platforms: Windows, Linux, Mac
10
+ # NOTE UAC (User Account Control) should be disabled to use library on Windows 7:
11
+ # * Click on the Windows Icon
12
+ # * Click on the Control Panel
13
+ # * Type in UAC in the search box (up-right corner of your window)
14
+ # * Click on "Change User Account Control settings"
15
+ # * Drag the slider down to either "Notify me when programs try to make changes to my computer"
16
+ # or to disable it completely
17
+ # * Reboot your computer when you're ready
18
+ # == General Limitations:
19
+ # * Only ruby scripts can be run in background.
20
+ # * No multiple instances with the same name.
21
+ # == Notes:
22
+ # * Linux/Mac specific methods have _linux suffix
23
+ # * Windows specific methods have _windows suffix
24
+ # * While enhancing windows code, take care that paths are in windows format,
25
+ # <br>e.i. with "\\" file separator while ruby by default uses a "/"
26
+ # * Additional functionality such as restart, reload, etc. will be added on demand
27
+ # * Remains support to provide platform specific options for start.
28
+ # <br>For more information regarding such options
29
+ # see documentation for win32-sevice (Windows), daemons (Linux/Mac)
30
+ # == Linux Notes:
31
+ # * <tt>pid_dir</tt> parameter contains absolute path to directory where pid files will be stored.
32
+ # <br>If directory doesn't exists then it will be created.
33
+ # <br>User should have a read/write permissions to this location.
34
+ # <br>Default location: <tt>$HOME/.bbfs/pids</tt>
35
+ # * User should check that default pid directory is free from pid files of "killed" daemons.
36
+ # <br>It may happen, for example, when system finished in abnormal way then pid files were
37
+ # not deleted by daemons library.
38
+ # <br>In such case incorrect results can be received, for example for <tt>exists?</tt> method
39
+ # <br>One of the suggested methods can be before starting a daemon to check with <tt>exists?</tt>
40
+ # method whether daemon already exists and with <tt>running?</tt> method does it running.
41
+ module RunInBackground
42
+ Params.string('bg_command', nil, 'Server\'s command. Commands are: start, delete and nil for' \
43
+ ' not running in background.')
44
+ Params.string('service_name', File.basename($0), 'Background service name.')
45
+
46
+ # Maximal time in seconds to wait until OS will finish a requested operation,
47
+ # e.g. daemon start/delete.
48
+ TIMEOUT = 20
49
+
50
+ if RUBY_PLATFORM =~ /linux/ or RUBY_PLATFORM =~ /darwin/
51
+ begin
52
+ require 'daemons'
53
+ require 'fileutils'
54
+ rescue LoadError
55
+ require 'rubygems'
56
+ require 'daemons'
57
+ require 'fileutils'
58
+ end
59
+
60
+ OS = :LINUX
61
+ Params.string('pid_dir', File.expand_path(File.join(Dir.home, '.bbfs', 'pids')),
62
+ 'Absolute path to directory, where pid files will be stored. ' + \
63
+ 'User should have a read/write permissions to this location. ' + \
64
+ 'If absent then it will be created. ' + \
65
+ 'It\'s actual only for Linux/Mac. ' + \
66
+ 'For more information see documentation on daemons module. ' +\
67
+ 'Default location is: $HOME/.bbfs/pids')
68
+
69
+ if Dir.exists? Params['pid_dir']
70
+ unless File.directory? Params['pid_dir']
71
+ raise IOError.new("pid directory #{Params['pid_dir']} should be a directory")
72
+ end
73
+ unless File.readable?(Params['pid_dir']) && File.writable?(Params['pid_dir'])
74
+ raise IOError.new("you should have read/write permissions to pid dir: #{Params['pid_dir']}")
75
+ end
76
+ else
77
+ ::FileUtils.mkdir_p Params['pid_dir']
78
+ end
79
+ elsif RUBY_PLATFORM =~ /mingw/ or RUBY_PLATFORM =~ /ms/ or RUBY_PLATFORM =~ /win/
80
+ require 'rbconfig'
81
+ begin
82
+ require 'win32/service'
83
+ require 'win32/daemon'
84
+ rescue LoadError
85
+ require 'rubygems'
86
+ require 'win32/service'
87
+ require 'win32/daemon'
88
+ end
89
+ include Win32
90
+
91
+ OS = :WINDOWS
92
+ # Get ruby interpreter path. Need it to run ruby binary.
93
+ # <br>TODO check whether this code works with Windows Ruby Version Management (e.g. Pik)
94
+ RUBY_INTERPRETER_PATH = File.join(Config::CONFIG["bindir"],
95
+ Config::CONFIG["RUBY_INSTALL_NAME"] +
96
+ Config::CONFIG["EXEEXT"]).tr!('/','\\')
97
+
98
+ # Path has to be absolute cause Win32-Service demands it.
99
+ wrapper = File.join(File.dirname(__FILE__), "..", "bin", File.basename(__FILE__, ".rb"), "daemon_wrapper")
100
+ # Wrapper script, that can receive commands from Windows Service Control and run user script,
101
+ # <br> provided as it's argument
102
+ WRAPPER_SCRIPT = File.expand_path(wrapper).tr!('/','\\')
103
+ else
104
+ raise "Unsupported platform #{RUBY_PLATFORM}"
105
+ end
106
+
107
+ # Start a service/daemon.
108
+ # <br>It important to delete it after usage.
109
+ # ==== Arguments
110
+ # * <tt>binary_path</tt> - absolute path to the script that should be run in background
111
+ # NOTE for Linux script should be executable and with UNIX end-of-lines (LF).
112
+ # * <tt>binary_args</tt> - Array (not nil) of script's command line arguments
113
+ # * <tt>name</tt> - service/daemon name.
114
+ # NOTE should be unique
115
+ # * <tt>opts_specific</tt> - Hash of platform specific options (only for more specific usage)
116
+ # For more information regarding such options see documentation for
117
+ # win32-sevice (Windows), daemons (Linux/Mac)
118
+ # ==== Example (LINUX)
119
+ # <tt> RunInBackground.start "/home/user/test_app", [], "daemon_test", {:monitor => true}</tt>
120
+ def RunInBackground.start binary_path, binary_args, name, opts_specific = {}
121
+ Log.debug1("executable that should be run as daemon/service: #{binary_path}")
122
+ Log.debug1("arguments: #{binary_args}")
123
+ Log.debug1("specific options: #{opts_specific}")
124
+
125
+ if binary_path == nil or binary_args == nil or name == nil
126
+ Log.error("binary path, binary args, name arguments must be defined")
127
+ raise ArgumentError.new("binary path, binary args, name arguments must be defined")
128
+ end
129
+
130
+ if OS == :WINDOWS
131
+ new_binary_path = String.new(binary_path)
132
+ new_binary_args = Array.new(binary_args)
133
+ wrap_windows new_binary_path, new_binary_args
134
+ start_windows new_binary_path, new_binary_args, name, opts_specific
135
+ else # OS == LINUX
136
+ start_linux binary_path, binary_args, name, opts_specific
137
+ end
138
+
139
+ 0.upto(TIMEOUT) do
140
+ if exists?(name) && running?(name)
141
+ puts "daemon/service #{name} started\n"
142
+ Log.info("daemon/service #{name} started")
143
+ return
144
+ end
145
+ sleep 1
146
+ end
147
+ # if got here then something gone wrong and daemon/service wasn't started in timely manner
148
+ delete name if exists? name
149
+ Log.error("daemon/service #{name} wasn't started in timely manner")
150
+ sleep(Params['log_param_max_elapsed_time_in_seconds_from_last_flush'] + 0.5)
151
+ raise "daemon/service #{name} wasn't started in timely manner"
152
+ end
153
+
154
+ def RunInBackground.start_linux binary_path, binary_args, name, opts = {}
155
+ unless File.executable? binary_path
156
+ raise ArgumentError.new("#{binary_path} is not executable.")
157
+ end
158
+
159
+ if opts.has_key? :dir
160
+ raise ArgumentError.new("No support for user-defined pid directories. See help")
161
+ end
162
+
163
+ opts[:app_name] = name
164
+ opts[:ARGV] = ['start']
165
+ (opts[:ARGV] << '--').concat(binary_args) if !binary_args.nil? && binary_args.size > 0
166
+ opts[:dir] = Params['pid_dir']
167
+ opts[:dir_mode] = :normal
168
+
169
+ Log.debug1("binary path: #{binary_path}")
170
+ Log.debug1("opts: #{opts}")
171
+
172
+ # Current process, that creates daemon, will transfer control to the Daemons library.
173
+ # So to continue working with current process, daemon creation initiated from separate process.
174
+ pid = fork do
175
+ Daemons.run binary_path, opts
176
+ end
177
+ Process.waitpid pid
178
+ end
179
+
180
+ def RunInBackground.start_windows binary_path, binary_args, name, opts = {}
181
+ raise ArgumentError.new("#{binary_path} doesn't exist'") unless File.exists? binary_path
182
+
183
+ # path that contains spaces must be escaped to be interpreted correctly
184
+ binary_path = %Q{"#{binary_path}"} if binary_path =~ / /
185
+ binary_path.tr!('/','\\')
186
+ # service should be run with the same load path as a current application
187
+ load_path = get_load_path
188
+ binary_args_str = binary_args.join ' '
189
+
190
+ opts[:binary_path_name] = \
191
+ "#{RUBY_INTERPRETER_PATH} #{load_path} #{binary_path} #{binary_args_str}"
192
+ # quotation marks must be escaped cause of ARGV parsing
193
+ opts[:binary_path_name] = opts[:binary_path_name].gsub '"', '"\\"'
194
+ opts[:service_name] = name
195
+ opts[:description] = name unless opts.has_key? :description
196
+ opts[:display_name] = name unless opts.has_key? :display_name
197
+ opts[:service_type] = Service::WIN32_OWN_PROCESS unless opts.has_key? :service_type
198
+ opts[:start_type] = Service::DEMAND_START unless opts.has_key? :start_type
199
+
200
+ # NOTE most of examples uses these dependencies. Meanwhile no explanations were found
201
+ opts[:dependencies] = ['W32Time','Schedule'] unless opts.has_key? :dependencies
202
+ # NOTE most of examples uses this option as defined beneath. The default is nil.
203
+ #opts[:load_order_group] = 'Network' unless opts.has_key? :load_order_group
204
+
205
+ Log.debug1("create service options: #{opts}")
206
+ Service.create(opts)
207
+ begin
208
+ Service.start(opts[:service_name])
209
+ rescue
210
+ Service.delete(opts[:service_name]) if Service.exists?(opts[:service_name])
211
+ raise
212
+ end
213
+ end
214
+
215
+ # Rerun current script in background.
216
+ # <br>Current process will be closed.
217
+ # <br>It suggested to remove from ARGV any command line arguments that point
218
+ # to run script in background, <br>otherwise an unexpexted result can be received
219
+ def RunInBackground.start! name, opts = {}
220
+ # $0 is the executable name.
221
+ start(File.expand_path($0), ARGV, name, opts)
222
+ sleep Params['log_param_max_elapsed_time_in_seconds_from_last_flush'] + 0.5
223
+ exit!
224
+ end
225
+
226
+ # Run in background script that was written as Windows Service, i.e. can receive signals
227
+ # from Service Control.
228
+ # <br>The code that is run in this script should be an extension of Win32::Daemon class.
229
+ # <br>For more information see Win32::Daemon help and examples.
230
+ # <br>No need to wrap such a script.
231
+ def RunInBackground.start_win32service binary_path, binary_args, name, opts_specific = {}
232
+ Log.debug1("executable that should be run as service: #{binary_path}")
233
+ Log.debug1("arguments: #{binary_args}")
234
+ Log.debug1("specific options: #{opts_specific}")
235
+
236
+ if OS == :WINDOWS
237
+ start_windows binary_path, binary_args, name, opts_specific
238
+ else # OS == :LINUX
239
+ raise NotImplementedError.new("Unsupported method on #{OS}")
240
+ end
241
+ 0.upto(TIMEOUT) do
242
+ if exists?(name) && running?(name)
243
+ puts "windows service #{name} started\n"
244
+ Log.info("windows service #{name} started")
245
+ return
246
+ end
247
+ sleep 1
248
+ end
249
+ # if got here then something gone wrong and daemon/service wasn't started in timely manner
250
+ delete name if exists? name
251
+ Log.error("daemon/service #{name} wasn't started in timely manner")
252
+ sleep(Params['log_param_max_elapsed_time_in_seconds_from_last_flush'] + 0.5)
253
+ raise "daemon/service #{name} wasn't started in timely manner"
254
+ end
255
+
256
+ # Wrap an arbitrary ruby script withing script that can be run as Windows Service.
257
+ # ==== Arguments
258
+ # * <tt>binary_path</tt> - absolute path of the script that should be run in background
259
+ # * <tt>binary_args</tt> - array (not nil) of scripts command line arguments
260
+ #
261
+ # NOTE binary_path and binary_args contents will be change
262
+ def RunInBackground.wrap_windows binary_path, binary_args
263
+ raise ArgumentError.new("#{binary_path} doesn't exists") unless File.exists? binary_path
264
+
265
+ # service should be run with the same load path as a current application
266
+ load_path = get_load_path
267
+ # path that contains spaces must be escaped to be interpreted correctly
268
+ binary_path = %Q{"#{binary_path}"} if binary_path =~ / /
269
+ binary_args.insert(0, RUBY_INTERPRETER_PATH, load_path, binary_path.tr('/','\\'))
270
+ binary_path.replace(WRAPPER_SCRIPT)
271
+ end
272
+
273
+ # NOTE if this method will become public then may be needed to change appropriately wrapper script
274
+ def RunInBackground.stop name
275
+ if not exists? name
276
+ raise ArgumentError.new("Daemon #{name} doesn't exists")
277
+ elsif OS == :WINDOWS
278
+ Service.stop(name)
279
+ else # OS == :LINUX
280
+ opts = {:app_name => name,
281
+ :ARGV => ['stop'],
282
+ :dir_mode => :normal,
283
+ :dir => Params['pid_dir']
284
+ }
285
+ # Current process, that creates daemon, will transfer control to the Daemons library.
286
+ # So to continue working with current process, daemon creation initiated from separate process.
287
+ # It looks that it holds only for start command
288
+ #pid = fork do
289
+ Daemons.run "", opts
290
+ #end
291
+ #Process.waitpid pid
292
+ end
293
+ end
294
+
295
+ # Delete service/daemon.
296
+ # <br>If running then stop and delete.
297
+ def RunInBackground.delete name
298
+ if not exists? name
299
+ raise ArgumentError.new("Daemon #{name} doesn't exists")
300
+ elsif running? name
301
+ stop name
302
+ end
303
+ if OS == :WINDOWS
304
+ Service.delete name
305
+ else # OS == :LINUX
306
+ opts = {:app_name => name,
307
+ :ARGV => ['zap'],
308
+ :dir_mode => :normal,
309
+ :dir => Params['pid_dir']
310
+ }
311
+ # Current process, that creates daemon, will transfer control to the Daemons library.
312
+ # So to continue working with current process, daemon creation initiated from separate process.
313
+ # It looks that it holds only for start command
314
+ #pid = fork do
315
+ Daemons.run "", opts
316
+ #end
317
+ #Process.waitpid pid
318
+ end
319
+ 0.upto(TIMEOUT) do
320
+ unless exists? name
321
+ puts "daemon/service #{name} deleted\n"
322
+ Log.info("daemon/service #{name} deleted")
323
+ return
324
+ end
325
+ sleep 1
326
+ end
327
+ # if got here then something gone wrong and daemon/service wasn't deleted in timely manner
328
+ Log.error("daemon/service #{name} wasn't deleted in timely manner")
329
+ sleep(Params['log_param_max_elapsed_time_in_seconds_from_last_flush'] + 0.5)
330
+ raise "daemon/service #{name} wasn't deleted in timely manner"
331
+ end
332
+
333
+ def RunInBackground.exists? name
334
+ if name == nil
335
+ raise ArgumentError.new("service/daemon name argument must be defined")
336
+ elsif OS == :WINDOWS
337
+ Service.exists? name
338
+ else # OS == :LINUX
339
+ pid_files = Daemons::PidFile.find_files(Params['pid_dir'], name)
340
+ pid_files != nil && pid_files.size > 0
341
+ end
342
+ end
343
+
344
+ def RunInBackground.running? name
345
+ if not exists? name
346
+ raise ArgumentError.new("Daemon #{name} doesn't exists")
347
+ elsif OS == :WINDOWS
348
+ Service.status(name).current_state == 'running'
349
+ else # OS == :LINUX
350
+ Daemons::Pid.running? name
351
+ end
352
+ end
353
+
354
+ # Returns absolute standard form of the path.
355
+ # It includes path separators accepted on this OS
356
+ def RunInBackground.get_abs_std_path path
357
+ path = File.expand_path path
358
+ path = path.tr('/','\\') if OS == :WINDOWS
359
+ path
360
+ end
361
+
362
+ # Returns load path as it provided in command line.
363
+ def RunInBackground.get_load_path
364
+ load_path = Array.new
365
+ $:.each do |location|
366
+ load_path << %Q{-I"#{get_abs_std_path(location)}"}
367
+ end
368
+ load_path.join ' '
369
+ end
370
+
371
+ # Prepare ARGV so it can be provided as a command line arguments.
372
+ # Remove bg_command from ARGV to prevent infinite recursion.
373
+ def RunInBackground.prepare_argv
374
+ new_argv = Array.new
375
+ ARGV.each do |arg|
376
+ # For each argument try splitting to 'name'='value'
377
+ arg_arr = arg.split '='
378
+ # If no '=' is argument, just copy paste.
379
+ if arg_arr.size == 1
380
+ arg = "\"#{arg}\"" if arg =~ / /
381
+ new_argv << arg
382
+ # If it is a 'name'='value' argument add "" so the value can be passed as argument again.
383
+ elsif arg_arr.size == 2
384
+ # Skip bg_command flag (remove infinite recursion)!
385
+ if arg_arr[0] !~ /bg_command/
386
+ arg_arr[1] = "\"#{arg_arr[1]}\"" if arg_arr[1] =~ / /
387
+ new_argv << arg_arr.join('=')
388
+ end
389
+ else
390
+ Log.warning("ARGV argument #{arg} wasn't processed")
391
+ new_argv << arg
392
+ end
393
+ end
394
+ ARGV.clear
395
+ ARGV.concat new_argv
396
+ end
397
+
398
+ def RunInBackground.run &b
399
+ case Params['bg_command']
400
+ when nil
401
+ yield b
402
+ when 'start'
403
+ # To prevent service enter loop cause of background parameter
404
+ # all options that points to run in background must be disabled
405
+ # (for more information see documentation for RunInBackground::start!)
406
+ Params['bg_command'] = nil
407
+ RunInBackground.prepare_argv
408
+
409
+ begin
410
+ RunInBackground.start! Params['service_name']
411
+ rescue Exception => e
412
+ Log.error("Start service command failed: #{e.message}")
413
+ raise
414
+ end
415
+ when 'delete'
416
+ if RunInBackground.exists? Params['service_name']
417
+ RunInBackground.delete Params['service_name']
418
+ else
419
+ msg = "Can't delete. Service #{Params['service_name']} already deleted"
420
+ puts msg
421
+ Log.warning(msg)
422
+ end
423
+ else
424
+ msg = "Unsupported command #{Params['bg_command']}. Supported commands are: start, delete"
425
+ puts msg
426
+ Log.error(msg)
427
+ end
428
+ end
429
+
430
+ private_class_method :start_linux, :start_windows, :wrap_windows, :stop, :get_abs_std_path,\
431
+ :get_load_path
432
+ end
433
+ end
@@ -0,0 +1,5 @@
1
+ module BBFS
2
+ module RunInBackground
3
+ VERSION = "0.1.2"
4
+ end
5
+ end
@@ -0,0 +1,124 @@
1
+ require 'test/unit'
2
+ require 'run_in_background'
3
+
4
+ module BBFS
5
+ # TODO break to number of small tests according to functionality
6
+ # TODO rewrite with Shoulda/RSpec
7
+ class TestRunInBackground < Test::Unit::TestCase
8
+ #include BBFS::RunInBackground
9
+
10
+ if RUBY_PLATFORM =~ /linux/ or RUBY_PLATFORM =~ /darwin/
11
+ OS = :LINUX
12
+ elsif RUBY_PLATFORM =~ /mingw/ or RUBY_PLATFORM =~ /ms/ or RUBY_PLATFORM =~ /win/
13
+ require 'sys/uname'
14
+ OS = :WINDOWS
15
+ else
16
+ raise "Unsupported platform #{RUBY_PLATFORM}"
17
+ end
18
+
19
+ def setup
20
+ @good_daemon = "good_daemon_test"
21
+ @good_daemonize = "good_daemonize_test"
22
+ @good_win32daemon = "good_win32daemon_test"
23
+ @bad_daemon = "bad_daemon_test"
24
+ @binary = File.join(File.dirname(File.expand_path(__FILE__)), 'test_app')
25
+ @binary.tr!('/','\\') if OS == :WINDOWS
26
+ File.chmod(0755, @binary) if OS == :LINUX && !File.executable?(@binary)
27
+ @absent_binary = File.join(File.dirname(File.expand_path(__FILE__)), "test_app_absent")
28
+ end
29
+
30
+ def test_functionality
31
+ if OS == :WINDOWS && Sys::Uname.sysname =~ /(Windows 7)/
32
+ skip "This test shouldn't be run on #{$1}"
33
+ end
34
+
35
+ # test start
36
+ # test application should actually start here
37
+ assert_nothing_raised{ RunInBackground.start(@binary, ["1000"], @good_daemon) }
38
+ assert_raise(ArgumentError) { RunInBackground.start(@absent_binary, ["1000"], @bad_daemon) }
39
+
40
+ # start arguments have to be defined
41
+ assert_raise(ArgumentError) { RunInBackground.start(["1000"], @bad_daemon) }
42
+ assert_raise(ArgumentError) { RunInBackground.start(nil, ["1000"], @bad_daemon) }
43
+ assert_raise(ArgumentError) { RunInBackground.start(@absent_binary, nil, @bad_daemon) }
44
+ assert_raise(ArgumentError) { RunInBackground.start(@absent_binary, ["1000"], nil) }
45
+
46
+ # test exists?
47
+ assert_raise(ArgumentError) { RunInBackground.exists? }
48
+ assert_equal(false, RunInBackground.exists?(@bad_daemon))
49
+ assert_equal(true, RunInBackground.exists?(@good_daemon))
50
+
51
+ # test running?
52
+ # if stop method will be public need to add test checks actually stopped daemon
53
+ assert_raise(ArgumentError) { RunInBackground.running? }
54
+ assert_raise(ArgumentError) { RunInBackground.running?(@bad_daemon) }
55
+ assert_equal(true, RunInBackground.running?(@good_daemon))
56
+
57
+ # test daemonazing (start!)
58
+ # from the nature of daemonization need to run it from another process that will be daemonized
59
+ ruby = (OS == :WINDOWS ? RunInBackground::RUBY_INTERPRETER_PATH : "ruby")
60
+ cmd = "#{ruby} -Ilib #{@binary} 50 #{@good_daemonize}"
61
+ pid = spawn(cmd)
62
+ Process.waitpid pid
63
+ # checking that it indeed was daemonized
64
+ # e.i. process was killed and code rerun in background
65
+ # it takes time to the OS to remove process, so using a timeout here
66
+ 0.upto(RunInBackground::TIMEOUT) do
67
+ begin
68
+ Process.kill(0, pid)
69
+ rescue Errno::ESRCH
70
+ break
71
+ end
72
+ sleep 1
73
+ end
74
+ assert_raise(Errno::ESRCH) { Process.kill(0, pid) }
75
+ assert_equal(true, RunInBackground.exists?(@good_daemonize))
76
+ assert_equal(true, RunInBackground.running?(@good_daemonize))
77
+
78
+ # test running win32 specific daemon (start_win32service)
79
+ # wrapper script will be run
80
+ if OS == :WINDOWS
81
+ win32service_arg = [RunInBackground::RUBY_INTERPRETER_PATH, @binary, 1000]
82
+ assert_nothing_raised{
83
+ RunInBackground.start_win32service(RunInBackground::WRAPPER_SCRIPT,
84
+ win32service_arg, @good_win32daemon)
85
+ }
86
+ assert_equal(true, RunInBackground.exists?(@good_win32daemon))
87
+ assert_equal(true, RunInBackground.running?(@good_win32daemon))
88
+ else
89
+ assert_raise(NotImplementedError) {
90
+ RunInBackground.start_win32service(@absent_binary, [], @bad_daemon)
91
+ }
92
+ end
93
+
94
+ # uncomment following lines if there is a suspicion that something gone wrong
95
+ # inspired by bug caused by coworking of daemon_wrapper an logger
96
+ #sleep 10
97
+ #assert_equal(true, RunInBackground.running?(@good_daemon))
98
+ #assert_equal(true, RunInBackground.running?(@good_daemonize))
99
+ #assert_equal(true, RunInBackground.running?(@good_win32daemon))
100
+
101
+ # test delete
102
+ # test application should actually stop here
103
+ assert_raise(ArgumentError) { RunInBackground.delete }
104
+ assert_raise(ArgumentError) { RunInBackground.delete(@bad_daemon) }
105
+ assert_nothing_raised { RunInBackground.delete(@good_daemon) }
106
+ assert_equal(false, RunInBackground.exists?(@good_daemon))
107
+
108
+ assert_nothing_raised { RunInBackground.delete(@good_daemonize) }
109
+ assert_equal(false, RunInBackground.exists?(@good_daemonize))
110
+
111
+ # actuall only for Windows platform
112
+ if RunInBackground.exists?(@good_win32daemon)
113
+ assert_nothing_raised { RunInBackground.delete(@good_win32daemon) }
114
+ assert_equal(false, RunInBackground.exists?(@good_win32daemon))
115
+ end
116
+ end
117
+
118
+ def teardown
119
+ RunInBackground.delete @good_daemon if RunInBackground.exists? @good_daemon
120
+ RunInBackground.delete @good_daemonize if RunInBackground.exists? @good_daemonize
121
+ RunInBackground.delete @good_win32daemon if RunInBackground.exists? @good_win32daemon
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,58 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Toy script used for RunInBackground tests.
4
+ # usage: $0 number_of_iterations [daemon_name_if_daemonized]
5
+
6
+ DBG = false # NOTE be sure to disable it in production
7
+
8
+ begin
9
+ begin
10
+ require 'log'
11
+ require 'params'
12
+ rescue LoadError
13
+ $:.unshift(File.join(File.dirname(File.expand_path(__FILE__)), '..', '..', 'lib'))
14
+ $:.unshift(File.join(File.dirname(File.expand_path(__FILE__)), '..', '..'))
15
+ require 'log'
16
+ require 'params'
17
+ end
18
+
19
+ # On WindowsXP log can be found under:
20
+ # C:/Documents and Settings/NetworkService/.bbfs/test_app_<pid>.log
21
+ BBFS::Params['log_file_name'] = File.join(Dir.home, '.bbfs', "#{File.basename(__FILE__)}_#{Process.pid}.log")
22
+ BBFS::Params['log_write_to_console'] = false
23
+ BBFS::Params['log_param_max_elapsed_time_in_seconds_from_last_flush'] = 1
24
+ if DBG
25
+ BBFS::Params['log_debug_level'] = 1
26
+ BBFS::Log.init
27
+ end
28
+
29
+ # app should be run in background
30
+ if ARGV.size == 2
31
+ begin
32
+ require 'run_in_background'
33
+ rescue LoadError
34
+ $:.unshift(File.join(File.dirname(File.expand_path(__FILE__)), '..', '..', 'lib'))
35
+ $:.unshift(File.join(File.dirname(File.expand_path(__FILE__)), '..', '..'))
36
+ require 'run_in_background'
37
+ end
38
+
39
+ BBFS::Log.debug1 "Before run in background: PID #{Process.pid}"
40
+ # ARGV.pop returns frozen string and thus causes a failure of Service.create
41
+ # to fix it new string with the same content created.
42
+ BBFS::RunInBackground.start!(String.new(ARGV.pop))
43
+ # if got here then error
44
+ BBFS::Log.error "After run in background: ERROR"
45
+ end
46
+
47
+ max = (ARGV.size > 0 && ARGV[0] != nil && ARGV[0].to_i > 0)? ARGV[0].to_i : 200
48
+
49
+ while max > 0
50
+ BBFS::Log.debug1 "#{max}"
51
+ sleep 1
52
+ max -= 1
53
+ end
54
+
55
+ rescue Exception => err
56
+ BBFS::Log.error "Wrapper error: #{err}"
57
+ raise
58
+ end
metadata ADDED
@@ -0,0 +1,96 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rib_fix
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.2
5
+ prerelease:
6
+ platform: x86-mingw32
7
+ authors:
8
+ - Genady Petelko
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-10-14 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: log
16
+ requirement: &5726688 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *5726688
25
+ - !ruby/object:Gem::Dependency
26
+ name: params
27
+ requirement: &5725812 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *5725812
36
+ - !ruby/object:Gem::Dependency
37
+ name: win32-service
38
+ requirement: &5724432 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *5724432
47
+ - !ruby/object:Gem::Dependency
48
+ name: sys-uname
49
+ requirement: &5723868 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :runtime
56
+ prerelease: false
57
+ version_requirements: *5723868
58
+ description: ! 'This library provides a basic cross-platform functionality to runarbitrary
59
+ ruby scripts in background and control them.Supported platforms: Windows, Linux,
60
+ Mac.'
61
+ email: nukegluk@gmail.com
62
+ executables: []
63
+ extensions: []
64
+ extra_rdoc_files: []
65
+ files:
66
+ - lib/run_in_background.rb
67
+ - lib/run_in_background/version.rb
68
+ - test/run_in_background/run_in_background_test.rb
69
+ - test/run_in_background/test_app
70
+ homepage: http://github.com/kolmanv/bbfs
71
+ licenses: []
72
+ post_install_message:
73
+ rdoc_options: []
74
+ require_paths:
75
+ - lib
76
+ required_ruby_version: !ruby/object:Gem::Requirement
77
+ none: false
78
+ requirements:
79
+ - - ! '>='
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ required_rubygems_version: !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ! '>='
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ requirements: []
89
+ rubyforge_project:
90
+ rubygems_version: 1.8.8
91
+ signing_key:
92
+ specification_version: 3
93
+ summary: Cross-platform library for daemons management.
94
+ test_files:
95
+ - test/run_in_background/run_in_background_test.rb
96
+ - test/run_in_background/test_app