perfmonger 0.6.1
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 +15 -0
- data/.dir-locals.el +2 -0
- data/.gitignore +4 -0
- data/.rspec +1 -0
- data/.travis.yml +12 -0
- data/COPYING +674 -0
- data/Gemfile +5 -0
- data/HOWTO.md +15 -0
- data/NEWS +115 -0
- data/README.md +61 -0
- data/Rakefile +8 -0
- data/bin/perfmonger +6 -0
- data/data/NOTICE +8 -0
- data/data/Twitter_Bootstrap_LICENSE.txt +176 -0
- data/data/assets/css/bootstrap-responsive.css +1109 -0
- data/data/assets/css/bootstrap.css +6167 -0
- data/data/assets/css/perfmonger.css +17 -0
- data/data/assets/dashboard.erb +319 -0
- data/data/assets/img/glyphicons-halflings-white.png +0 -0
- data/data/assets/img/glyphicons-halflings.png +0 -0
- data/data/assets/js/bootstrap.js +2280 -0
- data/data/assets/js/bootstrap.min.js +6 -0
- data/data/assets/js/canvasjs.js +9042 -0
- data/data/assets/js/canvasjs.min.js +271 -0
- data/data/sysstat.ioconf +268 -0
- data/ext/perfmonger/extconf.rb +19 -0
- data/ext/perfmonger/perfmonger.h +58 -0
- data/ext/perfmonger/perfmonger_record.c +754 -0
- data/ext/perfmonger/sysstat/common.c +627 -0
- data/ext/perfmonger/sysstat/common.h +207 -0
- data/ext/perfmonger/sysstat/ioconf.c +515 -0
- data/ext/perfmonger/sysstat/ioconf.h +84 -0
- data/ext/perfmonger/sysstat/iostat.c +1100 -0
- data/ext/perfmonger/sysstat/iostat.h +121 -0
- data/ext/perfmonger/sysstat/libsysstat.h +19 -0
- data/ext/perfmonger/sysstat/mpstat.c +953 -0
- data/ext/perfmonger/sysstat/mpstat.h +79 -0
- data/ext/perfmonger/sysstat/rd_stats.c +2388 -0
- data/ext/perfmonger/sysstat/rd_stats.h +651 -0
- data/ext/perfmonger/sysstat/sysconfig.h +13 -0
- data/lib/perfmonger/cli.rb +115 -0
- data/lib/perfmonger/command/base_command.rb +39 -0
- data/lib/perfmonger/command/fingerprint.rb +453 -0
- data/lib/perfmonger/command/plot.rb +429 -0
- data/lib/perfmonger/command/record.rb +32 -0
- data/lib/perfmonger/command/record_option.rb +149 -0
- data/lib/perfmonger/command/server.rb +294 -0
- data/lib/perfmonger/command/stat.rb +60 -0
- data/lib/perfmonger/command/stat_option.rb +29 -0
- data/lib/perfmonger/command/summary.rb +402 -0
- data/lib/perfmonger/config.rb +6 -0
- data/lib/perfmonger/version.rb +5 -0
- data/lib/perfmonger.rb +12 -0
- data/misc/release-howto.txt +17 -0
- data/misc/sample-cpu.png +0 -0
- data/misc/sample-read-iops.png +0 -0
- data/perfmonger.gemspec +44 -0
- data/test/run-test.sh +39 -0
- data/test/spec/bin_spec.rb +37 -0
- data/test/spec/data/2devices.expected +42 -0
- data/test/spec/data/2devices.output +42 -0
- data/test/spec/spec_helper.rb +20 -0
- data/test/spec/summary_spec.rb +193 -0
- data/test/test-perfmonger.c +145 -0
- data/test/test.h +9 -0
- metadata +154 -0
@@ -0,0 +1,115 @@
|
|
1
|
+
|
2
|
+
require 'optparse'
|
3
|
+
|
4
|
+
module PerfMonger
|
5
|
+
module CLI
|
6
|
+
|
7
|
+
class Runner
|
8
|
+
def self.register_command(command_name, klass)
|
9
|
+
@@commands ||= Hash.new
|
10
|
+
@@aliases ||= Hash.new
|
11
|
+
|
12
|
+
@@commands[command_name] = klass
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.register_alias(alias_name, command_name)
|
16
|
+
if @@commands.nil?
|
17
|
+
raise RuntimeError.new("No command is registered yet.")
|
18
|
+
end
|
19
|
+
|
20
|
+
if ! @@commands.has_key?(command_name)
|
21
|
+
raise RuntimeError.new("Command '#{command_name}' is not registered.")
|
22
|
+
end
|
23
|
+
|
24
|
+
@@aliases[alias_name] = command_name
|
25
|
+
end
|
26
|
+
|
27
|
+
def initialize
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
def run(argv = ARGV)
|
32
|
+
parser = OptionParser.new
|
33
|
+
parser.banner = <<EOS
|
34
|
+
Usage: #{File.basename($0)} [options] COMMAND [args]
|
35
|
+
|
36
|
+
EOS
|
37
|
+
|
38
|
+
## make list of subcommands
|
39
|
+
commands = @@commands.values.sort_by do |command|
|
40
|
+
# important command first: sort by [priority, name]
|
41
|
+
command_name = command.command_name
|
42
|
+
case command_name
|
43
|
+
when "record"
|
44
|
+
[0, command_name]
|
45
|
+
when "stat"
|
46
|
+
[1, command_name]
|
47
|
+
when "plot"
|
48
|
+
[2, command_name]
|
49
|
+
else
|
50
|
+
[999, command_name]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
max_len = commands.map(&:command_name).map(&:size).max
|
55
|
+
command_list_str = commands.map do |command|
|
56
|
+
# pad command names
|
57
|
+
command_name = command.command_name
|
58
|
+
command_name = command_name + (" " * (max_len - command_name.size))
|
59
|
+
|
60
|
+
str = " " + command_name + " " + command.description
|
61
|
+
|
62
|
+
if command.aliases && command.aliases.size > 0
|
63
|
+
str += "\n" + " " + (" " * max_len) + " " +
|
64
|
+
"Aliases: " + command.aliases.join(", ")
|
65
|
+
end
|
66
|
+
|
67
|
+
str
|
68
|
+
end.join("\n")
|
69
|
+
|
70
|
+
subcommand_list = <<EOS
|
71
|
+
|
72
|
+
Commands:
|
73
|
+
#{command_list_str}
|
74
|
+
EOS
|
75
|
+
|
76
|
+
parser.summary_indent = " "
|
77
|
+
|
78
|
+
parser.on('-h', '--help', 'Show this help') do
|
79
|
+
puts(parser.help)
|
80
|
+
puts(subcommand_list)
|
81
|
+
exit(true)
|
82
|
+
end
|
83
|
+
|
84
|
+
parser.on('-v', '--version', 'Show version number') do
|
85
|
+
puts("PerfMonger version " + PerfMonger::VERSION)
|
86
|
+
exit(true)
|
87
|
+
end
|
88
|
+
|
89
|
+
parser.order!(argv)
|
90
|
+
|
91
|
+
if argv.size == 0
|
92
|
+
puts(parser.help)
|
93
|
+
puts(subcommand_list)
|
94
|
+
exit(false)
|
95
|
+
end
|
96
|
+
|
97
|
+
command_name = argv.shift
|
98
|
+
|
99
|
+
if @@aliases[command_name]
|
100
|
+
command_name = @@aliases[command_name]
|
101
|
+
end
|
102
|
+
command_class = @@commands[command_name]
|
103
|
+
|
104
|
+
unless command_class
|
105
|
+
puts("No such command: #{command_name}")
|
106
|
+
puts(subcommand_list)
|
107
|
+
exit(false)
|
108
|
+
end
|
109
|
+
|
110
|
+
command_class.new.run(argv)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
|
2
|
+
module PerfMonger
|
3
|
+
module Command
|
4
|
+
|
5
|
+
class BaseCommand
|
6
|
+
class << self
|
7
|
+
attr_accessor :command_name
|
8
|
+
attr_accessor :description
|
9
|
+
attr_accessor :aliases
|
10
|
+
|
11
|
+
def register_command(command_name, description = "")
|
12
|
+
PerfMonger::CLI::Runner.register_command(command_name, self)
|
13
|
+
self.command_name = command_name
|
14
|
+
self.description = description
|
15
|
+
end
|
16
|
+
|
17
|
+
def register_alias(alias_name)
|
18
|
+
if self.command_name
|
19
|
+
RuntimeError.new("#{self} does not have registered command name.")
|
20
|
+
end
|
21
|
+
|
22
|
+
self.aliases ||= []
|
23
|
+
self.aliases.push(alias_name)
|
24
|
+
PerfMonger::CLI::Runner.register_alias(alias_name, self.command_name)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def initialize
|
29
|
+
@parser = OptionParser.new
|
30
|
+
@parser.banner = <<EOS
|
31
|
+
Usage: #{File.basename($0)} #{self.class.command_name} [options]
|
32
|
+
|
33
|
+
Options:
|
34
|
+
EOS
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,453 @@
|
|
1
|
+
|
2
|
+
require 'fileutils'
|
3
|
+
require 'tmpdir'
|
4
|
+
require 'tempfile'
|
5
|
+
|
6
|
+
module PerfMonger
|
7
|
+
module Command
|
8
|
+
|
9
|
+
class FingerprintCommand < BaseCommand
|
10
|
+
register_command 'fingerprint', 'Gather all possible system config information'
|
11
|
+
register_alias 'bukko'
|
12
|
+
register_alias 'fp'
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@parser = OptionParser.new
|
16
|
+
@parser.banner = <<EOS
|
17
|
+
Usage: perfmonger fingerprint [options] OUTPUT_TARBALL
|
18
|
+
|
19
|
+
Options:
|
20
|
+
EOS
|
21
|
+
|
22
|
+
hostname = `hostname`.strip
|
23
|
+
@output_tarball = "./fingerprint.#{hostname}.tar.gz"
|
24
|
+
end
|
25
|
+
|
26
|
+
def parse_args(argv)
|
27
|
+
@parser.parse!(argv)
|
28
|
+
|
29
|
+
if argv.size == 0
|
30
|
+
puts("ERROR: output directory is required.")
|
31
|
+
puts(@parser.help)
|
32
|
+
exit(false)
|
33
|
+
end
|
34
|
+
|
35
|
+
@output_tarball = argv.shift
|
36
|
+
|
37
|
+
if ! @output_tarball =~ /\.(tar\.gz|tgz)$/
|
38
|
+
@output_tarball += ".tar.gz"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def run(argv)
|
43
|
+
parse_args(argv)
|
44
|
+
|
45
|
+
ENV['LANG'] = 'C'
|
46
|
+
|
47
|
+
$stderr.puts("System information is gathered into #{@output_tarball}")
|
48
|
+
|
49
|
+
Dir.mktmpdir do |tmpdir|
|
50
|
+
output_basename = File.basename(@output_tarball.gsub(/\.(tar\.gz|tgz)$/, ''))
|
51
|
+
|
52
|
+
@output_dir = File.join(tmpdir, output_basename)
|
53
|
+
FileUtils.mkdir(@output_dir)
|
54
|
+
|
55
|
+
## Collect generic info.
|
56
|
+
do_with_message("Saving /proc info") do
|
57
|
+
save_proc_info()
|
58
|
+
end
|
59
|
+
|
60
|
+
do_with_message("Saving IRQ info") do
|
61
|
+
save_irq_info()
|
62
|
+
end
|
63
|
+
|
64
|
+
do_with_message("Saving block device info") do
|
65
|
+
save_device_info()
|
66
|
+
end
|
67
|
+
|
68
|
+
do_with_message("Saving /dev/disk info") do
|
69
|
+
save_disk_info()
|
70
|
+
end
|
71
|
+
|
72
|
+
do_with_message("Saving PCI/PCIe info") do
|
73
|
+
save_pci_info()
|
74
|
+
end
|
75
|
+
|
76
|
+
do_with_message("Saving kernel module info") do
|
77
|
+
save_module_info()
|
78
|
+
end
|
79
|
+
|
80
|
+
do_with_message("Saving distro info") do
|
81
|
+
save_distro_info()
|
82
|
+
end
|
83
|
+
|
84
|
+
do_with_message("Saving sysctl info") do
|
85
|
+
save_sysctl_info()
|
86
|
+
end
|
87
|
+
|
88
|
+
do_with_message("Saving dmidecode info") do
|
89
|
+
save_dmidecode_info()
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
## Collect vendor specific info
|
94
|
+
|
95
|
+
# LSI MegaRAID
|
96
|
+
megacli_bin = "/opt/MegaRAID/MegaCli/MegaCli64"
|
97
|
+
if File.executable?(megacli_bin) && Process::UID.rid == 0
|
98
|
+
do_with_message("Saving MegaRAID settings") do
|
99
|
+
save_megaraid_info(megacli_bin)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
tmptar_path = Tempfile.new("fingerprint").path
|
104
|
+
|
105
|
+
Dir.chdir(tmpdir) do
|
106
|
+
if ! system("tar czf '#{tmptar_path}' #{output_basename}")
|
107
|
+
raise RuntimeError.new("Failed to execute tar(1)")
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
FileUtils.mv(tmptar_path, @output_tarball)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
private
|
116
|
+
def do_with_message(message)
|
117
|
+
$stderr.print(message + " ... ")
|
118
|
+
$stderr.flush
|
119
|
+
|
120
|
+
@errors = []
|
121
|
+
|
122
|
+
begin
|
123
|
+
yield
|
124
|
+
rescue StandardError => err
|
125
|
+
$stderr.puts("failed")
|
126
|
+
@errors.push(err)
|
127
|
+
end
|
128
|
+
|
129
|
+
if @errors.empty?
|
130
|
+
$stderr.puts("done")
|
131
|
+
$stderr.puts("")
|
132
|
+
else
|
133
|
+
$stderr.puts("failed")
|
134
|
+
$stderr.puts("")
|
135
|
+
@errors.each do |error|
|
136
|
+
$stderr.puts(" ERROR: #{error.message}")
|
137
|
+
end
|
138
|
+
$stderr.puts("")
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def read_file(src)
|
143
|
+
if File.exists?(src)
|
144
|
+
begin
|
145
|
+
return File.read(src)
|
146
|
+
rescue StandardError => err
|
147
|
+
@errors.push(err)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
nil
|
152
|
+
end
|
153
|
+
|
154
|
+
def copy_file(src, dest)
|
155
|
+
content = read_file(src)
|
156
|
+
|
157
|
+
if content
|
158
|
+
File.open(dest, "w") do |f|
|
159
|
+
f.print(content)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def find_executable(command_name)
|
165
|
+
# try to find lspci
|
166
|
+
dirs = ["/sbin", "/usr/sbin", "/usr/local/sbin", "/usr/bin", "/usr/local/bin"]
|
167
|
+
dirs += ENV['PATH'].split(":")
|
168
|
+
|
169
|
+
bindir = dirs.find do |dir|
|
170
|
+
File.executable?(File.expand_path(command_name, dir))
|
171
|
+
end
|
172
|
+
|
173
|
+
if bindir
|
174
|
+
File.expand_path(command_name, bindir)
|
175
|
+
else
|
176
|
+
@errors << RuntimeError.new("#{command_name}(1) not found")
|
177
|
+
nil
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
|
182
|
+
def save_proc_info()
|
183
|
+
["cpuinfo", "meminfo", "mdstat", "mounts", "interrupts",
|
184
|
+
"diskstats", "partitions", "ioports",
|
185
|
+
].each do |entry|
|
186
|
+
copy_file("/proc/#{entry}", "#{@output_dir}/proc-#{entry}.log")
|
187
|
+
end
|
188
|
+
|
189
|
+
copy_file('/proc/scsi/scsi', "#{@output_dir}/proc-scsi.log")
|
190
|
+
|
191
|
+
File.open("#{@output_dir}/proc-sys-fs.log", "w") do |f|
|
192
|
+
Dir.glob("/proc/sys/fs/*").each do |path|
|
193
|
+
next unless File.file?(path)
|
194
|
+
begin
|
195
|
+
content = File.read(path)
|
196
|
+
rescue Errno::EACCES => err
|
197
|
+
@errors.push(err)
|
198
|
+
f.puts("## #{path}")
|
199
|
+
f.puts("permission denied")
|
200
|
+
f.puts("")
|
201
|
+
next
|
202
|
+
rescue StandardError => err
|
203
|
+
@errors.push(err)
|
204
|
+
next
|
205
|
+
end
|
206
|
+
f.puts("## #{path}")
|
207
|
+
f.puts(content)
|
208
|
+
f.puts("")
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
def save_irq_info()
|
214
|
+
File.open("#{@output_dir}/irq-smp-affinity.log", "w") do |f|
|
215
|
+
Dir.glob('/proc/irq/*/smp_affinity').sort_by do |path|
|
216
|
+
irqno = File.basename(File.dirname(path)).to_i
|
217
|
+
end.each do |path|
|
218
|
+
f.puts("## cat #{path}")
|
219
|
+
f.puts(`cat #{path}`)
|
220
|
+
f.puts("")
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
def save_device_info()
|
226
|
+
(Dir.glob('/sys/block/sd*') +
|
227
|
+
Dir.glob('/sys/block/xvd*')).each do |sd_dev|
|
228
|
+
File.open("#{@output_dir}/block-#{File.basename(sd_dev)}.log", "w") do |f|
|
229
|
+
f.puts("## ls -l #{sd_dev}")
|
230
|
+
f.puts(`ls -l #{sd_dev}`)
|
231
|
+
f.puts("")
|
232
|
+
['device/queue_depth',
|
233
|
+
'device/queue_type',
|
234
|
+
'device/iorequest_cnt',
|
235
|
+
'device/vendor',
|
236
|
+
'queue/scheduler',
|
237
|
+
'queue/nr_requests',
|
238
|
+
'queue/rq_affinity',
|
239
|
+
'queue/nomerges',
|
240
|
+
'queue/add_random',
|
241
|
+
'queue/rotational',
|
242
|
+
'queue/max_hw_sectors_kb',
|
243
|
+
'queue/physical_block_size',
|
244
|
+
'queue/optimal_io_size',
|
245
|
+
].each do |entity|
|
246
|
+
path = "#{sd_dev}/#{entity}"
|
247
|
+
if File.exists?(path)
|
248
|
+
f.puts("## #{path}")
|
249
|
+
f.puts(`cat #{path}`)
|
250
|
+
f.puts("")
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
def save_disk_info()
|
258
|
+
File.open("#{@output_dir}/disk-by-path.log", "w") do |f|
|
259
|
+
f.puts(`ls -l /dev/disk/by-path/`)
|
260
|
+
end
|
261
|
+
|
262
|
+
File.open("#{@output_dir}/disk-by-uuid.log", "w") do |f|
|
263
|
+
f.puts(`ls -l /dev/disk/by-uuid/`)
|
264
|
+
end
|
265
|
+
|
266
|
+
File.open("#{@output_dir}/disk-by-id.log", "w") do |f|
|
267
|
+
f.puts(`ls -l /dev/disk/by-id/`)
|
268
|
+
end
|
269
|
+
|
270
|
+
File.open("#{@output_dir}/disk-multipath.log", "w") do |f|
|
271
|
+
f.puts(`/sbin/multipath -ll 2>&1`)
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
def save_pci_info()
|
276
|
+
lspci_bin = find_executable("lspci")
|
277
|
+
|
278
|
+
if lspci_bin
|
279
|
+
File.open("#{@output_dir}/lspci.log", "w") do |f|
|
280
|
+
f.puts(`#{lspci_bin} -D -vvv`)
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
Dir.glob("/sys/devices/pci*/*/*/vendor") do |vendor|
|
285
|
+
pcidir = File.dirname(vendor)
|
286
|
+
|
287
|
+
prefix = [File.basename(File.dirname(File.dirname(pcidir))),
|
288
|
+
File.basename(File.dirname(pcidir)),
|
289
|
+
File.basename(pcidir)].join("-")
|
290
|
+
|
291
|
+
File.open("#{@output_dir}/#{prefix}.log", "w") do |f|
|
292
|
+
f.puts("## ls -l #{pcidir}")
|
293
|
+
f.puts(`ls -l #{pcidir}`)
|
294
|
+
f.puts("")
|
295
|
+
Dir.entries(pcidir).select do |filename|
|
296
|
+
! (["remove", "reset", "rescan", "rom", "uevent", "config",
|
297
|
+
"vpd"
|
298
|
+
].include?(filename) ||
|
299
|
+
filename =~ /\Aresource\d+\Z/ ||
|
300
|
+
filename =~ /\Aresource\d+_wc\Z/ # DDN device specific node (?)
|
301
|
+
)
|
302
|
+
end.each do |filename|
|
303
|
+
path = File.expand_path(filename, pcidir)
|
304
|
+
next unless File.file?(path)
|
305
|
+
content = read_file(path)
|
306
|
+
if content
|
307
|
+
f.puts("## #{path}")
|
308
|
+
f.puts(content)
|
309
|
+
f.puts("")
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
msi_irqs_dir = File.expand_path("msi_irqs", pcidir)
|
314
|
+
if File.directory?(msi_irqs_dir)
|
315
|
+
f.puts("## ls -l #{msi_irqs_dir}")
|
316
|
+
f.puts(`ls -l #{msi_irqs_dir}`)
|
317
|
+
f.puts("")
|
318
|
+
|
319
|
+
Dir.glob("#{msi_irqs_dir}/*/mode").each do |mode_path|
|
320
|
+
content = read_file(mode_path)
|
321
|
+
f.puts("## #{mode_path}")
|
322
|
+
f.puts(content)
|
323
|
+
f.puts("")
|
324
|
+
end
|
325
|
+
end
|
326
|
+
end
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
330
|
+
def save_module_info()
|
331
|
+
modules = []
|
332
|
+
|
333
|
+
if lsmod_bin = find_executable("lsmod")
|
334
|
+
File.open("#{@output_dir}/lsmod.log", "w") do |f|
|
335
|
+
content = `#{lsmod_bin}`
|
336
|
+
f.puts(content)
|
337
|
+
|
338
|
+
lines = content.split("\n")
|
339
|
+
lines.shift # omit 1st line (label)
|
340
|
+
modules = lines.map do |line|
|
341
|
+
line.split[0]
|
342
|
+
end
|
343
|
+
end
|
344
|
+
else
|
345
|
+
return
|
346
|
+
end
|
347
|
+
|
348
|
+
modinfo_bin = find_executable("modinfo")
|
349
|
+
|
350
|
+
Dir.glob("/sys/module/*/parameters") do |params_dir|
|
351
|
+
module_name = File.basename(File.dirname(params_dir))
|
352
|
+
next unless modules.include?(module_name)
|
353
|
+
|
354
|
+
File.open("#{@output_dir}/module-#{module_name}.log", "w") do |f|
|
355
|
+
Dir.glob("#{params_dir}/*").each do |param_file|
|
356
|
+
param_name = File.basename(param_file)
|
357
|
+
# blacklisting
|
358
|
+
next if module_name == "apparmor" && param_name == "audit"
|
359
|
+
next if module_name == "apparmor" && param_name == "mode"
|
360
|
+
|
361
|
+
content = read_file(param_file)
|
362
|
+
f.puts("## #{param_file}")
|
363
|
+
f.puts(content)
|
364
|
+
f.puts("")
|
365
|
+
end
|
366
|
+
|
367
|
+
if modinfo_bin
|
368
|
+
content = `#{modinfo_bin} #{module_name}`
|
369
|
+
f.puts("## modinfo #{module_name}")
|
370
|
+
f.puts(content)
|
371
|
+
f.puts("")
|
372
|
+
end
|
373
|
+
end
|
374
|
+
end
|
375
|
+
end
|
376
|
+
|
377
|
+
def save_distro_info()
|
378
|
+
File.open("#{@output_dir}/distro.log", "w") do |f|
|
379
|
+
if system("which uname >/dev/null 2>&1")
|
380
|
+
content = `uname -a`
|
381
|
+
f.puts("## uname -a")
|
382
|
+
f.puts(content)
|
383
|
+
f.puts("")
|
384
|
+
end
|
385
|
+
|
386
|
+
if system("which lsb_release >/dev/null 2>&1")
|
387
|
+
content = `lsb_release -a 2>/dev/null`
|
388
|
+
f.puts("## lsb_release -a")
|
389
|
+
f.puts(content)
|
390
|
+
f.puts("")
|
391
|
+
end
|
392
|
+
|
393
|
+
if File.exists?("/etc/debian_version")
|
394
|
+
content = read_file("/etc/debian_version")
|
395
|
+
f.puts("## /etc/debian_version")
|
396
|
+
f.puts(content)
|
397
|
+
f.puts("")
|
398
|
+
end
|
399
|
+
|
400
|
+
if File.exists?("/etc/redhat-release")
|
401
|
+
content = read_file("/etc/redhat-release")
|
402
|
+
f.puts("## /etc/redhat-release")
|
403
|
+
f.puts(content)
|
404
|
+
f.puts("")
|
405
|
+
end
|
406
|
+
end
|
407
|
+
end
|
408
|
+
|
409
|
+
def save_sysctl_info()
|
410
|
+
sysctl_bin = find_executable("sysctl")
|
411
|
+
|
412
|
+
if sysctl_bin
|
413
|
+
File.open("#{@output_dir}/sysctl.log", "w") do |f|
|
414
|
+
content = `#{sysctl_bin} -a`
|
415
|
+
f.puts("## sysctl -a")
|
416
|
+
f.puts(content)
|
417
|
+
f.puts("")
|
418
|
+
end
|
419
|
+
end
|
420
|
+
end
|
421
|
+
|
422
|
+
def save_dmidecode_info()
|
423
|
+
dmidecode_bin = find_executable("dmidecode")
|
424
|
+
|
425
|
+
if dmidecode_bin
|
426
|
+
File.open("#{@output_dir}/dmidecode.log", "w") do |f|
|
427
|
+
content = `#{dmidecode_bin} 2>&1`
|
428
|
+
f.puts("## dmidecode")
|
429
|
+
f.puts(content)
|
430
|
+
f.puts("")
|
431
|
+
end
|
432
|
+
end
|
433
|
+
end
|
434
|
+
|
435
|
+
def save_megaraid_info(megacli_bin)
|
436
|
+
File.open("#{@output_dir}/megaraid.log", "w") do |f|
|
437
|
+
params_list = ["-AdpCount",
|
438
|
+
"-AdpAllinfo -aALL",
|
439
|
+
"-AdpBbuCmd -aALL",
|
440
|
+
"-LDInfo -Lall -aALL",
|
441
|
+
"-PDList -aALL"
|
442
|
+
].each do |params|
|
443
|
+
f.puts("## #{megacli_bin} #{params}")
|
444
|
+
f.puts(`#{megacli_bin} #{params}`.gsub(/\r/, ""))
|
445
|
+
f.puts("")
|
446
|
+
end
|
447
|
+
end
|
448
|
+
end
|
449
|
+
end
|
450
|
+
|
451
|
+
end # module Command
|
452
|
+
end # module PerfMonger
|
453
|
+
|