Skip to content

Commit 178c320

Browse files
author
AJ Christensen
committed
Chef::Daemon
A class for daemonizing and associated tasks, including: Changing UID Changing GID Managing PID files
1 parent c81754e commit 178c320

1 file changed

Lines changed: 142 additions & 0 deletions

File tree

chef/lib/chef/daemon.rb

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
#
2+
# Author:: AJ Christensen (<aj@junglist.gen.nz>)
3+
# Copyright:: Copyright (c) 2008 OpsCode, Inc.
4+
# License:: Apache License, Version 2.0
5+
#
6+
# Licensed under the Apache License, Version 2.0 (the "License");
7+
# you may not use this file except in compliance with the License.
8+
# You may obtain a copy of the License at
9+
#
10+
# http://www.apache.org/licenses/LICENSE-2.0
11+
#
12+
# Unless required by applicable law or agreed to in writing, software
13+
# distributed under the License is distributed on an "AS IS" BASIS,
14+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
# See the License for the specific language governing permissions and
16+
# limitations under the License.
17+
18+
# I love you Merb (lib/merb-core/server.rb)
19+
20+
require 'chef/config'
21+
require 'etc'
22+
23+
class Chef
24+
class Daemon
25+
class << self
26+
attr_accessor :name
27+
=begin
28+
def daemonize(name)
29+
exit if fork
30+
Process.setsid
31+
exit if fork
32+
$stdin.reopen("/dev/null")
33+
$stdout.reopen("/tmp/log", "a")
34+
$stderr.reopen($stdout)
35+
end
36+
=end
37+
38+
def daemonize(name)
39+
@name = name
40+
pid = pid_from_file
41+
unless running?
42+
remove_pid_file()
43+
Chef::Log.info("Daemonizing..")
44+
begin
45+
exit if fork
46+
Process.setsid
47+
exit if fork
48+
Chef::Log.info("Forked, in #{Process.pid}")
49+
File.umask 0000
50+
$stdin.reopen("/dev/null")
51+
$stdout.reopen("/dev/null", "a")
52+
$stdout.reopen($stdout)
53+
at_exit { remove_pid_file }
54+
rescue NotImplementedError => e
55+
Chef.fatal!("There is no fork: #{e.message}")
56+
end
57+
else
58+
Chef.fatal!("Chef is already running pid #{pid}")
59+
end
60+
end
61+
62+
def running?
63+
if pid_from_file.nil?
64+
false
65+
else
66+
Process.kill(0, pid_from_file)
67+
true
68+
end
69+
rescue Errno::ESRCH, Errno::ENOENT
70+
false
71+
#rescue Errno::EACCESS => e
72+
# Chef.fatal!("You don't have access to the PID file at #{pid_file}: #{e.message}")
73+
end
74+
75+
def pid_file
76+
Chef::Config[:pid_file] or "/tmp/#{@name}.pid"
77+
end
78+
79+
def pid_from_file
80+
File.read(pid_file).chomp.to_i
81+
rescue Errno::ENOENT => e
82+
nil
83+
end
84+
85+
def save_pid_file
86+
file = pid_file
87+
begin
88+
FileUtils.mkdir_p(File.dirname(file))
89+
rescue Errno::EACCESS => e
90+
Chef.fatal!("Failed store pid in #{File.dirname(file)}, permission denied: #{e.message}")
91+
end
92+
93+
begin
94+
File.open(file, "w") { |f| f.write(Process.pid.to_s) }
95+
rescue Errno::EACCESS => e
96+
Chef.fatal!("Couldn't write to pidfile #{file}, permission denied: #{e.message}")
97+
end
98+
end
99+
100+
def remove_pid_file
101+
FileUtils.rm(pid_file) if File.exists?(pid_file)
102+
end
103+
104+
def change_privilege
105+
if Chef::Config[:user] and Chef::Config[:group]
106+
Chef::Log.info("About to change privilege to #{Chef::Config[:user]}:#{Chef::Config[:group]}")
107+
_change_privilege(Chef::Config[:user], Chef::Config[:group])
108+
elsif Chef::Config[:user]
109+
Chef::Log.info("About to change privilege to #{Chef::Config[:user]}")
110+
_change_privilege(Chef::Config[:user])
111+
end
112+
end
113+
114+
def _change_privilege(user, group=user)
115+
uid, gid = Process.euid, Process.egid
116+
117+
begin
118+
target_uid = Etc.getpwnam(user).uid
119+
rescue ArgumentError => e
120+
Chef.fatal!("Failed to get UID for user #{user}, does it exist? #{e.message}")
121+
return false
122+
end
123+
124+
begin
125+
target_gid = Etc.getgrnam(group).gid
126+
rescue ArgumentERror => e
127+
Chef.fatal!("Failed to get GID for group #{group}, does it exist? #{e.message}")
128+
return false
129+
end
130+
131+
if (uid != target_uid) or (gid != target_gid)
132+
Process.initgroups(user, target_gid)
133+
Process::GID.change_privilege(target_gid)
134+
Process::UID.change_privilege(target_uid)
135+
end
136+
true
137+
rescue Errno::EPERM => e
138+
Chef.fatal!("Permission denied when trying to change #{uid}:#{gid} to #{user}:#{group}. #{e.message}")
139+
end
140+
end
141+
end
142+
end

0 commit comments

Comments
 (0)