diff --git a/Gemfile b/Gemfile index 2f81332..8d1b7d6 100644 --- a/Gemfile +++ b/Gemfile @@ -349,7 +349,7 @@ gem 'health_check', '~> 2.6.0' # System information gem 'vmstat', '~> 2.3.0' -gem 'sys-filesystem', '~> 1.1.6' +gem 'sys-filesystem', '~> 1.1.6', group: :exclude # Gitaly GRPC client gem 'gitaly', '~> 0.2.1' diff --git a/app/controllers/admin/system_info_controller.rb b/app/controllers/admin/system_info_controller.rb index 9903972..41af5a2 100644 --- a/app/controllers/admin/system_info_controller.rb +++ b/app/controllers/admin/system_info_controller.rb @@ -1,3 +1,5 @@ +require 'open3' + class Admin::SystemInfoController < Admin::ApplicationController EXCLUDED_MOUNT_OPTIONS = [ 'nobrowse', @@ -29,10 +31,14 @@ class Admin::SystemInfoController < Admin::ApplicationController 'vfat' ].freeze + MOUNT_REGEX = /(\S+) on (\S+) type (\S+) \(([^)]+)\)/ + + Mount = Struct.new('Mount', :name, :mount_point, :mount_type, :options) + FsStat = Struct.new('FsStats', :path, :bytes_total, :bytes_used) + def show @cpus = Vmstat.cpu rescue nil @memory = Vmstat.memory rescue nil - mounts = Sys::Filesystem.mounts @disks = [] mounts.each do |mount| @@ -42,15 +48,38 @@ class Admin::SystemInfoController < Admin::ApplicationController next if (EXCLUDED_MOUNT_TYPES & [mount.mount_type]).any? begin - disk = Sys::Filesystem.stat(mount.mount_point) + disk = fs_stat(mount.mount_point) @disks.push({ bytes_total: disk.bytes_total, bytes_used: disk.bytes_used, disk_name: mount.name, mount_path: disk.path }) - rescue Sys::Filesystem::Error + rescue IOError end end end + + def mounts + stdout, stderr, status = Open3.capture3('mount') + fail IOError, stderr unless status.success? + + stdout.lines + .map { |line| MOUNT_REGEX.match(line) } + .compact + .map { |match| Mount.new(*match.captures) } + end + + def fs_stat(mount_point) + stdout, status = Open3.capture2('stat', '-c', '%s %b %a', '-f', mount_point) + fail IOError unless status.success? + + block_size, blocks_total, blocks_free = stdout.split(' ').map(&:to_i) + + bytes_total = blocks_total * block_size + bytes_free = blocks_free * block_size + bytes_used = bytes_total - bytes_free + + FsStat.new(mount_point, bytes_total, bytes_used) + end end