Parent

Class Index [+]

Quicksearch

Merb::Server

Server encapsulates the management of Merb daemons.

Public Class Methods

_change_privilege(user, group=user) click to toggle source

Change privileges of the process to the specified user and group.

Parameters

user

The user to change the process to.

group

The group to change the process to.

Alternatives

If group is left out, the user will be used as the group.

:api: private

     # File lib/merb-core/server.rb, line 324
324:       def _change_privilege(user, group=user)
325:         Merb.logger.warn! "Changing privileges to #{user}:#{group}"
326: 
327:         uid, gid = Process.euid, Process.egid
328: 
329:         begin
330:           target_uid = Etc.getpwnam(user).uid
331:         rescue ArgumentError => e
332:           Merb.fatal!("Failed to change to user #{user}, does the user exist?", e)
333:           return false
334:         end
335: 
336:         begin
337:           target_gid = Etc.getgrnam(group).gid
338:         rescue ArgumentError => e
339:           Merb.fatal!("Failed to change to group #{group}, does the group exist?", e)
340:           return false
341:         end
342: 
343:         if (uid != target_uid) || (gid != target_gid)
344:           # Change process ownership
345:           Process.initgroups(user, target_gid)
346:           Process::GID.change_privilege(target_gid)
347:           Process::UID.change_privilege(target_uid)
348:         end
349:         true
350:       rescue Errno::EPERM => e
351:         Merb.fatal! "Permission denied for changing user:group to #{user}:#{group}.", e
352:         false
353:       end
add_irb_trap() click to toggle source

Add trap to enter IRB on SIGINT. Process exit if second SIGINT is received.

:api: private

     # File lib/merb-core/server.rb, line 358
358:       def add_irb_trap
359:         Merb.trap("INT") do
360:           if @interrupted
361:             Merb.logger.warn! "Interrupt received a second time, exiting!\n"
362:             exit
363:           end
364: 
365:           @interrupted = true
366:           Merb.logger.warn! "Interrupt a second time to quit."
367:           Kernel.sleep 1.5
368:           ARGV.clear # Avoid passing args to IRB
369: 
370:           if @irb.nil?
371:             require "irb"
372:             IRB.setup(nil)
373:             @irb = IRB::Irb.new(nil)
374:             IRB.conf[:MAIN_CONTEXT] = @irb.context
375:           end
376: 
377:           Merb.trap(:INT) { @irb.signal_handle }
378:           catch(:IRB_EXIT) { @irb.eval_input }
379: 
380:           Merb.logger.warn! "Exiting from IRB mode back into server mode."
381:           @interrupted = false
382:           add_irb_trap
383:         end
384:       end
alive?(port) click to toggle source

Parameters

port<~to_s>

The port to check for Merb instances on.

Returns

Boolean

True if Merb is running on the specified port.

:api: private

    # File lib/merb-core/server.rb, line 54
54:       def alive?(port)
55:         pidfile = pid_file(port)
56:         pid     = pid_in_file(pidfile)
57:         Process.kill(0, pid)
58:         true
59:       rescue Errno::ESRCH, Errno::ENOENT
60:         false
61:       rescue Errno::EACCES => e
62:         Merb.fatal!("You don't have access to the PID file at #{pidfile}: #{e.message}")
63:       end
bootup() click to toggle source

Starts up Merb by running the bootloader and starting the adapter.

:api: private

     # File lib/merb-core/server.rb, line 168
168:       def bootup
169:         Merb.trap("TERM") { shutdown }
170: 
171:         Merb.logger.warn! "Running bootloaders..." if Merb::Config[:verbose]
172:         BootLoader.run
173:         Merb.logger.warn! "Starting Rack adapter..." if Merb::Config[:verbose]
174:         Merb.adapter.start(Merb::Config.to_hash)
175:       end
change_privilege() click to toggle source

Change process user/group to those specified in Merb::Config.

:api: private

     # File lib/merb-core/server.rb, line 190
190:       def change_privilege
191:         if Merb::Config[:user] && Merb::Config[:group]
192:           Merb.logger.verbose! "About to change privilege to group "              "#{Merb::Config[:group]} and user #{Merb::Config[:user]}"
193:           _change_privilege(Merb::Config[:user], Merb::Config[:group])
194:         elsif Merb::Config[:user]
195:           Merb.logger.verbose! "About to change privilege to user "              "#{Merb::Config[:user]}"
196:           _change_privilege(Merb::Config[:user])
197:         else
198:           return true
199:         end
200:       end
daemonize(port) click to toggle source

Parameters

port<~to_s>

The port of the Merb process to daemonize.

:api: private

     # File lib/merb-core/server.rb, line 141
141:       def daemonize(port)
142:         Merb.logger.warn! "About to fork..." if Merb::Config[:verbose]
143:         fork do
144:           Process.setsid
145:           exit if fork
146:           Merb.logger.warn! "In #{Process.pid}" if Merb.logger
147:           File.umask 0000
148:           STDIN.reopen "/dev/null"
149:           STDOUT.reopen "/dev/null", "a"
150:           STDERR.reopen STDOUT
151:           begin
152:             Dir.chdir Merb::Config[:merb_root]
153:           rescue Errno::EACCES => e
154:             Merb.fatal! "You specified Merb root as #{Merb::Config[:merb_root]}, "                "yet the current user does not have access to it. ", e
155:           end
156:           at_exit { remove_pid_file(port) }
157:           Merb::Config[:port] = port
158:           bootup
159:         end
160:       rescue NotImplementedError => e
161:         Merb.fatal! "Daemonized mode is not supported on your platform. ", e
162:       end
kill(port, sig = "INT") click to toggle source

Parameters

port<~to_s>

The port of the Merb process to kill.

sig<~to_s>

The signal to send to the process, the default is 9 - SIGKILL.

No Name Default Action Description 1 SIGHUP terminate process terminal line hangup 2 SIGINT terminate process interrupt program 3 SIGQUIT create core image quit program 4 SIGILL create core image illegal instruction 9 SIGKILL terminate process kill program 15 SIGTERM terminate process software termination signal 30 SIGUSR1 terminate process User defined signal 1 31 SIGUSR2 terminate process User defined signal 2

Alternatives

If you pass “all” as the port, the signal will be sent to all Merb processes.

:api: private

     # File lib/merb-core/server.rb, line 88
 88:       def kill(port, sig = "INT")
 89:         if sig.is_a?(Integer)
 90:           sig = Signal.list.invert[sig]
 91:         end
 92:         
 93:         Merb::BootLoader::BuildFramework.run
 94: 
 95:         # If we kill the master, then the workers should be reaped also.
 96:         if %(main master all).include?(port)
 97:           # If a graceful exit is requested then send INT to the master process.
 98:           #
 99:           # Otherwise read pids from pid files and try to kill each process in turn.
100:           kill_pid(sig, pid_file("main")) if sig == "INT"
101:         else
102:           kill_pid(sig, pid_file(port))
103:         end
104:       end
kill_pid(sig, file) click to toggle source

Sends the provided signal to the process pointed at by the provided pid file. :api: private

     # File lib/merb-core/server.rb, line 108
108:       def kill_pid(sig, file)
109:         begin
110:           pid = pid_in_file(file)
111:           Merb.logger.fatal! "Killing pid #{pid} with #{sig}"
112:           Process.kill(sig, pid)
113:           FileUtils.rm(file) if File.exist?(file)
114:         rescue Errno::EINVAL
115:           Merb.logger.fatal! "Failed to kill PID #{pid} with #{sig}: '#{sig}' is an invalid "              "or unsupported signal number."
116:         rescue Errno::EPERM
117:           Merb.logger.fatal! "Failed to kill PID #{pid} with #{sig}: Insufficient permissions."
118:         rescue Errno::ESRCH
119:           FileUtils.rm file
120:           Merb.logger.fatal! "Failed to kill PID #{pid} with #{sig}: Process is "              "deceased or zombie."
121:         rescue Errno::EACCES => e
122:           Merb.logger.fatal! e.message
123:         rescue Errno::ENOENT => e
124:           # This should not cause abnormal exit, which is why 
125:           # we do not use Merb.fatal but instead just log with max level.
126:           Merb.logger.fatal! "Could not find a PID file at #{file}. "              "Most likely the process is no longer running and the pid file was not cleaned up."
127:         rescue Exception => e
128:           if !e.is_a?(SystemExit)
129:             Merb.logger.fatal! "Failed to kill PID #{pid.inspect} with #{sig.inspect}: #{e.message}"
130:           end
131:         end
132:       end
pid_file(port) click to toggle source

Gets the pid file for the specified port/socket.

Parameters

port<~to_s>

The port/socket of the Merb process to whom the the PID file belongs to.

Returns

String

Location of pid file for specified port. If clustered and pid_file option is specified, it adds the port/socket value to the path.

:api: private

     # File lib/merb-core/server.rb, line 290
290:       def pid_file(port)
291:         pidfile = Merb::Config[:pid_file] || (Merb.log_path / "merb.%s.pid")
292:         pidfile % port
293:       end
pid_files() click to toggle source

Get a list of the pid files.

Returns

Array

List of pid file paths. If not running clustered, the array contains a single path.

:api: private

     # File lib/merb-core/server.rb, line 302
302:       def pid_files
303:         if Merb::Config[:pid_file]
304:           if Merb::Config[:cluster]
305:             Dir[Merb::Config[:pid_file] % "*"]
306:           else
307:             [ Merb::Config[:pid_file] ]
308:           end
309:         else
310:           Dir[Merb.log_path / "merb.*.pid"]
311:         end
312:        end
pid_in_file(pidfile) click to toggle source

:api: private

    # File lib/merb-core/server.rb, line 66
66:       def pid_in_file(pidfile)
67:         File.read(pidfile).chomp.to_i
68:       end
remove_pid(port) click to toggle source

Delete the pidfile for the specified port/socket.

:api: private

     # File lib/merb-core/server.rb, line 245
245:       def remove_pid(port)
246:         FileUtils.rm(pid_file(port)) if File.file?(pid_file(port))
247:       end
remove_pid_file(port) click to toggle source

Removes a PID file used by the server from the filesystem. This uses :pid_file options from configuration when provided or merb..pid in log directory by default.

Parameters

port<~to_s>

The port of the Merb process to whom the the PID file belongs to.

Alternatives

If Merb::Config[:pid_file] has been specified, that will be used instead of the port/socket based PID file.

:api: private

     # File lib/merb-core/server.rb, line 217
217:       def remove_pid_file(port)
218:         pidfile = pid_file(port)
219:         if File.exist?(pidfile)
220:           Merb.logger.warn! "Removing pid file #{pidfile} (port/socket: #{port})..."
221:           FileUtils.rm(pidfile)
222:         end
223:       end
shutdown(status = 0) click to toggle source

Shut down Merb, reap any workers if necessary.

:api: private

     # File lib/merb-core/server.rb, line 180
180:       def shutdown(status = 0)
181:         # reap_workers does exit but may not be called...
182:         Merb::BootLoader::LoadClasses.reap_workers(status) if Merb::Config[:fork_for_class_load]
183:         # which is why we exit explicitly here
184:         exit(status)
185:       end
start(port, cluster=nil) click to toggle source

Start a Merb server, in either foreground, daemonized or cluster mode.

Parameters

port<~to_i>

The port to which the first server instance should bind to. Subsequent server instances bind to the immediately following ports.

cluster<~to_i>

Number of servers to run in a cluster.

Alternatives

If cluster is left out, then one process will be started. This process will be daemonized if Merb::Config[:daemonize] is true.

:api: private

    # File lib/merb-core/server.rb, line 23
23:       def start(port, cluster=nil)
24: 
25:         @port = port
26:         @cluster = cluster
27: 
28:         if Merb::Config[:daemonize]
29:           pidfile = pid_file(port)
30:           pid = File.read(pidfile).chomp.to_i if File.exist?(pidfile)
31: 
32:           unless alive?(@port)
33:             remove_pid_file(@port)
34:             Merb.logger.warn! "Daemonizing..." if Merb::Config[:verbose]
35:             daemonize(@port)
36:           else
37:             Merb.fatal! "Merb is already running on port #{port}.\n"                "\e[0m   \e[1;31;47mpid file: \e[34;47m#{pidfile}"                "\e[1;31;47m, process id is \e[34;47m#{pid}."
38:           end
39:         else
40:           bootup
41:         end
42:       end
store_details(port = nil) click to toggle source

Stores a PID file on the filesystem. This uses :pid_file options from configuration when provided or merb..pid in log directory by default.

Parameters

port<~to_s>

The port of the Merb process to whom the the PID file belongs to.

Alternatives

If Merb::Config[:pid_file] has been specified, that will be used instead of the port/socket based PID file.

:api: private

     # File lib/merb-core/server.rb, line 262
262:       def store_details(port = nil)
263:         file = pid_file(port)
264:         begin
265:           FileUtils.mkdir_p(File.dirname(file))
266:         rescue Errno::EACCES => e
267:           Merb.fatal! "Failed to store Merb logs in #{File.dirname(file)}, "              "permission denied. ", e
268:         end
269:         Merb.logger.warn! "Storing pid #{Process.pid} file to #{file}..." if Merb::Config[:verbose]
270:         begin
271:           File.open(file, 'w'){ |f| f.write(Process.pid.to_s) }
272:         rescue Errno::EACCES => e
273:           Merb.fatal! "Failed to access #{file}, permission denied.", e
274:         end
275:       end
store_pid(port) click to toggle source

Stores a PID file on the filesystem. This uses :pid_file options from configuration when provided or merb..pid in log directory by default.

Parameters

port<~to_s>

The port of the Merb process to whom the the PID file belongs to.

Alternatives

If Merb::Config[:pid_file] has been specified, that will be used instead of the port/socket based PID file.

:api: private

     # File lib/merb-core/server.rb, line 238
238:       def store_pid(port)
239:         store_details(port)
240:       end

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.