cz_system_info 0.1.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.
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ # The CzSystemInfo module serves as a namespace only.
4
+ module CzSystemInfo
5
+ # The Memory module provides various functions that return information
6
+ # regarding the memory on your system.
7
+ module Memory
8
+ MEMORY_FILE = '/proc/meminfo'
9
+ MEMINFO_REGEX = /(.*)?:\s+?(\d+)/.freeze
10
+
11
+ private_constant :MEMORY_FILE
12
+ private_constant :MEMINFO_REGEX
13
+
14
+ # Obtain detailed memory information about your host in the form of a hash.
15
+ # Note that the exact nature of this hash is largely dependent on your
16
+ # operating system.
17
+ #
18
+ def memory
19
+ hash = {}
20
+
21
+ File.foreach(MEMORY_FILE) do |line|
22
+ key, value = MEMINFO_REGEX.match(line.chomp).captures
23
+ hash[key] = value.to_i
24
+ end
25
+
26
+ hash
27
+ end
28
+
29
+ # Total memory in bytes. By default this is only physical memory, but
30
+ # if the +extended+ option is set to true, then swap memory is included
31
+ # as part of the total.
32
+ #
33
+ def total(extended: false)
34
+ hash = memory
35
+ extended ? (hash['MemTotal'] + hash['SwapTotal']) * 1024 : hash['MemTotal'] * 1024
36
+ end
37
+
38
+ # The memory currently available, in bytes. By default this is only
39
+ # physical memory, but if the +extended+ option is set to true, then free
40
+ # swap memory is also included.
41
+ #
42
+ def free(extended: false)
43
+ hash = memory
44
+ extended ? (hash['MemFree'] + hash['SwapFree']) * 1024 : hash['MemFree'] * 1024
45
+ end
46
+
47
+ # The memory, in bytes, currently in use. By default this is only
48
+ # physical memory, but if the +extended+ option is set to true then
49
+ # swap is included in the calculation.
50
+ #
51
+ def used(extended: false)
52
+ hash = memory
53
+ (total(extended: extended) - free(extended: extended) - hash['Buffers'] - hash['Cached'] - hash['Slab']) * 1024
54
+ end
55
+
56
+ # A number between 0 and 100 that specifies the approximate percentage of
57
+ # memory that is in use. If the +extended+ option is set to true then
58
+ # swap memory is included in the calculation.
59
+ #
60
+ def load(extended: false)
61
+ (used(extended: extended) / total(extended: extended).to_f).round(2) * 100
62
+ end
63
+
64
+ module_function :memory, :total, :free, :used, :load
65
+ end # Memory
66
+ end # CzSystemInfo
@@ -0,0 +1,222 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ffi'
4
+
5
+ # The CzSystemInfo module serves as a namespace only.
6
+ module CzSystemInfo
7
+ # The Uptime class encapsulates various bits of information regarding your
8
+ # system's uptime, including boot time.
9
+ class Uptime
10
+ extend FFI::Library
11
+ ffi_lib FFI::Library::LIBC
12
+
13
+ # Error typically raised in one of the Uptime methods should fail.
14
+ class Error < StandardError; end
15
+
16
+ # Hit this issue on Linux, not sure why
17
+ begin
18
+ find_type(:clock_t)
19
+ rescue TypeError
20
+ typedef(:long, :clock_t)
21
+ end
22
+
23
+ attach_function :strerror, [:int], :string
24
+ attach_function :sysconf, [:int], :long
25
+ attach_function :time, [:pointer], :time_t
26
+ attach_function :times, [:pointer], :clock_t
27
+
28
+ private_class_method :strerror, :sysconf, :time, :times, :new
29
+
30
+ begin
31
+ attach_function :sysctl, %i[pointer uint pointer pointer pointer size_t], :int
32
+ private_class_method :sysctl
33
+ rescue FFI::NotFoundError
34
+ attach_function :setutxent, [], :void
35
+ attach_function :getutxent, [], :pointer
36
+ attach_function :endutxent, [], :void
37
+ private_class_method :setutxent, :getutxent, :endutxent
38
+ end
39
+
40
+ CTL_KERN = 1 # Kernel
41
+ KERN_BOOTTIME = 21 # Time kernel was booted
42
+ TICKS = 100 # Ticks per second (TODO: use sysconf)
43
+ BOOT_TIME = 2 # Boot time
44
+
45
+ private_constant :CTL_KERN
46
+ private_constant :KERN_BOOTTIME
47
+ private_constant :TICKS
48
+ private_constant :BOOT_TIME
49
+
50
+ class Tms < FFI::Struct
51
+ layout(
52
+ :tms_utime, :clock_t,
53
+ :tms_stime, :clock_t,
54
+ :tms_cutime, :clock_t,
55
+ :tms_cstime, :clock_t
56
+ )
57
+ end
58
+
59
+ private_constant :Tms
60
+
61
+ class Timeval < FFI::Struct
62
+ layout(
63
+ :tv_sec, :long,
64
+ :tv_usec, :long
65
+ )
66
+ end
67
+
68
+ private_constant :Timeval
69
+
70
+ class ExitStatus < FFI::Struct
71
+ layout(
72
+ :e_termination, :short,
73
+ :e_exit, :short
74
+ )
75
+ end
76
+
77
+ private_constant :ExitStatus
78
+
79
+ class Utmpx < FFI::Struct
80
+ layout(
81
+ :ut_user, [:char, 32],
82
+ :ut_id, [:char, 4],
83
+ :ut_line, [:char, 32],
84
+ :ut_pid, :pid_t,
85
+ :ut_type, :short,
86
+ :ut_exit, ExitStatus,
87
+ :ut_tv, Timeval,
88
+ :ut_session, :int,
89
+ :padding, [:int, 5],
90
+ :ut_host, [:char, 257]
91
+ )
92
+ end
93
+
94
+ private_constant :Utmpx
95
+
96
+ # Returns a Time object indicating the time the system was last booted.
97
+ #
98
+ # Example:
99
+ #
100
+ # CzSystemInfo::Uptime.boot_time # => Mon Jul 13 06:08:25 -0600 2009
101
+ #
102
+ def self.boot_time
103
+ if RbConfig::CONFIG['host_os'] =~ /linux/i
104
+ Time.now - seconds
105
+ elsif respond_to?(:sysctl, true)
106
+ tv = Timeval.new
107
+ mib = FFI::MemoryPointer.new(:int, 2).write_array_of_int([CTL_KERN, KERN_BOOTTIME])
108
+ size = FFI::MemoryPointer.new(:long, 1).write_int(tv.size)
109
+
110
+ if sysctl(mib, 2, tv, size, nil, 0) != 0
111
+ raise SystemCallError, "sysctl function failed: #{strerror(FFI.errno)}"
112
+ end
113
+
114
+ Time.at(tv[:tv_sec], tv[:tv_usec])
115
+ else
116
+ begin
117
+ setutxent()
118
+ while ent = Utmpx.new(getutxent())
119
+ if ent[:ut_type] == BOOT_TIME
120
+ time = Time.at(ent[:ut_tv][:tv_sec], ent[:ut_tv][:tv_usec])
121
+ break
122
+ end
123
+ end
124
+ ensure
125
+ endutxent()
126
+ end
127
+ time
128
+ end
129
+ end
130
+
131
+ # Returns the total number of seconds of uptime.
132
+ #
133
+ # Example:
134
+ #
135
+ # CzSystemInfo::Uptime.seconds => 118800
136
+ #
137
+ def self.seconds
138
+ if RbConfig::CONFIG['host_os'] =~ /linux/i
139
+ # rubocop:disable Lint/RescueException
140
+ begin
141
+ File.read('/proc/uptime').split.first.to_i
142
+ rescue Exception => err
143
+ raise Error, err
144
+ end
145
+ # rubocop:enable Lint/RescueException
146
+ elsif respond_to?(:sysctl, true)
147
+ tv = Timeval.new
148
+ mib = FFI::MemoryPointer.new(:int, 2).write_array_of_int([CTL_KERN, KERN_BOOTTIME])
149
+ size = FFI::MemoryPointer.new(:long, 1).write_int(tv.size)
150
+
151
+ if sysctl(mib, 2, tv, size, nil, 0) != 0
152
+ raise SystemCallError, "sysctl function failed: #{strerror(FFI.errno)}"
153
+ end
154
+
155
+ time(nil) - tv[:tv_sec]
156
+ else
157
+ tms = Tms.new
158
+ times(tms) / TICKS
159
+ end
160
+ end
161
+
162
+ # Returns the total number of minutes of uptime.
163
+ #
164
+ # Example:
165
+ #
166
+ # CzSystemInfo::Uptime.minutes # => 678
167
+ #
168
+ def self.minutes
169
+ seconds / 60
170
+ end
171
+
172
+ # Returns the total number of hours of uptime.
173
+ #
174
+ # Example:
175
+ #
176
+ # CzSystemInfo::Uptime.hours # => 31
177
+ #
178
+ def self.hours
179
+ seconds / 3600
180
+ end
181
+
182
+ # Returns the total number of days of uptime.
183
+ #
184
+ # Example:
185
+ #
186
+ # CzSystemInfo::Uptime.days # => 2
187
+ #
188
+ def self.days
189
+ seconds / 86400
190
+ end
191
+
192
+ # Returns the uptime as a colon separated string, including days,
193
+ # hours, minutes and seconds.
194
+ #
195
+ # Example:
196
+ #
197
+ # CzSystemInfo::Uptime.uptime # => "1:9:24:57"
198
+ #
199
+ def self.uptime
200
+ secs = seconds
201
+ days = secs / 86400
202
+ secs -= days * 86400
203
+ hours = secs / 3600
204
+ secs -= hours * 3600
205
+ mins = secs / 60
206
+ secs -= mins * 60
207
+
208
+ "#{days}:#{hours}:#{mins}:#{secs}"
209
+ end
210
+
211
+ # Returns the uptime as a four element array, including days, hours,
212
+ # minutes and seconds.
213
+ #
214
+ # Example:
215
+ #
216
+ # CzSystemInfo::Uptime.dhms # => [1,9,24,57]
217
+ #
218
+ def self.dhms
219
+ uptime.split(':')
220
+ end
221
+ end
222
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CzSystemInfo
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "cz_system_info/version"
4
+ require_relative "cz_system_info/cpu"
5
+ require_relative "cz_system_info/filesystem"
6
+ require_relative "cz_system_info/memory"
7
+ require_relative "cz_system_info/uptime"
8
+
9
+ module CzSystemInfo
10
+ class Error < StandardError; end
11
+ # Your code goes here...
12
+ end
metadata ADDED
@@ -0,0 +1,78 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cz_system_info
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - hayate
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2022-10-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: ffi
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.1'
27
+ description: Move Daniel Berger's sys code into one.
28
+ email:
29
+ - holdstock@yeah.net
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - ".github/workflows/main.yml"
35
+ - ".gitignore"
36
+ - Gemfile
37
+ - LICENSE.txt
38
+ - README.md
39
+ - Rakefile
40
+ - bin/console
41
+ - bin/setup
42
+ - cz_system_info.gemspec
43
+ - lib/cz_system_info.rb
44
+ - lib/cz_system_info/cpu.rb
45
+ - lib/cz_system_info/filesystem.rb
46
+ - lib/cz_system_info/filesystem/constants.rb
47
+ - lib/cz_system_info/filesystem/functions.rb
48
+ - lib/cz_system_info/filesystem/structs.rb
49
+ - lib/cz_system_info/memory.rb
50
+ - lib/cz_system_info/uptime.rb
51
+ - lib/cz_system_info/version.rb
52
+ homepage: https://github.com/hinagiku/cz_system_info
53
+ licenses:
54
+ - MIT
55
+ metadata:
56
+ homepage_uri: https://github.com/hinagiku/cz_system_info
57
+ source_code_uri: https://github.com/hinagiku/cz_system_info
58
+ changelog_uri: https://github.com/hinagiku/cz_system_info
59
+ post_install_message:
60
+ rdoc_options: []
61
+ require_paths:
62
+ - lib
63
+ required_ruby_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: 2.3.0
68
+ required_rubygems_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: '0'
73
+ requirements: []
74
+ rubygems_version: 3.2.3
75
+ signing_key:
76
+ specification_version: 4
77
+ summary: Move Daniel Berger's sys code into one.
78
+ test_files: []