/* 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; }