ducksboard_reporter 0.1.1 → 0.1.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: faaa03c65806c52554a5e2afe37b04914c1dccb6
4
- data.tar.gz: 7820258a49917f566545b8298760c2fc4461d448
3
+ metadata.gz: 0f166259ade7200cbecbe4b6c47afebab9ec0168
4
+ data.tar.gz: b4c7a1700503fb55d363461d70069f35f39fafc4
5
5
  SHA512:
6
- metadata.gz: 90b1b70ee0b2b8fc0b838b20a95b682ae024c2dd6a2b9f48cc43a944672a9dec9baee1fa842e8678fc1d07a125ac6d52461abb1c58a652f362ccc8fb10984075
7
- data.tar.gz: b1779d9639ce483333c7ee84429074c5e6e36033b5ed7c5fa7ee2c9455a7c5f80c7c53c7f53846ae5e5d85c5ef696cfc3138f57018e6f3422b1f72af7d0680b4
6
+ metadata.gz: e9c0f3bacc413c914382430327ed53dc1e23eacb800aa69c0c363c6fc667b70261d77e1a8393775b6bd8d9ac210581155ac285a9776fc0a52669aab5432154ac
7
+ data.tar.gz: 7a83efa936333b143b766f3df60043a858ba3623a66a0517779362ab74c349e562a5ab6cf8b03fe9ae91ac317c1cb1b5e69b1d3f3c1582085947886a1a37c429
@@ -4,10 +4,30 @@ $:.unshift File.expand_path("../../lib", __FILE__)
4
4
  require "ducksboard_reporter"
5
5
  require "trollop"
6
6
  require "yaml"
7
+ require "rund"
7
8
 
8
9
  opts = Trollop::options do
9
10
  opt :config_file, "Path to config file", short: "f", type: :string, required: true
11
+ opt :pid_file, "Path to pid file", short: "p", type: :string
12
+ opt :log_file, "Path to log file", short: "l", type: :string
13
+ opt :run_dir, "Path to run dir", type: :string
14
+ opt :user, "The daemon wil run as specified user", type: :string
15
+ opt :group, "The daemon wil run as specified group", type: :string
16
+ opt :daemonize, "Detach from terminal", short: "d", default: false
10
17
  end
11
18
 
19
+ # Rund.debug = true
20
+
12
21
  config = YAML.load_file(opts[:config_file])
22
+
23
+ if opts[:daemonize]
24
+ Rund.pid_file = opts[:pid_file]
25
+ Rund.log_file = opts[:log_file]
26
+ Rund.run_dir = opts[:run_dir]
27
+ Rund.user = opts[:user]
28
+ Rund.group = opts[:group]
29
+ Rund.daemonize!
30
+ end
31
+
13
32
  DucksboardReporter::App.new(config).start
33
+
@@ -1,3 +1,3 @@
1
1
  module DucksboardReporter
2
- VERSION = "0.1.1"
2
+ VERSION = "0.1.2"
3
3
  end
data/lib/rund.rb ADDED
@@ -0,0 +1,192 @@
1
+ require "fileutils"
2
+ require "etc"
3
+
4
+ module Rund
5
+ extend self
6
+
7
+ def daemonize!
8
+ # Keeep $stderr IO to display error and debug messages until
9
+ # daemonizing is finished
10
+ keep_local_stderr
11
+
12
+ File.umask(0000)
13
+ Process.daemon(true, true)
14
+ change_group if @group
15
+ change_user if @user
16
+ write_pid if @pid_file
17
+ change_dir
18
+ redirect_input
19
+ redirect_output
20
+
21
+ close_local_stderr
22
+ end
23
+
24
+ def log_file=(path)
25
+ @log_file = clean_path(path)
26
+ end
27
+
28
+ def pid_file=(path)
29
+ @pid_file = clean_path(path)
30
+ end
31
+
32
+ def run_dir=(path)
33
+ @run_dir = clean_path(path)
34
+ end
35
+
36
+ def input_file=(path)
37
+ @input_file = clean_path(path)
38
+ end
39
+
40
+ def user=(user)
41
+ @user = user
42
+ end
43
+
44
+ def group=(group)
45
+ @group = group
46
+ end
47
+
48
+ def debug=(flag)
49
+ @debug = !!flag
50
+ end
51
+
52
+ private
53
+
54
+ def change_user
55
+ error("Not running as root. Cannot change user of process.") if Process.uid != 0
56
+ begin
57
+ user = (@user.is_a? Integer) ? Etc.getpwuid(@user) : Etc.getpwnam(@user)
58
+ rescue ArgumentError
59
+ error("User #{@user} does not exist")
60
+ end
61
+
62
+ debug { "Changing user to #{user.name} UID=#{user.uid}" }
63
+
64
+ Process::UID.change_privilege(user.uid)
65
+ end
66
+
67
+ def change_group
68
+ error("Not running as root. Cannot change group of process.") if Process.uid != 0
69
+ begin
70
+ group = (@group.is_a? Integer) ? Etc.getgrgid(@group) : Etc.getgrnam(@group)
71
+ rescue ArgumentError
72
+ error("Group #{@group} does not exist")
73
+ end
74
+
75
+ debug { "Changing group to #{group.name} GID=#{group.gid}" }
76
+
77
+ begin
78
+ Process::GID.change_privilege(group.gid)
79
+ rescue Errno::EPERM
80
+ error("Cannot change to group #{group.name}. Permission denied.")
81
+ end
82
+ end
83
+
84
+ def keep_local_stderr
85
+ @stderr = $stderr.dup
86
+ @stderr.sync
87
+ end
88
+
89
+ def close_local_stderr
90
+ @stderr.close
91
+ end
92
+
93
+ def clean_path(path)
94
+ path = path.to_s.strip
95
+ path.empty? ? nil : File.absolute_path(path)
96
+ end
97
+
98
+ def change_dir
99
+ @run_dir ||= "/"
100
+ debug { "Changing to #{@run_dir} as run dir" }
101
+ Dir.chdir(@run_dir)
102
+ end
103
+
104
+ def redirect_output
105
+ @log_file ||= "/dev/null"
106
+ debug { "Logging to #{@log_file}" }
107
+
108
+ log_dir = File.dirname(@log_file)
109
+ error("Log file dir does not exist #{log_dir}") unless File.exists?(log_dir)
110
+
111
+ begin
112
+ unless File.exists?(@log_file)
113
+ FileUtils.touch(@log_file)
114
+ File.chmod(0644, @log_file)
115
+ end
116
+ rescue Errno::EACCES
117
+ error("Cannot write log file #{@log_file}. Permission denied.")
118
+ end
119
+
120
+ $stderr.reopen(@log_file, "a")
121
+ $stdout.reopen($stderr)
122
+ $stdout.sync = $stderr.sync = true
123
+ end
124
+
125
+ def redirect_input
126
+ @input_file ||= "/dev/null"
127
+ $stdin.reopen(@input_file, "r")
128
+ end
129
+
130
+ def write_pid
131
+ debug { "Writing pid to #{@pid_file}" }
132
+
133
+ begin
134
+ File.open(@pid_file, File::CREAT | File::EXCL | File::WRONLY) {|f| f.write("#{Process.pid}") }
135
+ rescue Errno::EACCES
136
+ error("Cannot write pid file #{@pid_file}. Permission denied.")
137
+ rescue Errno::EEXIST
138
+ check_pid
139
+ retry
140
+ end
141
+
142
+ at_exit do
143
+ begin
144
+ File.delete(@pid_file) if @pid_file && File.exists?(@pid_file)
145
+ rescue Errno::EACCES
146
+ debug { "Cannot delete pid file #{@pid_file}. Permission denied." }
147
+ end
148
+ end
149
+ end
150
+
151
+ def pid_status
152
+ return :exited unless File.exists?(@pid_file)
153
+ return :dead if pid == 0
154
+
155
+ Process.kill(0, pid) # check process status
156
+ :running
157
+ rescue Errno::ESRCH
158
+ :dead
159
+ rescue Errno::EPERM
160
+ :not_owned
161
+ end
162
+
163
+ def check_pid
164
+ case pid_status
165
+ when :running, :not_owned
166
+ error("A process is already running with pid #{pid}")
167
+ when :dead
168
+ debug { "Deleting stale pid file" }
169
+ File.delete(@pid_file)
170
+ end
171
+ end
172
+
173
+ def pid
174
+ @pid ||= File.read(@pid_file).strip.to_i
175
+ end
176
+
177
+ def error(msg)
178
+ @stderr << "ERROR: #{msg}\n"
179
+ exit 1
180
+ end
181
+
182
+ def debug(msg = nil)
183
+ return unless @debug
184
+ msg = yield if block_given?
185
+ @stderr << "DEBUG: #{msg}\n"
186
+ end
187
+
188
+ def error(msg)
189
+ @stderr << "ERROR: #{msg}\n"
190
+ exit 1
191
+ end
192
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ducksboard_reporter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - unnu
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-09-30 00:00:00.000000000 Z
11
+ date: 2014-10-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -174,6 +174,7 @@ files:
174
174
  - lib/ducksboard_reporter/reporters/random.rb
175
175
  - lib/ducksboard_reporter/version.rb
176
176
  - lib/ducksboard_reporter/widget.rb
177
+ - lib/rund.rb
177
178
  - spec/ducksboard_reporter_spec.rb
178
179
  - spec/reporter_spec.rb
179
180
  - spec/spec_helper.rb