Created
October 10, 2020 20:43
-
-
Save caiorss/2527d1402ea1469f67fba9ab172f05e5 to your computer and use it in GitHub Desktop.
Sample C++ code for getting system info via virtual file system
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Summary: Gets Linux runtime information from VSF virtual file system. | |
* | |
*/ | |
#include <iostream> | |
#include <fstream> | |
#include <sstream> | |
#include <string> | |
#include <iomanip> // std::seprecision, std::fixed | |
// See: https://man7.org/linux/man-pages/man2/sysinfo.2.html | |
#include <sys/sysinfo.h> | |
void get_memory_info(); | |
void show_sysinfo1(); | |
void show_uptime(); | |
void show_mount_points(); | |
void show_kernel_runtime_config(); | |
std::string readFile(std::string const& file); | |
int main(int argc, char** argv) | |
{ | |
if(argc < 2){ | |
std::cerr << " [ERROR] Usage: $ " << argv[0] << " <COMMAND> " << '\n'; | |
return EXIT_FAILURE; | |
} | |
auto command = std::string{ argv[1] }; | |
if(command == "version"){ | |
std::cout << "===== Kernel Version ====================================" << '\n'; | |
auto version = readFile("/proc/version"); | |
std::cout << " System version = " << version << '\n'; | |
return EXIT_SUCCESS; | |
} | |
if(command == "memory") | |
{ | |
std::cout << " ==== Memory (Reported by command $ free -m ) ========" << '\n'; | |
get_memory_info(); | |
return EXIT_SUCCESS; | |
} | |
// Using the header: <sys/sysinfo.h> | |
// Note: this information is reported by the command $ free -m | |
if(command == "sysinfo1") | |
{ | |
std::cout << " ===== System Info 1 (Reported by $ free -m and $ uptime ) === " << '\n'; | |
show_sysinfo1(); | |
return EXIT_SUCCESS; | |
} | |
if(command == "uptime") | |
{ | |
std::cout << "===== System uptime since boot (Reported by $ uptime) ====" << '\n'; | |
show_uptime(); | |
return EXIT_SUCCESS; | |
} | |
if(command == "load-avg") | |
{ | |
std::cout << " ==== System Load Average ================================" << '\n'; | |
auto loadavg = readFile("/proc/loadavg"); | |
std::cout << "Load average = " << loadavg << '\n'; | |
return EXIT_SUCCESS; | |
} | |
if(command == "mount") | |
{ | |
std::cout << " ====== System mount points ( Reported by command $ mount ) ===== " << '\n'; | |
show_mount_points(); | |
return EXIT_SUCCESS; | |
} | |
if(command == "sysctl") | |
{ | |
std::cout << " ===== Kernel Runtime Information (Reported by $ sysctl ) ======= " << '\n'; | |
show_kernel_runtime_config(); | |
return EXIT_SUCCESS; | |
} | |
if(command == "dmesg") | |
{ | |
std::cout << " ===== Kernel debug message (Reported by $ dmesg ) ==========" << '\n'; | |
auto ifs = std::ifstream("/dev/kmsg"); | |
std::string line; | |
while( std::getline(ifs, line) ){ | |
std::cout << line << '\n'; | |
} | |
} | |
if(command == "cpuinfo") | |
{ | |
std::cout << "======= CPU Information =====================================" << '\n'; | |
auto ifs = std::ifstream("/proc/cpuinfo"); | |
std::string line; | |
while( std::getline(ifs, line) ){ | |
std::cout << line << '\n'; | |
} | |
} | |
return EXIT_SUCCESS; | |
} | |
void get_memory_info() | |
{ | |
constexpr const char* meminfo_file = "/proc/meminfo"; | |
// factor = 1 Gigabytes = 1024 * 1024 kbytes | |
constexpr double factor = 1024 * 1024; | |
auto ifs = std::ifstream{meminfo_file}; | |
if(!ifs.good()){ | |
throw std::runtime_error("Error: unable to memory-info file."); | |
} | |
std::string line, label; | |
std::uint64_t value; | |
while( std::getline(ifs, line) ) | |
{ | |
std::stringstream ss{line}; | |
ss >> label >> value; | |
if(label == "MemTotal:") | |
std::cout << " Total memory (Gb) = " << (value / factor) << '\n'; | |
if(label == "MemAvailable:") | |
std::cout << " Memory Available (Gb) = " << (value / factor) << '\n'; | |
} | |
} | |
void show_sysinfo1() | |
{ | |
struct sysinfo info; | |
::sysinfo(&info); | |
// 1 Gigabyte = 1024 megabytes = 1024 * 1024 kbytes = 1024 * 1024 * 1024 bytes; | |
constexpr double factor = 1024 * 1024 * 1024; | |
constexpr std::uint64_t one_day_to_seconds = 24 * 60 * 60; | |
std::cout << " [*] System uptime since boot (seconds) = " << info.uptime << '\n' | |
<< " [*] System uptime since boot (days) = " << info.uptime / one_day_to_seconds << '\n' | |
<< " [*] Total RAM memory (Gb) = " << info.totalram / factor << '\n' | |
<< " [*] Free RAM memory (Gb) = " << info.freeram / factor << '\n' | |
<< " [*] Total SWAP (Gb) = " << info.totalswap / factor << '\n' | |
<< " [*] Free SWAP (Gb) = " << info.freeswap / factor << '\n' | |
<< " [*] Number of processes running = " << info.procs << '\n' | |
<< '\n'; | |
} | |
// Reported by command $ uptime | |
void show_uptime() | |
{ | |
auto ifs = std::ifstream("/proc/uptime"); | |
if( !ifs.good() ){ throw std::runtime_error("Error: unable to open uptime file "); } | |
double seconds; | |
ifs >> seconds; | |
uint64_t factor = 24 * 60 * 60; | |
std::cout << " Uptime in hours = " << seconds / ( 60 * 60) << '\n'; | |
std::cout << " Uptime in days = " << seconds / factor << '\n'; | |
} | |
void show_kernel_runtime_config() | |
{ | |
auto show_field= [](std::string const& label, std::string const& file) | |
{ | |
std::cout << " [*] " | |
<< std::setw(40) << std::right << (label + " => ") | |
<< std::setw(50) << std::left << readFile(file) | |
<< '\n'; | |
}; | |
std::cout << '\n'; | |
show_field("Machine Hostname", "/proc/sys/kernel/hostname"); | |
show_field("Kernel Version", "/proc/sys/kernel/osrelease"); | |
show_field("Os type", "/proc/sys/kernel/ostype"); | |
show_field("Boot unique ID identifier", "/proc/sys/kernel/random/boot_id"); | |
show_field("Date which kernel was compiled", "/proc/sys/kernel/version"); | |
show_field("Sysrq enabled (Emergency keys)", "/proc/sys/kernel/sysrq"); | |
show_field("Max number of Cgroups namespaces", "/proc/sys/user/max_cgroup_namespaces"); | |
show_field("Max number of Mount namespaces", "/proc/sys/user/max_net_namespaces"); | |
} | |
void show_network_interfaces() | |
{ | |
throw std::runtime_error("Error: not implemented yet."); | |
} | |
// Show mounted file systems, but ignore 'cgroup', 'overlay', 'fusectl' | |
void show_mount_points() | |
{ | |
auto ifs = std::ifstream("/proc/mounts"); | |
if(!ifs){ | |
throw std::runtime_error("Error: unable to open file /proc/mounts"); | |
} | |
std::cout << '\n'; | |
std::cout << " " | |
<< std::setw(20) << std::left << "File system" | |
<< std::setw(20) << std::left << "Type" | |
<< std::setw(10) << std::left << "Mount point" | |
<< '\n'; | |
std::cout << " " | |
<< std::setw(20) << std::left << "------------" | |
<< std::setw(20) << std::left << "----" | |
<< std::setw(10) << std::left << "-----------" | |
<< '\n'; | |
std::string line, fsystem, type, mount_directory; | |
while( std::getline(ifs, line) ) | |
{ | |
auto ss = std::stringstream(line); | |
ss >> fsystem >> mount_directory >> type; | |
if( type != "cgroup" && type != "overlay" && type != "cgroup2") | |
{ | |
std::cout << " " | |
<< std::setw(20) << std::left << fsystem | |
<< std::setw(20) << std::left << type | |
<< std::setw(10) << std::left << mount_directory | |
<< '\n'; | |
} | |
} | |
} | |
// Requires: <string>, <stream>, <sstream> | |
std::string readFile(std::string const& file) | |
{ | |
std::ifstream is(file); | |
if( !is.good() ){ | |
throw std::runtime_error("Error: stream has errors."); | |
} | |
std::stringstream ss; | |
ss << is.rdbuf(); | |
std::string m; | |
// Remove ending line character '\n' or '\r\n'. | |
std::getline(ss, m); | |
return m; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment