Skip to content

Instantly share code, notes, and snippets.

@aras-p
Created October 27, 2017 08:43
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save aras-p/47e2252d6b1fa57d3619fd8e021690ec to your computer and use it in GitHub Desktop.
Save aras-p/47e2252d6b1fa57d3619fd8e021690ec to your computer and use it in GitHub Desktop.
Perl get hardware/OS data without non-standard modules
#!/usr/bin/perl
BEGIN {
if ($^O eq "MSWin32")
{
require Win32; Win32::->import();
require Win32::API; Win32::API::->import();
require Win32::TieRegistry; Win32::TieRegistry::->import();
}
}
use List::Util 'first';
my $cpu = 'Unknown';
my $cpus = 0;
my $cpufreq = 0;
my $ram = 0;
my $os = 'Unknown';
sub trim { my $s = shift; $s =~ s/^\s+|\s+$//g; return $s };
if ($^O eq "MSWin32")
{
# 0.09s
# Note: could use "wmic" to query that stuff, but that is a bit slower (e.g. whole sysinfo.pl script takes 0.38s)
#
# OS: 'Windows 10.0.15063'
# CPU: 'Intel(R) Core(TM) i7-5820K CPU @ 3.30GHz'
# CPU count: 12
# CPU freq: 3.3 GHz
# RAM: 16 GB
$cpus = $ENV{'NUMBER_OF_PROCESSORS'};
my $cpuKey = $Registry->Open( "LMachine/HARDWARE/DESCRIPTION/System/CentralProcessor/0", {Access=>Win32::TieRegistry::KEY_READ(),Delimiter=>"/"} );
if ($cpuKey)
{
$cpu = $cpuKey->{"/ProcessorNameString"};
$cpufreq = hex($cpuKey->{"/~MHz"});
$cpufreq = int(($cpufreq + 50) / 100) * 100; # round to hundreds of MHz
}
Win32::API::Struct->typedef(
MEMORYSTATUSEX => qw{
DWORD dwLength;
DWORD MemLoad;
ULONGLONG TotalPhys;
ULONGLONG AvailPhys;
ULONGLONG TotalPage;
ULONGLONG AvailPage;
ULONGLONG TotalVirtual;
ULONGLONG AvailVirtual;
ULONGLONG AvailExtendedVirtual;
}
);
if (Win32::API->Import('kernel32', 'BOOL GlobalMemoryStatusEx(LPMEMORYSTATUSEX lpMemoryStatusEx)'))
{
my $memstatus = Win32::API::Struct->new('MEMORYSTATUSEX');
$memstatus->{dwLength} = $memstatus->sizeof();
$memstatus->{MemLoad} = 0;
$memstatus->{TotalPhys} = 0;
$memstatus->{AvailPhys} = 0;
$memstatus->{TotalPage} = 0;
$memstatus->{AvailPage} = 0;
$memstatus->{TotalVirtual} = 0;
$memstatus->{AvailVirtual} = 0;
$memstatus->{AvailExtendedVirtual} = 0;
GlobalMemoryStatusEx($memstatus);
$ram = $memstatus->{TotalPhys};
}
($osString, $osMajor, $osMinor, $osBuild, $osID) = Win32::GetOSVersion();
$os = "Windows $osMajor.$osMinor.$osBuild";
}
elsif ($^O eq 'darwin')
{
# 0.03s
# OS: 'macOS 10.12.6'
# CPU: 'Intel(R) Core(TM) i7-4850HQ CPU @ 2.30GHz'
# CPU count: 8
# CPU freq: 2.3 GHz
# RAM: 16 GB
$os = 'macOS Unknown';
my $strOS = trim(scalar(`sw_vers`));
$os = 'macOS ' . $1 if $strOS =~ /ProductVersion:\s*(.+)/;
$cpu = trim(`sysctl -n machdep.cpu.brand_string`);
$cpus = trim(`sysctl -n hw.ncpu`);
$cpufreq = trim(`sysctl -n hw.cpufrequency`) / 1000000.0;
$ram = trim(`sysctl -n hw.memsize`);
}
else
{
# 0.03s
# OS: 'Linux Ubuntu 16.04.2 LTS'
# CPU: 'Intel(R) Core(TM) i7-5820K CPU @ 3.30GHz'
# CPU count: 12
# CPU freq: 3.301 GHz
# RAM: 16 GB
open my $h, "/proc/cpuinfo";
if ($h)
{
my @info = <$h>;
close $h;
$cpus = scalar(map /^processor/, @info);
my $strCPU = first { /^model name/ } @info;
$cpu = $1 if ($strCPU && $strCPU =~ /:\s+(.*)/);
my $strFreq = first { /^cpu MHz/ } @info;
$cpufreq = $1 if ($strFreq && $strFreq =~ /:\s+(.*)/);
}
open $h, "/proc/meminfo";
if ($h)
{
my @info = <$h>;
close $h;
my $strRAM = first { /^MemTotal/ } @info;
$ram = $1 * 1024 if ($strRAM && $strRAM =~ /:\s+(\d+)/);
}
$os = 'Linux Unknown';
open $h, "/etc/lsb-release";
if ($h)
{
my @info = <$h>;
close $h;
my $strOS = first { /^DISTRIB_DESCRIPTION/ } @info;
$os = 'Linux ' . $1 if ($strOS && $strOS =~ /=\"(.*)\"/);
}
}
$ram = int($ram / 1024 / 1024 / 1024 + 0.5);
$cpufreq = int($cpufreq) / 1000;
print "OS: '$os'\n";
print "CPU: '$cpu'\n";
print "CPU count: $cpus\n";
print "CPU freq: $cpufreq GHz\n";
print "RAM: $ram GB\n";
@davestoddard
Copy link

There is no allowance for FreeBSD here. The best way to collect this data would be through the FreeBSD sysctl subsystem. CPU is available via 'sysctl hw.model', OS is 'sysctl kern.ostype', CPU count is 'sysctl kern.smp.cpus', CPU frequency is 'sysctl machdep.tsc_freq', and RAM is 'sysctl kern.ipc.maxmbufmem'.

@aras-p
Copy link
Author

aras-p commented Oct 31, 2017

@davestoddard very much likely, all I care for my case is Windows, Mac & Linux. I don't have any FreeBSD environment here to test whether whatever I'd write up would actually work.

@nilsoberg2
Copy link

nilsoberg2 commented Oct 4, 2019

Thanks for the gist. Can you provide a license for it? (E.g. MIT)

@aras-p
Copy link
Author

aras-p commented Oct 12, 2019

Thanks for the gist. Can you provide a license for it? (E.g. MIT)
@nilsoberg2 I'm fine with unlicense / public domain

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment