linux_stat 1.2.1 → 1.4.0
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 +4 -4
- data/README.md +275 -231
- data/exe/linuxstat.rb +15 -15
- data/lib/linux_stat.rb +1 -0
- data/lib/linux_stat/battery.rb +2 -0
- data/lib/linux_stat/bios.rb +2 -0
- data/lib/linux_stat/cpu.rb +2 -0
- data/lib/linux_stat/filesystem.rb +2 -0
- data/lib/linux_stat/kernel.rb +2 -0
- data/lib/linux_stat/memory.rb +9 -7
- data/lib/linux_stat/mounts.rb +5 -3
- data/lib/linux_stat/net.rb +6 -4
- data/lib/linux_stat/os.rb +3 -1
- data/lib/linux_stat/pci.rb +61 -56
- data/lib/linux_stat/prettify_bytes.rb +16 -9
- data/lib/linux_stat/process.rb +95 -28
- data/lib/linux_stat/process_info.rb +93 -25
- data/lib/linux_stat/swap.rb +6 -4
- data/lib/linux_stat/thermal.rb +122 -0
- data/lib/linux_stat/usb.rb +52 -47
- data/lib/linux_stat/user.rb +6 -3
- data/lib/linux_stat/version.rb +1 -1
- metadata +3 -2
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
module LinuxStat
|
|
2
|
+
# Sensors are available to /sys/class/hwmon
|
|
3
|
+
# This module just reads the files inside them to get the sensor information.
|
|
4
|
+
#
|
|
5
|
+
# https://www.kernel.org/doc/Documentation/thermal/sysfs-api.txt
|
|
6
|
+
|
|
7
|
+
module Thermal
|
|
8
|
+
class << self
|
|
9
|
+
##
|
|
10
|
+
# Get temperatures from all sensors.
|
|
11
|
+
#
|
|
12
|
+
# The return value is an Array of Hashes.
|
|
13
|
+
#
|
|
14
|
+
# It opens various files from /sys/, and it should be
|
|
15
|
+
# considered very slow.
|
|
16
|
+
#
|
|
17
|
+
# Each hash may contain information including:
|
|
18
|
+
#
|
|
19
|
+
# path, name, label
|
|
20
|
+
# temperature, temp_crit, temp_max
|
|
21
|
+
#
|
|
22
|
+
# But if the info isn't available, it will return an empty Array.
|
|
23
|
+
def temperatures
|
|
24
|
+
query_hwmon('temp'.freeze, :temperature, true)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
##
|
|
28
|
+
# Get RPM from all fans.
|
|
29
|
+
#
|
|
30
|
+
# The return value is an Array of Hashes.
|
|
31
|
+
#
|
|
32
|
+
# It opens various files from /sys/, and it should be
|
|
33
|
+
# considered very slow.
|
|
34
|
+
#
|
|
35
|
+
# Each hash may contain information including:
|
|
36
|
+
#
|
|
37
|
+
# path, name, label
|
|
38
|
+
# rpm, temp_crit, temp_max
|
|
39
|
+
#
|
|
40
|
+
# But if the info isn't available, it will return an empty Array.
|
|
41
|
+
def fans
|
|
42
|
+
query_hwmon('fan'.freeze, :rpm)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
##
|
|
46
|
+
# Counts the number of sensors (fans are not counted)
|
|
47
|
+
#
|
|
48
|
+
# The return type is an Integer.
|
|
49
|
+
def count_sensors
|
|
50
|
+
return 0 unless hwmon_readable?
|
|
51
|
+
|
|
52
|
+
Dir["/sys/class/hwmon/hwmon[0-9]*/temp[0-9]*_input".freeze].size
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
##
|
|
56
|
+
# Counts the number of fans (sensors are not counted)
|
|
57
|
+
#
|
|
58
|
+
# The return type is an Integer.
|
|
59
|
+
def count_fans
|
|
60
|
+
return 0 unless hwmon_readable?
|
|
61
|
+
|
|
62
|
+
Dir["/sys/class/hwmon/hwmon[0-9]*/fan[0-9]*_input".freeze].size
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
private
|
|
66
|
+
def hwmon_readable?
|
|
67
|
+
@@hwmon_readable ||= File.readable?("/sys/class/hwmon/")
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def query_hwmon(mon, key, div = false)
|
|
71
|
+
return [] unless hwmon_readable?
|
|
72
|
+
|
|
73
|
+
name = dir = ''.freeze
|
|
74
|
+
|
|
75
|
+
files = Dir["/sys/class/hwmon/hwmon[0-9]*/#{mon}[0-9]*_input".freeze]
|
|
76
|
+
i = -1
|
|
77
|
+
ret = []
|
|
78
|
+
|
|
79
|
+
while x = files[i += 1]
|
|
80
|
+
splitted = File.split(x)
|
|
81
|
+
path = File.join(splitted[0..-2])
|
|
82
|
+
|
|
83
|
+
n = splitted[-1][/.*_/]
|
|
84
|
+
|
|
85
|
+
label_f = "#{path}/#{n}label"
|
|
86
|
+
label = File.readable?(label_f) ? IO.read(label_f, encoding: 'ASCII-8BIT'.freeze).strip : nil
|
|
87
|
+
|
|
88
|
+
temp_crit_f = "#{path}/#{n}crit"
|
|
89
|
+
temp_crit = File.readable?(temp_crit_f) ? IO.read(temp_crit_f, encoding: 'ASCII-8BIT'.freeze).to_i : nil
|
|
90
|
+
|
|
91
|
+
temp_max_f = "#{path}/#{n}max"
|
|
92
|
+
temp_max = File.readable?(temp_max_f) ? IO.read(temp_max_f, encoding: 'ASCII-8BIT'.freeze).to_i : nil
|
|
93
|
+
|
|
94
|
+
value = File.readable?(x) ? IO.read(x).to_i : nil
|
|
95
|
+
|
|
96
|
+
if dir != path
|
|
97
|
+
dir = path
|
|
98
|
+
name_f = "#{path}/name"
|
|
99
|
+
name = File.readable?(name_f) ? IO.read(name_f, encoding: 'ASCII-8BIT'.freeze).tap(&:strip!) : ''.freeze
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
if div
|
|
103
|
+
value /= 1000.0
|
|
104
|
+
temp_max /= 1000.0 if temp_max
|
|
105
|
+
temp_crit /= 1000.0 if temp_crit
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
h = {path: path, name: name}
|
|
109
|
+
|
|
110
|
+
h.merge!(label: label) if label
|
|
111
|
+
h.merge!(key => value)
|
|
112
|
+
h.merge!(temp_crit: temp_crit) if temp_crit
|
|
113
|
+
h.merge!(temp_crit: temp_max) if temp_max
|
|
114
|
+
|
|
115
|
+
ret.push(h)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
ret
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
data/lib/linux_stat/usb.rb
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
module LinuxStat
|
|
2
|
+
# Shows various USB device related information of the current system.
|
|
3
|
+
|
|
2
4
|
module USB
|
|
3
5
|
class << self
|
|
4
6
|
##
|
|
@@ -49,72 +51,75 @@ module LinuxStat
|
|
|
49
51
|
return [] unless @@sys_usb_readable
|
|
50
52
|
|
|
51
53
|
Dir['/sys/bus/usb/devices/*/'.freeze].sort!.map! { |x|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
54
|
+
begin
|
|
55
|
+
id_vendor_file = File.join(x, 'idVendor'.freeze)
|
|
56
|
+
next unless File.readable?(id_vendor_file)
|
|
57
|
+
id_vendor = IO.read(id_vendor_file).strip
|
|
55
58
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
+
id_product_file = File.join(x, 'idProduct'.freeze)
|
|
60
|
+
next unless File.readable?(id_vendor_file)
|
|
61
|
+
id_product = IO.read(id_product_file).strip
|
|
59
62
|
|
|
60
|
-
|
|
61
|
-
|
|
63
|
+
bus_num_file = File.join(x, 'busnum'.freeze)
|
|
64
|
+
bus_num = File.readable?(bus_num_file) ? IO.read(bus_num_file).strip : ''.freeze
|
|
62
65
|
|
|
63
|
-
|
|
64
|
-
|
|
66
|
+
dev_num_file = File.join(x, 'devnum'.freeze)
|
|
67
|
+
dev_num = File.readable?(dev_num_file) ? IO.read(dev_num_file).strip : ''.freeze
|
|
65
68
|
|
|
66
|
-
|
|
67
|
-
|
|
69
|
+
serial_file = File.join(x, 'serial'.freeze)
|
|
70
|
+
serial = File.readable?(serial_file) ? IO.read(serial_file).strip : ''.freeze
|
|
68
71
|
|
|
69
|
-
|
|
70
|
-
|
|
72
|
+
product_file = File.join(x, 'product'.freeze)
|
|
73
|
+
product = File.readable?(product_file) ? IO.read(product_file).strip : ''.freeze
|
|
71
74
|
|
|
72
|
-
|
|
73
|
-
|
|
75
|
+
manufacturer_file = File.join(x, 'manufacturer'.freeze)
|
|
76
|
+
manufacturer = File.readable?(manufacturer_file) ? IO.read(manufacturer_file).strip : ''.freeze
|
|
74
77
|
|
|
75
|
-
|
|
76
|
-
|
|
78
|
+
removable_file = File.join(x, 'removable'.freeze)
|
|
79
|
+
removable = File.readable?(removable_file) ? IO.read(removable_file).strip.downcase : ''.freeze
|
|
77
80
|
|
|
78
|
-
|
|
79
|
-
|
|
81
|
+
authorized_file = File.join(x, 'authorized'.freeze)
|
|
82
|
+
authorized = File.readable?(authorized_file) ? IO.read(authorized_file).to_i : ''.freeze
|
|
80
83
|
|
|
81
|
-
|
|
82
|
-
|
|
84
|
+
b_max_power_file = File.join(x, 'bMaxPower'.freeze)
|
|
85
|
+
b_max_power = File.readable?(b_max_power_file) ? IO.read(b_max_power_file).strip : ''.freeze
|
|
83
86
|
|
|
84
|
-
|
|
85
|
-
|
|
87
|
+
b_max_packet_size0_file = File.join(x, 'bMaxPacketSize0'.freeze)
|
|
88
|
+
b_max_packet_size0 = File.readable?(b_max_packet_size0_file) ? IO.read(b_max_packet_size0_file).to_i : ''.freeze
|
|
86
89
|
|
|
87
|
-
|
|
90
|
+
query = hwdata ? query_hwdata(id_vendor, id_product) : {}
|
|
88
91
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
92
|
+
is_removable = if removable == 'removable'.freeze
|
|
93
|
+
true
|
|
94
|
+
elsif removable == 'unknown'.freeze
|
|
95
|
+
nil
|
|
96
|
+
else
|
|
97
|
+
false
|
|
98
|
+
end
|
|
96
99
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
100
|
+
ret = {
|
|
101
|
+
path: x, id: "#{id_vendor}:#{id_product}",
|
|
102
|
+
vendor_id: id_vendor, product_id: id_product
|
|
103
|
+
}
|
|
101
104
|
|
|
102
|
-
|
|
103
|
-
|
|
105
|
+
ret.merge!(bus_num: bus_num.to_i) unless bus_num.empty?
|
|
106
|
+
ret.merge!(dev_num: dev_num.to_i) unless dev_num.empty?
|
|
104
107
|
|
|
105
|
-
|
|
108
|
+
ret.merge!(serial: serial) unless serial.empty?
|
|
106
109
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
+
ret.merge!(hwdata: query) unless query.empty?
|
|
111
|
+
ret.merge!(product: product) unless product.empty?
|
|
112
|
+
ret.merge!(manufacturer: manufacturer) unless manufacturer.empty?
|
|
110
113
|
|
|
111
|
-
|
|
112
|
-
|
|
114
|
+
ret.merge!(removable: is_removable) unless is_removable.nil?
|
|
115
|
+
ret.merge!(authorized: authorized == 1)
|
|
113
116
|
|
|
114
|
-
|
|
115
|
-
|
|
117
|
+
ret.merge!(b_max_power: b_max_power) unless b_max_power.empty?
|
|
118
|
+
ret.merge!(b_max_packet_size0: b_max_packet_size0) if b_max_packet_size0
|
|
116
119
|
|
|
117
|
-
|
|
120
|
+
ret
|
|
121
|
+
rescue StandardError
|
|
122
|
+
end
|
|
118
123
|
}.tap(&:compact!)
|
|
119
124
|
end
|
|
120
125
|
|
data/lib/linux_stat/user.rb
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
module LinuxStat
|
|
2
|
+
# Shows various User related information of the current system.
|
|
3
|
+
|
|
2
4
|
module User
|
|
3
5
|
class << self
|
|
4
6
|
##
|
|
@@ -55,6 +57,7 @@ module LinuxStat
|
|
|
55
57
|
# But if the status isn't available it will return an empty Hash.
|
|
56
58
|
def gids
|
|
57
59
|
return {} unless passwd_readable?
|
|
60
|
+
|
|
58
61
|
passwd_splitted.reduce({}) { |h, x|
|
|
59
62
|
h.merge!(x[0].to_sym => x[3].to_i)
|
|
60
63
|
}
|
|
@@ -103,7 +106,7 @@ module LinuxStat
|
|
|
103
106
|
|
|
104
107
|
uid, gid = LinuxStat::Sysconf.get_uid, LinuxStat::Sysconf.get_gid
|
|
105
108
|
|
|
106
|
-
username = ''
|
|
109
|
+
username = ''.freeze
|
|
107
110
|
passwd.each { |x|
|
|
108
111
|
splitted = x.split(?:).freeze
|
|
109
112
|
if splitted[2].to_i == uid && splitted[3].to_i == gid
|
|
@@ -187,7 +190,7 @@ module LinuxStat
|
|
|
187
190
|
def username_by_gid(gid = get_gid)
|
|
188
191
|
return ''.freeze unless passwd_readable?
|
|
189
192
|
|
|
190
|
-
username = ''
|
|
193
|
+
username = ''.freeze
|
|
191
194
|
passwd.each do |x|
|
|
192
195
|
splitted = x.split(?:.freeze)
|
|
193
196
|
if splitted[2].to_i == gid
|
|
@@ -314,7 +317,7 @@ module LinuxStat
|
|
|
314
317
|
def home_by_gid(id = get_gid)
|
|
315
318
|
return ''.freeze unless passwd_readable?
|
|
316
319
|
|
|
317
|
-
home = ''
|
|
320
|
+
home = ''.freeze
|
|
318
321
|
passwd.each do |x|
|
|
319
322
|
splitted = x.split(?:.freeze)
|
|
320
323
|
|
data/lib/linux_stat/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: linux_stat
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Sourav Goswami
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2021-01-19 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: Linux only, efficient linux system utilization reporting and system monitoring
|
|
14
14
|
gem
|
|
@@ -52,6 +52,7 @@ files:
|
|
|
52
52
|
- lib/linux_stat/process.rb
|
|
53
53
|
- lib/linux_stat/process_info.rb
|
|
54
54
|
- lib/linux_stat/swap.rb
|
|
55
|
+
- lib/linux_stat/thermal.rb
|
|
55
56
|
- lib/linux_stat/usb.rb
|
|
56
57
|
- lib/linux_stat/user.rb
|
|
57
58
|
- lib/linux_stat/version.rb
|