Module: Thin::Daemonizable

Included in:
Server
Defined in:
lib/thin/daemonizing.rb

Overview

Module included in classes that can be turned into a daemon. Handle stuff like:

  • storing the PID in a file

  • redirecting output to the log file

  • changing process privileges

  • killing the process gracefully

Defined Under Namespace

Modules: ClassMethods

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#log_fileObject

Returns the value of attribute log_file.



27
28
29
# File 'lib/thin/daemonizing.rb', line 27

def log_file
  @log_file
end

#pid_fileObject

Returns the value of attribute pid_file.



27
28
29
# File 'lib/thin/daemonizing.rb', line 27

def pid_file
  @pid_file
end

Class Method Details

.included(base) ⇒ Object



29
30
31
# File 'lib/thin/daemonizing.rb', line 29

def self.included(base)
  base.extend ClassMethods
end

Instance Method Details

#change_privilege(user, group = user) ⇒ Object

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



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/thin/daemonizing.rb', line 67

def change_privilege(user, group=user)
  log ">> Changing process privilege to #{user}:#{group}"

  uid, gid = Process.euid, Process.egid
  target_uid = Etc.getpwnam(user).uid
  target_gid = Etc.getgrnam(group).gid

  if uid != target_uid || gid != target_gid
    # Change PID file ownership
    File.chown(target_uid, target_gid, @pid_file)

    # Change process ownership
    Process.initgroups(user, target_gid)
    Process::GID.change_privilege(target_gid)
    Process::UID.change_privilege(target_uid)
  end
rescue Errno::EPERM => e
  log "Couldn't change user and group to #{user}:#{group}: #{e}"
end

#daemonizeObject

Turns the current script into a daemon process that detaches from the console.



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/thin/daemonizing.rb', line 38

def daemonize
  raise PlatformNotSupported, 'Daemonizing is not supported on Windows'     if Thin.win?
  raise ArgumentError,        'You must specify a pid_file to daemonize' unless @pid_file

  remove_stale_pid_file

  pwd = Dir.pwd # Current directory is changed during daemonization, so store it

  # HACK we need to create the directory before daemonization to prevent a bug under 1.9
  #      ignoring all signals when the directory is created after daemonization.
  FileUtils.mkdir_p File.dirname(@pid_file)
  FileUtils.mkdir_p File.dirname(@log_file)

  Daemonize.daemonize(File.expand_path(@log_file), name)

  Dir.chdir(pwd)

  write_pid_file

  self.after_daemonize if self.respond_to? :after_daemonize

  at_exit do
    log ">> Exiting!"
    remove_pid_file
  end
end

#on_restart(&block) ⇒ Object

Register a proc to be called to restart the server.



88
89
90
# File 'lib/thin/daemonizing.rb', line 88

def on_restart(&block)
  @on_restart = block
end

#pidObject



33
34
35
# File 'lib/thin/daemonizing.rb', line 33

def pid
  File.exist?(pid_file)  && !File.zero?(pid_file) ? open(pid_file).read.to_i : nil
end

#restartObject

Restart the server.



93
94
95
96
97
98
99
100
101
# File 'lib/thin/daemonizing.rb', line 93

def restart
  if @on_restart
    log '>> Restarting ...'
    stop
    remove_pid_file
    @on_restart.call
    exit!
  end
end