linux_stat 0.4.2 → 0.6.3
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/LICENSE.txt +21 -0
- data/README.md +354 -57
- data/bin/console +1 -1
- data/bin/setup +0 -2
- data/{bin → exe}/linuxstat.rb +7 -9
- data/ext/fs_stat/fs_stat.c +2 -0
- data/ext/sysconf/sysconf.c +30 -2
- data/ext/utsname/utsname.c +2 -0
- data/lib/linux_stat.rb +32 -4
- data/lib/linux_stat/cpu.rb +14 -5
- data/lib/linux_stat/kernel.rb +1 -2
- data/lib/linux_stat/mounts.rb +152 -1
- data/lib/linux_stat/net.rb +107 -1
- data/lib/linux_stat/prettify_bytes.rb +75 -0
- data/lib/linux_stat/process_info.rb +107 -48
- data/lib/linux_stat/user.rb +298 -0
- data/lib/linux_stat/version.rb +1 -1
- metadata +11 -6
@@ -0,0 +1,75 @@
|
|
1
|
+
module LinuxStat
|
2
|
+
module PrettifyBytes
|
3
|
+
class << self
|
4
|
+
# Converts a number to decimal byte units and outputs with the metric prefix
|
5
|
+
# For example,
|
6
|
+
#
|
7
|
+
# LinuxStat::PrettifyBytes.convert_decimal(1000) # => "1.0 kilobyte"
|
8
|
+
# LinuxStat::PrettifyBytes.convert_decimal(1000 ** 3) # => "1.0 gigabyte"
|
9
|
+
# LinuxStat::PrettifyBytes.convert_decimal(1024 ** 3) # => "1.07 gigabytes"
|
10
|
+
def convert_decimal(n)
|
11
|
+
@@d_units ||= %W(#{''} kilo mega giga tera peta exa zetta)
|
12
|
+
.map.with_index { |x, i| [x, 1000.**(i + 1)] }
|
13
|
+
unit = @@d_units.find { |x| n < x[1] } || ['yotta'.freeze, 10 ** 27]
|
14
|
+
|
15
|
+
converted = n.fdiv(unit[1] / 1000).round(2)
|
16
|
+
"#{pad_left(converted)} #{unit[0]}byte#{?s.freeze if converted != 1}"
|
17
|
+
end
|
18
|
+
|
19
|
+
# Converts a number to binary byte units and outputs with the IEC prefix
|
20
|
+
# For example,
|
21
|
+
#
|
22
|
+
# LinuxStat::PrettifyBytes.convert_binary(1000) # => "1000.0 bytes"
|
23
|
+
# LinuxStat::PrettifyBytes.convert_binary(1000 ** 3) # => "953.67 mebibytes"
|
24
|
+
# LinuxStat::PrettifyBytes.convert_binary(1024 ** 3) # => "1.0 gibibyte"
|
25
|
+
def convert_binary(n)
|
26
|
+
@@b_units ||= %W(#{''} kibi mebi gibi tebi pebi exbi zebi)
|
27
|
+
.map.with_index { |x, i| [x, 1024.**(i + 1)] }
|
28
|
+
unit = @@b_units.find { |x| n < x[1] } || ['yobi'.freeze, 10 ** 27]
|
29
|
+
|
30
|
+
converted = n.fdiv(unit[1] / 1024).round(2)
|
31
|
+
"#{pad_left(converted)} #{unit[0]}byte#{?s.freeze if converted != 1}"
|
32
|
+
end
|
33
|
+
|
34
|
+
# Converts a number to decimal byte units
|
35
|
+
# For example,
|
36
|
+
#
|
37
|
+
# LinuxStat::PrettifyBytes.convert_short_decimal(1000) # => "1.0 kB"
|
38
|
+
# LinuxStat::PrettifyBytes.convert_short_decimal(1000 ** 3) # => "1.0 GB"
|
39
|
+
# LinuxStat::PrettifyBytes.convert_short_decimal(1024 ** 3) # => "1.07 GB"
|
40
|
+
def convert_short_decimal(n)
|
41
|
+
@@sd_units ||= %W(#{''} k M G T P E Z)
|
42
|
+
.map.with_index { |x, i| [x, 1000.**(i + 1)] }
|
43
|
+
unit = @@sd_units.find { |x| n < x[1] } || [?Y.freeze, 10 ** 27]
|
44
|
+
|
45
|
+
converted = n.fdiv(unit[1] / 1000).round(2)
|
46
|
+
"#{pad_left(converted)} #{unit[0]}B"
|
47
|
+
end
|
48
|
+
|
49
|
+
# Converts a number to binary byte units
|
50
|
+
# For example,
|
51
|
+
#
|
52
|
+
# LinuxStat::PrettifyBytes.convert_short_binary(1000) # => "1000 B"
|
53
|
+
# LinuxStat::PrettifyBytes.convert_short_binary(1000 ** 3) # => "953.67 MiB"
|
54
|
+
# LinuxStat::PrettifyBytes.convert_short_binary(1024 ** 3) # => "1.0 GiB"
|
55
|
+
def convert_short_binary(n)
|
56
|
+
return "#{n} B" if n < 1024
|
57
|
+
|
58
|
+
@@sb_units ||= %W(#{''} K M G T P E Z)
|
59
|
+
.map.with_index { |x, i| [x, 1024.**(i + 1)] }
|
60
|
+
unit = @@sb_units.find { |x| n < x[1] } || [?Y.freeze, 1024 ** 9]
|
61
|
+
|
62
|
+
converted = n.fdiv(unit[1] / 1024).round(2)
|
63
|
+
"#{pad_left(converted)} #{unit[0]}iB"
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
def pad_left(n, mantissa_length = 2)
|
68
|
+
n = n.round(mantissa_length)
|
69
|
+
exp, mant = n.to_s.split(?..freeze)
|
70
|
+
m = mant.length < mantissa_length ? mant + ?0.freeze * (mantissa_length - mant.length) : mant
|
71
|
+
exp + ?..freeze + m
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -70,10 +70,10 @@ module LinuxStat
|
|
70
70
|
# By default it is the id of the current process ($$)
|
71
71
|
#
|
72
72
|
# It retuns the memory, virtual memory, and resident memory of the process.
|
73
|
-
# All values are in
|
73
|
+
# All values are in kilobytes.
|
74
74
|
#
|
75
75
|
# The output is a Hash. For example, a sample output:
|
76
|
-
# {:memory=>
|
76
|
+
# {:memory=>8515.584, :virtual_memory=>79781.888, :resident_memory=>13955.072}
|
77
77
|
#
|
78
78
|
# Note:
|
79
79
|
# If you need only memory usage of a process, run LinuxStat::ProcessInfo.memory(pid)
|
@@ -85,34 +85,19 @@ module LinuxStat
|
|
85
85
|
#
|
86
86
|
# If the info isn't available it will return an empty Hash.
|
87
87
|
def mem_stat(pid = $$)
|
88
|
-
|
89
|
-
|
88
|
+
statm = "/proc/#{pid}/statm".freeze
|
89
|
+
return {} unless File.readable?(statm)
|
90
90
|
|
91
|
-
|
92
|
-
IO.read(stat_file).split
|
93
|
-
else
|
94
|
-
[]
|
95
|
-
end
|
91
|
+
data = IO.read(statm).split
|
96
92
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
[]
|
101
|
-
end
|
102
|
-
|
103
|
-
_rss_anon = status.find { |x| x.start_with?('RssAnon') }
|
104
|
-
rss_anon = _rss_anon ? _rss_anon.split[1].to_i : nil
|
105
|
-
|
106
|
-
_virtual_memory = stat[22]
|
107
|
-
vm = _virtual_memory ? _virtual_memory.to_i.fdiv(1024).to_i : nil
|
108
|
-
|
109
|
-
_vm_rss = status.find { |x| x.start_with?('VmRSS') }
|
110
|
-
vm_rss = _vm_rss ? _vm_rss.split[1].to_i : nil
|
93
|
+
_rss_anon = (data[1] && data[2]) ? data[1].to_i.-(data[2].to_i).*(pagesize).fdiv(1000) : nil
|
94
|
+
_virtual_memory = data[0] ? data[0].to_i*(pagesize).fdiv(1000) : nil
|
95
|
+
_resident_memory = data[1] ? data[1].to_i.*(pagesize).fdiv(1000) : nil
|
111
96
|
|
112
97
|
{
|
113
|
-
memory:
|
114
|
-
virtual_memory:
|
115
|
-
resident_memory:
|
98
|
+
memory: _rss_anon,
|
99
|
+
virtual_memory: _virtual_memory,
|
100
|
+
resident_memory: _resident_memory
|
116
101
|
}
|
117
102
|
end
|
118
103
|
|
@@ -121,16 +106,17 @@ module LinuxStat
|
|
121
106
|
# By default it is the id of the current process ($$)
|
122
107
|
#
|
123
108
|
# It retuns the memory of the process.
|
124
|
-
# The value is in
|
109
|
+
# The value is in kilobytes.
|
125
110
|
# The output is an Integer. For example, a sample output:
|
126
|
-
#
|
111
|
+
# 8523.776
|
127
112
|
#
|
128
113
|
# If the info isn't available it will return nil.
|
129
114
|
def memory(pid = $$)
|
130
|
-
|
131
|
-
|
115
|
+
file = "/proc/#{pid}/statm".freeze
|
116
|
+
return nil unless File.readable?(file)
|
132
117
|
|
133
|
-
|
118
|
+
data = IO.read(file).split
|
119
|
+
(data[1] && data[2]) ? data[1].to_i.-(data[2].to_i).*(pagesize).fdiv(1000) : nil
|
134
120
|
end
|
135
121
|
|
136
122
|
# virtual_memory(pid = $$)
|
@@ -138,14 +124,17 @@ module LinuxStat
|
|
138
124
|
# By default it is the id of the current process ($$)
|
139
125
|
#
|
140
126
|
# It retuns the virtual memory for the process.
|
141
|
-
# The value is in
|
127
|
+
# The value is in kilobytes.
|
142
128
|
# The output is an Integer. For example, a sample output:
|
143
|
-
#
|
129
|
+
# 79781.888
|
144
130
|
#
|
145
131
|
# If the info isn't available it will return nil.
|
146
132
|
def virtual_memory(pid = $$)
|
147
|
-
|
148
|
-
|
133
|
+
file = "/proc/#{pid}/statm".freeze
|
134
|
+
return nil unless File.readable?(file)
|
135
|
+
|
136
|
+
_virtual_memory = IO.read(file).split[0]
|
137
|
+
_virtual_memory ? _virtual_memory.to_i.*(pagesize).fdiv(1000) : nil
|
149
138
|
end
|
150
139
|
|
151
140
|
# resident_memory(pid = $$)
|
@@ -153,21 +142,24 @@ module LinuxStat
|
|
153
142
|
# By default it is the id of the current process ($$)
|
154
143
|
#
|
155
144
|
# It retuns the resident memory for the process.
|
156
|
-
# The value is in
|
145
|
+
# The value is in kilobytes.
|
157
146
|
# The output is an Integer. For example, a sample output:
|
158
|
-
#
|
147
|
+
# 13996.032
|
159
148
|
#
|
160
149
|
# If the info isn't available it will return nil.
|
161
150
|
def resident_memory(pid = $$)
|
162
|
-
|
163
|
-
|
151
|
+
file = "/proc/#{pid}/statm".freeze
|
152
|
+
return nil unless File.readable?(file)
|
164
153
|
|
165
|
-
_vm_rss
|
154
|
+
_vm_rss = IO.read(file).split[1]
|
155
|
+
_vm_rss ? _vm_rss.to_i.*(pagesize).fdiv(1000) : nil
|
166
156
|
end
|
167
157
|
|
168
|
-
# cpu_stat(pid: $$, sleep: 0.
|
158
|
+
# cpu_stat(pid: $$, sleep: 1.0 / LinuxStat::Sysconf.sc_clk_tck)
|
169
159
|
# Where pid is the process ID and sleep time is the interval between measurements.
|
170
|
-
#
|
160
|
+
#
|
161
|
+
# By default it is the id of the current process ($$), and sleep is LinuxStat::Sysconf.sc_clk_tck
|
162
|
+
# The smallest amount of available sleep time is 1.0 / LinuxStat::Sysconf.sc_clk_tck.
|
171
163
|
#
|
172
164
|
# Note 1:
|
173
165
|
# Do note that the sleep time can slow down your application.
|
@@ -197,7 +189,7 @@ module LinuxStat
|
|
197
189
|
#
|
198
190
|
# The :last_executed_cpu also returns an Integer indicating
|
199
191
|
# the last executed cpu of the process.
|
200
|
-
def cpu_stat(pid: $$, sleep:
|
192
|
+
def cpu_stat(pid: $$, sleep: ticks_to_ms)
|
201
193
|
file = "/proc/#{pid}/stat"
|
202
194
|
return {} unless File.readable?(file)
|
203
195
|
|
@@ -229,9 +221,11 @@ module LinuxStat
|
|
229
221
|
}
|
230
222
|
end
|
231
223
|
|
232
|
-
# cpu_usage(pid: $$, sleep: 0.
|
224
|
+
# cpu_usage(pid: $$, sleep: 1.0 / LinuxStat::Sysconf.sc_clk_tck)
|
233
225
|
# Where pid is the process ID and sleep time is the interval between measurements.
|
234
|
-
#
|
226
|
+
#
|
227
|
+
# By default it is the id of the current process ($$), and sleep is 1.0 / LinuxStat::Sysconf.sc_clk_tck
|
228
|
+
# The smallest amount of available sleep time is LinuxStat::Sysconf.sc_clk_tck.
|
235
229
|
#
|
236
230
|
# It retuns the CPU usage in Float.
|
237
231
|
# For example:
|
@@ -241,7 +235,7 @@ module LinuxStat
|
|
241
235
|
# But if the info isn't available, it will return nil.
|
242
236
|
#
|
243
237
|
# This method is more efficient than running LinuxStat::ProcessInfo.cpu_stat()
|
244
|
-
def cpu_usage(pid: $$, sleep:
|
238
|
+
def cpu_usage(pid: $$, sleep: ticks_to_ms)
|
245
239
|
file = "/proc/#{pid}/stat"
|
246
240
|
return nil unless File.readable?(file)
|
247
241
|
|
@@ -281,7 +275,8 @@ module LinuxStat
|
|
281
275
|
file = "/proc/#{pid}/stat".freeze
|
282
276
|
return nil unless File.readable?(file)
|
283
277
|
|
284
|
-
IO.read(file).split[19]
|
278
|
+
data = IO.read(file).split[19]
|
279
|
+
data ? data.to_i : nil
|
285
280
|
end
|
286
281
|
|
287
282
|
# last_executed_cpu(pid = $$)
|
@@ -298,13 +293,77 @@ module LinuxStat
|
|
298
293
|
file = "/proc/#{pid}/stat".freeze
|
299
294
|
return nil unless File.readable?(file)
|
300
295
|
|
301
|
-
IO.read(
|
296
|
+
IO.read(file).split[38].to_i
|
297
|
+
end
|
298
|
+
|
299
|
+
# uid(pid = $$)
|
300
|
+
# returns the UIDs of the process as an Array of Integers.
|
301
|
+
#
|
302
|
+
# If the info isn't available it returns an empty Array.
|
303
|
+
def uid(pid = $$)
|
304
|
+
file = "/proc/#{pid}/status".freeze
|
305
|
+
return nil unless File.readable?(file)
|
306
|
+
|
307
|
+
data = IO.readlines(file.freeze).find { |x|
|
308
|
+
x[/Uid.*\d*/]
|
309
|
+
}.to_s.split.drop(1)
|
310
|
+
|
311
|
+
{
|
312
|
+
real: data[0].to_i,
|
313
|
+
effective: data[1].to_i,
|
314
|
+
saved_set: data[2].to_i,
|
315
|
+
filesystem_uid: data[3].to_i
|
316
|
+
}
|
317
|
+
end
|
318
|
+
|
319
|
+
# gid(pid = $$)
|
320
|
+
# returns the GIDs of the process as an Hash containing the following data:
|
321
|
+
# :real, :effective, :saved_set, :filesystem_uid
|
322
|
+
#
|
323
|
+
# If the info isn't available it returns an empty Hash.
|
324
|
+
def gid(pid = $$)
|
325
|
+
file = "/proc/#{pid}/status".freeze
|
326
|
+
return nil unless File.readable?(file)
|
327
|
+
|
328
|
+
data = IO.readlines(file.freeze).find { |x|
|
329
|
+
x[/Gid.*\d*/]
|
330
|
+
}.split.drop(1)
|
331
|
+
|
332
|
+
{
|
333
|
+
real: data[0].to_i,
|
334
|
+
effective: data[1].to_i,
|
335
|
+
saved_set: data[2].to_i,
|
336
|
+
filesystem_uid: data[3].to_i
|
337
|
+
}
|
338
|
+
end
|
339
|
+
|
340
|
+
# owner(pid = $$)
|
341
|
+
# Returns the owner of the process
|
342
|
+
# But if the status is not available, it will return an empty frozen String.
|
343
|
+
def owner(pid = $$)
|
344
|
+
file = "/proc/#{pid}/status".freeze
|
345
|
+
return ''.freeze unless File.readable?(file)
|
346
|
+
|
347
|
+
gid = IO.readlines(file.freeze).find { |x|
|
348
|
+
x[/Gid.*\d*/]
|
349
|
+
}.split.drop(1)[2].to_i
|
350
|
+
|
351
|
+
LinuxStat::User.username_by_gid(gid)
|
302
352
|
end
|
303
353
|
|
304
354
|
private
|
305
355
|
def get_ticks
|
306
356
|
@@ticks ||= Sysconf.sc_clk_tck
|
307
357
|
end
|
358
|
+
|
359
|
+
# Just to avoid multiple calculations!...
|
360
|
+
def ticks_to_ms
|
361
|
+
@@ms ||= 1.0 / get_ticks
|
362
|
+
end
|
363
|
+
|
364
|
+
def pagesize
|
365
|
+
@@pagesize ||= LinuxStat::Sysconf.pagesize
|
366
|
+
end
|
308
367
|
end
|
309
368
|
end
|
310
369
|
end
|
@@ -0,0 +1,298 @@
|
|
1
|
+
module LinuxStat
|
2
|
+
module User
|
3
|
+
class << self
|
4
|
+
# Returns an array of users as string
|
5
|
+
# For example:
|
6
|
+
# ["root", "bin", "daemon", "mail", "ftp", "http", "nobody"]
|
7
|
+
# But if the status isn't available it will return an empty Array.
|
8
|
+
def list
|
9
|
+
return [] unless passwd_readable?
|
10
|
+
passwd.map { |x| x[/.+?:/][0..-2].freeze }
|
11
|
+
end
|
12
|
+
|
13
|
+
# Returns all the Group ids directories as Hash.
|
14
|
+
# For example:
|
15
|
+
# {:root=>{:uid=>0, :gid=>0}, :bin=>{:uid=>1, :gid=>1}, :daemon=>{:uid=>2, :gid=>2}, :mail=>{:uid=>8, :gid=>12}, :ftp=>{:uid=>14, :gid=>11}}
|
16
|
+
#
|
17
|
+
# But if the status isn't available it will return an empty Hash.
|
18
|
+
def ids
|
19
|
+
return {} unless passwd_readable?
|
20
|
+
passwd_splitted.reduce({}) { |h, x|
|
21
|
+
h.merge!(x[0].to_sym => {
|
22
|
+
uid: x[2].to_i, gid: x[3].to_i
|
23
|
+
})
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
# Returns all the user IDs as Hash.
|
28
|
+
# For example:
|
29
|
+
# LinuxStat::User.uids
|
30
|
+
# => {:root=>0, :bin=>1, :daemon=>2, :mail=>8, :ftp=>14}
|
31
|
+
#
|
32
|
+
# But if the status isn't available it will return an empty Hash.
|
33
|
+
def uids
|
34
|
+
return {} unless passwd_readable?
|
35
|
+
passwd_splitted.reduce({}) { |h, x|
|
36
|
+
h.merge!(x[0].to_sym => x[2].to_i)
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
# Returns all the Group identifiers as Hash.
|
41
|
+
# For example:
|
42
|
+
# LinuxStat::User.gids
|
43
|
+
# => {:root=>0, :bin=>1, :daemon=>2, :mail=>12, :ftp=>11}
|
44
|
+
#
|
45
|
+
# But if the status isn't available it will return an empty Hash.
|
46
|
+
def gids
|
47
|
+
return {} unless passwd_readable?
|
48
|
+
passwd_splitted.reduce({}) { |h, x|
|
49
|
+
h.merge!(x[0].to_sym => x[3].to_i)
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
53
|
+
# Returns all the home directories as Hash.
|
54
|
+
# For example:
|
55
|
+
# LinuxStat::User.home_directories
|
56
|
+
# => {:root=>"/root", :bin=>"/", :daemon=>"/", :mail=>"/var/spool/mail", :ftp=>"/srv/ftp", :http=>"/srv/http", :nobody=>"/"}
|
57
|
+
#
|
58
|
+
# But if the status isn't available it will return an empty Hash.
|
59
|
+
def home_directories
|
60
|
+
return {} unless passwd_readable?
|
61
|
+
passwd.reduce({}) { |h, x|
|
62
|
+
splitted = x.split(?:)
|
63
|
+
h.merge!(splitted[0].to_sym => splitted[5])
|
64
|
+
}
|
65
|
+
end
|
66
|
+
|
67
|
+
# Returns the user ID as integer
|
68
|
+
# It directly calls LinuxStat::Sysconf.get_uid and LinuxStat::Sysconf.get_gid
|
69
|
+
# and then reads /etc/passwd and matches the values with UID and GID.
|
70
|
+
#
|
71
|
+
# It doesn't get affected with the assignment of USER environment variable
|
72
|
+
# If either /etc/passwd is readable or LinuxStat::Sysconf.get_login() is not empty.
|
73
|
+
#
|
74
|
+
# But if /etc/passwd isn't readable (which is weird), it will fall back to sysconf.h's get_login()
|
75
|
+
# It that's not available, like in docker, falls back to ENV['USER].to_s
|
76
|
+
#
|
77
|
+
# Note that this is not cached or memoized so use this at your own processing expense.
|
78
|
+
# It should return the username under most robust circumstances.
|
79
|
+
# But if nothing is available for some reason, it will return an empty String.
|
80
|
+
def get_user
|
81
|
+
unless passwd_readable?
|
82
|
+
_l = LinuxStat::Sysconf.get_login().freeze
|
83
|
+
return _l.empty? ? ENV['USER'.freeze].to_s : _l
|
84
|
+
end
|
85
|
+
|
86
|
+
uid, gid = LinuxStat::Sysconf.get_uid, LinuxStat::Sysconf.get_gid
|
87
|
+
|
88
|
+
username = ''
|
89
|
+
passwd.each { |x|
|
90
|
+
splitted = x.split(?:).freeze
|
91
|
+
if splitted[2].to_i == uid && splitted[3].to_i == gid
|
92
|
+
username = splitted[0]
|
93
|
+
break
|
94
|
+
end
|
95
|
+
}
|
96
|
+
username
|
97
|
+
end
|
98
|
+
|
99
|
+
# Returns the user ID as integer
|
100
|
+
# It directly calls LinuxStat::Sysconf.get_uid
|
101
|
+
def get_uid
|
102
|
+
LinuxStat::Sysconf.get_uid
|
103
|
+
end
|
104
|
+
|
105
|
+
# Returns the group ID as integer
|
106
|
+
# It directly calls LinuxStat::Sysconf.get_uid
|
107
|
+
def get_gid
|
108
|
+
LinuxStat::Sysconf.get_gid
|
109
|
+
end
|
110
|
+
|
111
|
+
# Returns the effective user ID as integer
|
112
|
+
# It directly calls LinuxStat::Sysconf.get_euid
|
113
|
+
def get_euid
|
114
|
+
LinuxStat::Sysconf.get_euid
|
115
|
+
end
|
116
|
+
|
117
|
+
# Calls LinuxStat::Sysconf.get_login()
|
118
|
+
# The username is returned as a String.
|
119
|
+
# It doesn't get affected by ENV['USER]
|
120
|
+
#
|
121
|
+
# But if the name isn't available (say inside a container), it will return an empty String.
|
122
|
+
# This is meant for speed but not for reliability.
|
123
|
+
# To get more reliable output, you might try LinuxStat::User.get_user()
|
124
|
+
def get_login
|
125
|
+
LinuxStat::Sysconf.get_login
|
126
|
+
end
|
127
|
+
|
128
|
+
# def usernames_by_uid(gid = get_uid)
|
129
|
+
# Where uid is the group id of the user. By default it's the uid of the current user.
|
130
|
+
#
|
131
|
+
# It returns an Array containing the username corresponding to the uid.
|
132
|
+
#
|
133
|
+
# For example:
|
134
|
+
# LinuxStat::User.usernames_by_uid(1001)
|
135
|
+
# => ["userx", "usery"]
|
136
|
+
#
|
137
|
+
# But if the info isn't available it will return an empty Array.
|
138
|
+
def usernames_by_uid(uid = get_uid)
|
139
|
+
return [] unless passwd_readable?
|
140
|
+
|
141
|
+
usernames = []
|
142
|
+
passwd_splitted.each { |x|
|
143
|
+
usernames << x[0] if x[2].to_i == uid
|
144
|
+
}
|
145
|
+
usernames
|
146
|
+
end
|
147
|
+
|
148
|
+
# def username_by_gid(gid = get_gid)
|
149
|
+
# Where gid is the group id of the user. By default it's the gid of the current user.
|
150
|
+
#
|
151
|
+
# It returns a String cotaining the username corresponding to the gid
|
152
|
+
# But if the info isn't available it will return an empty frozen String.
|
153
|
+
def username_by_gid(gid = get_gid)
|
154
|
+
return ''.freeze unless passwd_readable?
|
155
|
+
|
156
|
+
username = ''
|
157
|
+
passwd.each do |x|
|
158
|
+
splitted = x.split(?:.freeze)
|
159
|
+
if splitted[2].to_i == gid
|
160
|
+
username = splitted[0]
|
161
|
+
break
|
162
|
+
end
|
163
|
+
end
|
164
|
+
username
|
165
|
+
end
|
166
|
+
|
167
|
+
# gid_by_username(username = get_user)
|
168
|
+
# Where username is the username to look for, by default it is the current user.
|
169
|
+
#
|
170
|
+
# It returns the gid by the username.
|
171
|
+
# For example:
|
172
|
+
# LinuxStat::User.gid_by_username('root')
|
173
|
+
# => "0"
|
174
|
+
#
|
175
|
+
# The return type is Integer.
|
176
|
+
# But if user passed doesn't exist or if the info isn't available, it will return nil.
|
177
|
+
def gid_by_username(username = get_user)
|
178
|
+
return nil unless passwd_readable?
|
179
|
+
|
180
|
+
gid = nil
|
181
|
+
passwd.each do |x|
|
182
|
+
splitted = x.split(?:.freeze)
|
183
|
+
if splitted[0] == username
|
184
|
+
gid = splitted[3].to_i
|
185
|
+
break
|
186
|
+
end
|
187
|
+
end
|
188
|
+
gid
|
189
|
+
end
|
190
|
+
|
191
|
+
# uid_by_username(username = get_user)
|
192
|
+
# Where username is the username to look for, by default it is the current user.
|
193
|
+
#
|
194
|
+
# It returns the uid by the username.
|
195
|
+
# For example:
|
196
|
+
# LinuxStat::User.uid_by_username('root')
|
197
|
+
# => 0
|
198
|
+
#
|
199
|
+
# The return type is Integer.
|
200
|
+
# But if user passed doesn't exist or if the info isn't available, it will return nil.
|
201
|
+
def uid_by_username(username = get_user)
|
202
|
+
return nil unless passwd_readable?
|
203
|
+
|
204
|
+
uid = nil
|
205
|
+
passwd.each do |x|
|
206
|
+
splitted = x.split(?:.freeze)
|
207
|
+
if splitted[0] == username
|
208
|
+
uid = splitted[2].to_i
|
209
|
+
break
|
210
|
+
end
|
211
|
+
end
|
212
|
+
uid
|
213
|
+
end
|
214
|
+
|
215
|
+
# home_by_username(user = get_user)
|
216
|
+
# Where user is the name of the user.
|
217
|
+
# Returns the user's home. By default it returns the home of the current user.
|
218
|
+
#
|
219
|
+
# If the info isn't available, it will return ENV['HOME].to_s.freeze
|
220
|
+
def home_by_username(user = get_user)
|
221
|
+
return ENV['HOME'].to_s.freeze unless passwd_readable?
|
222
|
+
|
223
|
+
home = ''
|
224
|
+
passwd.each { |x|
|
225
|
+
splitted = x.split(?:)
|
226
|
+
if splitted[0] == user
|
227
|
+
home = splitted[5]
|
228
|
+
break
|
229
|
+
end
|
230
|
+
}
|
231
|
+
home
|
232
|
+
end
|
233
|
+
|
234
|
+
# home_by_uid(id = get_uid)
|
235
|
+
# Gets all the users home directory with user id.
|
236
|
+
# It returns an Array in this format:
|
237
|
+
# LinuxStat::User.homes_by_uid(1001)
|
238
|
+
# => ["/home/userx", "/home/usery"]
|
239
|
+
#
|
240
|
+
# Assuming both the users share same UID.
|
241
|
+
#
|
242
|
+
# If the info isn't available, it will return an empty Array.
|
243
|
+
def homes_by_uid(id = get_uid)
|
244
|
+
return [] unless passwd_readable?
|
245
|
+
|
246
|
+
home = []
|
247
|
+
passwd.each do |x|
|
248
|
+
splitted = x.split(?:.freeze)
|
249
|
+
home << splitted[5] if splitted[2].to_i == id
|
250
|
+
end
|
251
|
+
home
|
252
|
+
end
|
253
|
+
|
254
|
+
# home_by_gid(id = get_uid)
|
255
|
+
# Gets the home of the user corresponding to the GID.
|
256
|
+
# It returns a String in this format:
|
257
|
+
#
|
258
|
+
# Assuming both the users share same UID.
|
259
|
+
#
|
260
|
+
# If the info isn't available, it will return an empty frozen String.
|
261
|
+
def home_by_gid(id = get_gid)
|
262
|
+
return ''.freeze unless passwd_readable?
|
263
|
+
|
264
|
+
home = ''
|
265
|
+
passwd.each do |x|
|
266
|
+
splitted = x.split(?:.freeze)
|
267
|
+
|
268
|
+
if splitted[3].to_i == id
|
269
|
+
home = splitted[5]
|
270
|
+
break
|
271
|
+
end
|
272
|
+
end
|
273
|
+
home
|
274
|
+
end
|
275
|
+
|
276
|
+
alias get_current_user get_user
|
277
|
+
|
278
|
+
private
|
279
|
+
def passwd
|
280
|
+
@@passwd_file ||= '/etc/passwd'.freeze
|
281
|
+
IO.readlines(@@passwd_file)
|
282
|
+
end
|
283
|
+
|
284
|
+
# Only use this method where we are sure that the whole array is going to be used.
|
285
|
+
# In cases like find() or a loop with `break` this is a lot of overhead.
|
286
|
+
# In cases like reduce({}) or select, this is not helpful.
|
287
|
+
def passwd_splitted
|
288
|
+
@@passwd_file ||= '/etc/passwd'.freeze
|
289
|
+
IO.readlines(@@passwd_file).map { |x| x.split(?:.freeze) }
|
290
|
+
end
|
291
|
+
|
292
|
+
def passwd_readable?
|
293
|
+
@@passwd_file ||= '/etc/passwd'.freeze
|
294
|
+
@@passwd_readable ||= File.readable?(@@passwd_file)
|
295
|
+
end
|
296
|
+
end
|
297
|
+
end
|
298
|
+
end
|