整理代码
This commit is contained in:
commit
c7b4e178ec
364 changed files with 59691 additions and 0 deletions
829
util/SystemInfo.cpp
Normal file
829
util/SystemInfo.cpp
Normal file
|
|
@ -0,0 +1,829 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* INCLUDE
|
||||
*******************************************************************************
|
||||
*/
|
||||
#include "SystemInfo.h"
|
||||
#include <Poco/DirectoryIterator.h>
|
||||
#include <Poco/Path.h>
|
||||
#include <Poco/Pipe.h>
|
||||
#include <Poco/PipeStream.h>
|
||||
#include <Poco/Process.h>
|
||||
#include <Poco/StreamCopier.h>
|
||||
#include <dirent.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/statvfs.h>
|
||||
#include <unistd.h>
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <cctype>
|
||||
#include <chrono>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <experimental/filesystem>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
#include "Application.h"
|
||||
#include "Logger.h"
|
||||
#include "Poco/Thread.h"
|
||||
#include "linux-system-usage.hpp"
|
||||
|
||||
using namespace get_system_usage_linux;
|
||||
|
||||
namespace Util
|
||||
{
|
||||
/*
|
||||
*******************************************************************************
|
||||
* CLASS DECLARE
|
||||
*******************************************************************************
|
||||
*/
|
||||
unsigned SystemInfo::cpuUsage()
|
||||
{
|
||||
CPU_stats t1 = read_cpu_data();
|
||||
Poco::Thread::sleep(100);
|
||||
CPU_stats t2 = read_cpu_data();
|
||||
|
||||
return (unsigned)(100.0f * get_cpu_usage(t1, t2));
|
||||
}
|
||||
|
||||
SystemInfo::MemoryInfo SystemInfo::readMemoryInfo()
|
||||
{
|
||||
auto memory_data = read_memory_data();
|
||||
|
||||
MemoryInfo info;
|
||||
info.total = memory_data.total_memory;
|
||||
info.free = memory_data.free_memory;
|
||||
info.usage = 100.0f * memory_data.get_memory_usage();
|
||||
info.available = memory_data.available_memory;
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
std::map<std::string, Util::SystemInfo::StorageInfo> SystemInfo::getStorageInfo(bool returnSpace)
|
||||
{
|
||||
std::ifstream mounts("/proc/mounts");
|
||||
std::string line;
|
||||
std::map<std::string, StorageInfo> storageMap;
|
||||
|
||||
if (!mounts.is_open())
|
||||
{
|
||||
logger().error("Failed to open /proc/mounts");
|
||||
return storageMap;
|
||||
}
|
||||
while (std::getline(mounts, line))
|
||||
{
|
||||
std::istringstream iss(line);
|
||||
std::string device, path;
|
||||
iss >> device >> path;
|
||||
std::string deviceType = device.find("/dev/sd") == 0 ? "disk" : "";
|
||||
deviceType = !deviceType.empty() ? deviceType : (device.find("/dev/mmcblk") == 0 ? "mmcblk" : "");
|
||||
deviceType = !deviceType.empty() ? deviceType : (path.find("/mnt/storages/nfs") == 0 ? "nfs" : "");
|
||||
deviceType = !deviceType.empty() ? deviceType : (path.find("/mnt/storages/cifs") == 0 ? "cifs" : "");
|
||||
if (!deviceType.empty())
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!mountPointEnable(path))
|
||||
{
|
||||
logger().error("%s Mount point is not available", path);
|
||||
continue;
|
||||
}
|
||||
StorageInfo storageInfo;
|
||||
storageInfo.device = device;
|
||||
storageInfo.path = path;
|
||||
storageInfo.status = 1;
|
||||
storageInfo.type = deviceType;
|
||||
|
||||
if (returnSpace)
|
||||
{
|
||||
struct statvfs stat;
|
||||
int ret_code = statvfs(path.c_str(), &stat);
|
||||
if (ret_code != 0)
|
||||
{
|
||||
int err = errno;
|
||||
logger().error("Failed to get disk usage information for: %s", strerror(err));
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned long long total = stat.f_blocks * stat.f_frsize;
|
||||
unsigned long long free = stat.f_bfree * stat.f_frsize;
|
||||
unsigned long long available = stat.f_bavail * stat.f_frsize;
|
||||
unsigned long long used = total - free;
|
||||
storageInfo.total = total;
|
||||
storageInfo.used = used;
|
||||
storageInfo.available = available;
|
||||
storageInfo.free = free;
|
||||
}
|
||||
}
|
||||
storageMap[device] = storageInfo;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
logger().error("SystemInfo::getStorageInfo erorr: %s", std::string(e.what()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto blocks = getBlockDevices();
|
||||
for (const auto& block : blocks)
|
||||
{
|
||||
if (block.empty() || block.back() != '1')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
auto it = storageMap.find(block);
|
||||
if (it == storageMap.end())
|
||||
{
|
||||
StorageInfo storageInfo;
|
||||
storageInfo.status = 2;
|
||||
storageInfo.device = block;
|
||||
storageMap[block] = storageInfo;
|
||||
}
|
||||
}
|
||||
return storageMap;
|
||||
}
|
||||
|
||||
bool isBlockDevice(const std::string& path)
|
||||
{
|
||||
struct stat statbuf;
|
||||
if (stat(path.c_str(), &statbuf) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return S_ISBLK(statbuf.st_mode);
|
||||
}
|
||||
|
||||
std::vector<std::string> SystemInfo::getBlockDevices()
|
||||
{
|
||||
std::vector<std::string> blockDevices;
|
||||
std::ifstream file("/proc/partitions");
|
||||
std::string line;
|
||||
|
||||
while (std::getline(file, line))
|
||||
{
|
||||
std::istringstream iss(line);
|
||||
std::string major, minor, blocks, name;
|
||||
if (!(iss >> major >> minor >> blocks >> name))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string devicePath = "/dev/" + name;
|
||||
if (devicePath.find("/dev/sd") == 0 && isBlockDevice(devicePath))
|
||||
{
|
||||
blockDevices.push_back(devicePath);
|
||||
}
|
||||
}
|
||||
|
||||
return blockDevices;
|
||||
}
|
||||
|
||||
std::vector<Util::SystemInfo::FileInfo> SystemInfo::getFileInfoList(std::string parentPath)
|
||||
{
|
||||
std::vector<Util::SystemInfo::FileInfo> fileInfoList;
|
||||
Poco::Path path(parentPath);
|
||||
if (!path.isDirectory())
|
||||
{
|
||||
logger().error("Error: %s is not a directory.", parentPath);
|
||||
return fileInfoList;
|
||||
}
|
||||
try
|
||||
{
|
||||
Poco::DirectoryIterator it(parentPath);
|
||||
Poco::DirectoryIterator end;
|
||||
|
||||
while (it != end)
|
||||
{
|
||||
const Poco::Path& p = it.path();
|
||||
Util::SystemInfo::FileInfo fileInfo;
|
||||
fileInfo.name = p.getFileName();
|
||||
fileInfo.parentPath = parentPath;
|
||||
fileInfo.type = it->isDirectory() ? 2 : (it->isFile() ? 1 : 0);
|
||||
if (it->isDirectory())
|
||||
{
|
||||
}
|
||||
else if (it->isFile())
|
||||
{
|
||||
Poco::File file(p.toString());
|
||||
fileInfo.size = file.getSize();
|
||||
fileInfo.lastModifyTime = file.getLastModified().epochTime();
|
||||
}
|
||||
++it;
|
||||
fileInfoList.push_back(fileInfo);
|
||||
}
|
||||
}
|
||||
catch (Poco::Exception& e)
|
||||
{
|
||||
logger().error("An error occurred: %s", e.displayText());
|
||||
}
|
||||
return fileInfoList;
|
||||
}
|
||||
|
||||
unsigned long long Util::SystemInfo::getPathFreeSpace(const std::string& path)
|
||||
{
|
||||
struct statvfs stat;
|
||||
if (statvfs(path.c_str(), &stat) != 0)
|
||||
{
|
||||
logger().error("Failed to get filesystem stats for %s", path);
|
||||
return 0;
|
||||
}
|
||||
unsigned long long free = stat.f_bfree * stat.f_frsize;
|
||||
|
||||
return free;
|
||||
}
|
||||
|
||||
unsigned long long Util::SystemInfo::checkSizeAndDelEarliestFile(const std::string& basePath,
|
||||
const unsigned int limitMB,
|
||||
const std::string deletePath,
|
||||
const std::string& deleteExtName,
|
||||
const std::set<std::string> exculdePathOrFiles)
|
||||
{
|
||||
int i = 10;
|
||||
unsigned long long freeBytes = 0;
|
||||
while (i-- > 0)
|
||||
{
|
||||
freeBytes = getPathFreeSpace(basePath);
|
||||
unsigned long long limitBytes = static_cast<unsigned long long>(limitMB) * 1024 * 1024;
|
||||
logger().information(" freeBytes=%s, limitBytes=%s", std::to_string(freeBytes), std::to_string(limitBytes));
|
||||
|
||||
if (freeBytes < limitBytes)
|
||||
{
|
||||
logger().information(" Space is less than=%s. Deleting earliest file...", std::to_string(limitMB));
|
||||
|
||||
try
|
||||
{
|
||||
std::string findCmd = "find " + deletePath + " -type f -name \"*" + deleteExtName +
|
||||
"\" -exec stat -c '%mY %n' {} + | sort -n | head -n 1 | cut -d' ' -f2-";
|
||||
logger().information("Execute command: %s", findCmd);
|
||||
std::string oldestFile;
|
||||
std::array<char, 128> buffer;
|
||||
std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(findCmd.c_str(), "r"), pclose);
|
||||
if (!pipe)
|
||||
{
|
||||
throw std::runtime_error("popen() failed!");
|
||||
}
|
||||
while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr)
|
||||
{
|
||||
oldestFile += buffer.data();
|
||||
}
|
||||
|
||||
if (!oldestFile.empty() && oldestFile[oldestFile.size() - 1] == '\n')
|
||||
{
|
||||
oldestFile.erase(oldestFile.size() - 1);
|
||||
}
|
||||
|
||||
if (!oldestFile.empty())
|
||||
{
|
||||
bool isExecuteDelete = true;
|
||||
|
||||
for (std::string name : exculdePathOrFiles)
|
||||
{
|
||||
if (oldestFile.find(name) == 0)
|
||||
{
|
||||
isExecuteDelete = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isExecuteDelete)
|
||||
{
|
||||
try
|
||||
{
|
||||
Poco::File file(oldestFile);
|
||||
|
||||
if (file.exists())
|
||||
{
|
||||
file.remove();
|
||||
logger().information("File deleted successfully: %s", oldestFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
logger().information("File does not exist: %s", oldestFile);
|
||||
}
|
||||
}
|
||||
catch (const Poco::Exception& ex)
|
||||
{
|
||||
logger().information("Failed to delete file: : %s, error:", oldestFile, ex.displayText());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logger().information("deleted old file -> exculde path or file:%s", oldestFile);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logger().information("deleted old file -> No .mp4 files found");
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
logger().error("deleted old file -> Error: ", e.what());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (freeBytes <= 0)
|
||||
{
|
||||
freeBytes = getPathFreeSpace(basePath);
|
||||
}
|
||||
return freeBytes;
|
||||
}
|
||||
|
||||
bool Util::SystemInfo::mountPointEnable(const std::string& localPath)
|
||||
{
|
||||
return Util::SystemInfo::executeCommand("ls " + localPath, 5);
|
||||
}
|
||||
|
||||
bool Util::SystemInfo::mountCifs(std::string ip, std::string remotePath, std::string localPath, std::string username,
|
||||
std::string password, std::string vers, std::string charset)
|
||||
{
|
||||
Util::SystemInfo::umount(localPath);
|
||||
Util::SystemInfo::executeCommand("rm -rf " + localPath);
|
||||
Util::SystemInfo::executeCommand("mkdir -p " + localPath);
|
||||
|
||||
std::string _charset = charset.empty() ? "" : ",iocharset=" + charset;
|
||||
std::string mountCmd = Poco::format("mount -t cifs -o username=%s,password=%s,vers=%s%s //%s%s %s", username,
|
||||
password, vers, _charset, ip, remotePath, localPath);
|
||||
return Util::SystemInfo::executeCommand(mountCmd);
|
||||
}
|
||||
bool Util::SystemInfo::mountNfs(std::string ip, std::string remotePath, std::string localPath, std::string vers)
|
||||
{
|
||||
Util::SystemInfo::umount(localPath);
|
||||
Util::SystemInfo::executeCommand("rm -rf " + localPath);
|
||||
Util::SystemInfo::executeCommand("mkdir -p " + localPath);
|
||||
|
||||
std::string mountCmd = Poco::format("mount -t nfs -o nolock,vers=%s %s:%s %s", vers, ip, remotePath, localPath);
|
||||
return Util::SystemInfo::executeCommand(mountCmd, 5);
|
||||
}
|
||||
bool Util::SystemInfo::umount(std::string localPath)
|
||||
{
|
||||
return Util::SystemInfo::executeCommand("umount -f " + localPath);
|
||||
}
|
||||
|
||||
int Util::SystemInfo::getProcessPID(const std::string& processName)
|
||||
{
|
||||
try
|
||||
{
|
||||
DIR* dir = opendir("/proc");
|
||||
if (!dir)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string targetName = processName;
|
||||
size_t lastSlash = targetName.find_last_of('/');
|
||||
if (lastSlash != std::string::npos)
|
||||
{
|
||||
targetName = targetName.substr(lastSlash + 1);
|
||||
}
|
||||
|
||||
struct dirent* entry;
|
||||
int pid = 0;
|
||||
|
||||
while ((entry = readdir(dir)))
|
||||
{
|
||||
if (entry->d_type != DT_DIR || !isdigit(entry->d_name[0]))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string commPath = std::string("/proc/") + entry->d_name + "/comm";
|
||||
std::ifstream commFile(commPath);
|
||||
if (commFile)
|
||||
{
|
||||
std::string commName;
|
||||
if (std::getline(commFile, commName))
|
||||
{
|
||||
commName.erase(std::remove(commName.begin(), commName.end(), '\n'), commName.end());
|
||||
if (commName == targetName)
|
||||
{
|
||||
pid = std::stoi(entry->d_name);
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
std::string cmdlinePath = std::string("/proc/") + entry->d_name + "/cmdline";
|
||||
std::ifstream cmdlineFile(cmdlinePath);
|
||||
if (cmdlineFile)
|
||||
{
|
||||
std::string cmdline;
|
||||
if (std::getline(cmdlineFile, cmdline))
|
||||
{
|
||||
size_t nullPos = cmdline.find('\0');
|
||||
if (nullPos != std::string::npos)
|
||||
{
|
||||
cmdline.resize(nullPos);
|
||||
}
|
||||
|
||||
lastSlash = cmdline.find_last_of('/');
|
||||
std::string exeName = (lastSlash != std::string::npos) ? cmdline.substr(lastSlash + 1) : cmdline;
|
||||
if (exeName == targetName)
|
||||
{
|
||||
pid = std::stoi(entry->d_name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
return pid;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
logger().error("getProcessPID Error: %s", std::string(e.what()));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::vector<std::string> Util::SystemInfo::getNetworkInterfaceNames()
|
||||
{
|
||||
std::vector<std::string> interfaceNames;
|
||||
try
|
||||
{
|
||||
Poco::Net::NetworkInterface::List interfaces = Poco::Net::NetworkInterface::list(false, false);
|
||||
for (const auto& interface : interfaces)
|
||||
{
|
||||
if (!interface.isLoopback()
|
||||
|
||||
&& !interface.name().empty())
|
||||
{
|
||||
interfaceNames.push_back(interface.name());
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const Poco::Exception& e)
|
||||
{
|
||||
logger().error("getNetworkInterfaceNames Error: %s", std::string(e.what()));
|
||||
}
|
||||
return interfaceNames;
|
||||
}
|
||||
|
||||
Util::SystemInfo::NetworkInterfaceInfo Util::SystemInfo::getNetWorkInterfaceInfo(const std::string& interfaceName,
|
||||
bool returnGateway)
|
||||
{
|
||||
Util::SystemInfo::NetworkInterfaceInfo info;
|
||||
try
|
||||
{
|
||||
auto interface = Poco::Net::NetworkInterface::forName(interfaceName);
|
||||
if (interface.name() == interfaceName)
|
||||
{
|
||||
info.name = interface.name();
|
||||
info.displayName = interface.displayName();
|
||||
info.ipAddress = interface.address().toString();
|
||||
info.subnetMask = interface.subnetMask().toString();
|
||||
info.broadcastAddress = interface.broadcastAddress().toString();
|
||||
auto macAddress = interface.macAddress();
|
||||
info.macAddress = Poco::format("%02X:%02X:%02X:%02X:%02X:%02X", (unsigned)macAddress[0],
|
||||
(unsigned)macAddress[1], (unsigned)macAddress[2], (unsigned)macAddress[3],
|
||||
(unsigned)macAddress[4], (unsigned)macAddress[5]);
|
||||
info.isUp = interface.isUp();
|
||||
|
||||
if (returnGateway)
|
||||
{
|
||||
info.gateway = gatewayAddress(interfaceName).toString();
|
||||
}
|
||||
info.isInitialized = true;
|
||||
}
|
||||
}
|
||||
catch (const Poco::Exception& e)
|
||||
{
|
||||
logger().error("Error getNetWorkInterfaceInfo info: %s", std::string(e.what()));
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
Poco::Net::IPAddress Util::SystemInfo::localAddress(const std::string& interfaceName)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Poco::Net::NetworkInterface::forName(interfaceName).address();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return Poco::Net::IPAddress("0.0.0.0");
|
||||
}
|
||||
}
|
||||
std::map<std::string, Poco::Net::IPAddress> Util::SystemInfo::localAddresses()
|
||||
{
|
||||
std::map<std::string, Poco::Net::IPAddress> ipMap;
|
||||
try
|
||||
{
|
||||
Poco::Net::NetworkInterface::List interfaces = Poco::Net::NetworkInterface::list();
|
||||
|
||||
for (const auto& interface : interfaces)
|
||||
{
|
||||
if (interface.isUp() && !interface.isLoopback() && !interface.address().isWildcard() &&
|
||||
interface.address().isUnicast() && interface.address().family() == Poco::Net::AddressFamily::IPv4)
|
||||
{
|
||||
ipMap[interface.name()] = interface.address();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const Poco::Exception& e)
|
||||
{
|
||||
logger().error("localAddresses Error: %s", std::string(e.what()));
|
||||
}
|
||||
return ipMap;
|
||||
}
|
||||
|
||||
std::vector<std::string> Util::SystemInfo::localAddressesList()
|
||||
{
|
||||
std::vector<std::string> ipList;
|
||||
try
|
||||
{
|
||||
Poco::Net::NetworkInterface::List interfaces = Poco::Net::NetworkInterface::list();
|
||||
|
||||
for (const auto& interface : interfaces)
|
||||
{
|
||||
if (interface.isUp() && !interface.isLoopback())
|
||||
{
|
||||
Poco::Net::NetworkInterface::AddressList addresses = interface.addressList();
|
||||
|
||||
for (const auto& addressInfo : addresses)
|
||||
{
|
||||
const Poco::Net::IPAddress& ip = addressInfo.get<0>();
|
||||
|
||||
if (!ip.isWildcard() && ip.isUnicast() && ip.family() == Poco::Net::AddressFamily::IPv4)
|
||||
{
|
||||
ipList.push_back(ip.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const Poco::Exception& e)
|
||||
{
|
||||
logger().error("localAddresses Error: %s", std::string(e.what()));
|
||||
}
|
||||
return ipList;
|
||||
}
|
||||
|
||||
std::string Util::SystemInfo::localAddressOfAvailable()
|
||||
{
|
||||
std::map<std::string, Poco::Net::IPAddress> ipMap = localAddresses();
|
||||
std::string hostIp = "0.0.0.0";
|
||||
if (!ipMap.empty())
|
||||
{
|
||||
hostIp = ipMap.begin()->second.toString();
|
||||
}
|
||||
return hostIp;
|
||||
}
|
||||
|
||||
std::string Util::SystemInfo::getFirstWirelessInterfaceName()
|
||||
{
|
||||
auto interfaces = getNetworkInterfaceNames();
|
||||
for (auto& name : interfaces)
|
||||
{
|
||||
std::vector<std::string> wirelessPatterns = {"wlan", "wi-fi", "wireless", "wifi", "ath", "ra", "wlp", "wlan"};
|
||||
for (const auto& pattern : wirelessPatterns)
|
||||
{
|
||||
if (Poco::toLower(name).find(pattern) != std::string::npos)
|
||||
{
|
||||
return name;
|
||||
}
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
Poco::Net::IPAddress Util::SystemInfo::subnetMask(const std::string& interfaceName)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Poco::Net::NetworkInterface::forName(interfaceName).subnetMask();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return Poco::Net::IPAddress("0.0.0.0");
|
||||
}
|
||||
}
|
||||
|
||||
Poco::Net::NetworkInterface::MACAddress Util::SystemInfo::macAddress(const std::string& interfaceName)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Poco::Net::NetworkInterface::forName(interfaceName).macAddress();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return Poco::Net::NetworkInterface::MACAddress();
|
||||
}
|
||||
}
|
||||
|
||||
Poco::Net::NetworkInterface::MACAddress Util::SystemInfo::getFirstMacAddress()
|
||||
{
|
||||
auto interfaces = getNetworkInterfaceNames();
|
||||
try
|
||||
{
|
||||
for (const auto& name : interfaces)
|
||||
{
|
||||
return Poco::Net::NetworkInterface::forName(name).macAddress();
|
||||
}
|
||||
return Poco::Net::NetworkInterface::MACAddress();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return Poco::Net::NetworkInterface::MACAddress();
|
||||
}
|
||||
}
|
||||
|
||||
bool Util::SystemInfo::netInterfaceIsExist(const std::string& interfaceName)
|
||||
{
|
||||
if (interfaceName.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
std::vector<std::string> interfaceNames = Util::SystemInfo::getNetworkInterfaceNames();
|
||||
for (const auto& name : interfaceNames)
|
||||
{
|
||||
if (interfaceName == name)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Util::SystemInfo::netInterfaceIsAvailable(const std::string& interfaceName)
|
||||
{
|
||||
std::vector<std::string> interfaceNames;
|
||||
try
|
||||
{
|
||||
Poco::Net::NetworkInterface::List interfaces = Poco::Net::NetworkInterface::list(false, false);
|
||||
for (const auto& interface : interfaces)
|
||||
{
|
||||
if (!interface.isLoopback() && interface.isUp() && !interface.name().empty())
|
||||
{
|
||||
if (interfaceName == interface.name())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const Poco::Exception& e)
|
||||
{
|
||||
logger().error("netInterfaceIsAvailable Error: %s", std::string(e.what()));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Poco::Net::IPAddress Util::SystemInfo::gatewayAddress(const std::string& interfaceName)
|
||||
{
|
||||
#define BUFLEN 20480
|
||||
Poco::Net::IPAddress invalid("0.0.0.0");
|
||||
|
||||
int fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
|
||||
if (fd < 0)
|
||||
{
|
||||
logger().error("NETLINK socket error");
|
||||
return invalid;
|
||||
}
|
||||
|
||||
char req[BUFLEN] = {0};
|
||||
struct nlmsghdr* nh = (struct nlmsghdr*)req;
|
||||
nh->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
|
||||
nh->nlmsg_type = RTM_GETROUTE;
|
||||
nh->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
|
||||
struct rtmsg* rtm = (struct rtmsg*)NLMSG_DATA(nh);
|
||||
rtm->rtm_family = AF_INET;
|
||||
rtm->rtm_table = RT_TABLE_MAIN;
|
||||
struct sockaddr_nl nladdr = {0};
|
||||
nladdr.nl_family = AF_NETLINK;
|
||||
if (bind(fd, (struct sockaddr*)&nladdr, sizeof(nladdr)) < 0)
|
||||
{
|
||||
logger().error("NETLINK bind error");
|
||||
close(fd);
|
||||
return invalid;
|
||||
}
|
||||
if (send(fd, req, sizeof(req), 0) < 0)
|
||||
{
|
||||
logger().error("NETLINK send error");
|
||||
close(fd);
|
||||
return invalid;
|
||||
}
|
||||
|
||||
char buf[BUFLEN] = {0};
|
||||
struct iovec iov = {buf, sizeof(buf)};
|
||||
struct sockaddr_nl sa;
|
||||
struct msghdr msg = {&sa, sizeof(sa), &iov, 1, NULL, 0, 0};
|
||||
int len = recvmsg(fd, &msg, 0);
|
||||
if (len < 0)
|
||||
{
|
||||
logger().error("NETLINK recvmsg error");
|
||||
close(fd);
|
||||
return invalid;
|
||||
}
|
||||
|
||||
struct nlmsghdr* nhp;
|
||||
for (nhp = (struct nlmsghdr*)buf; NLMSG_OK(nhp, len); nhp = NLMSG_NEXT(nhp, len))
|
||||
{
|
||||
struct rtmsg* rtp = (struct rtmsg*)NLMSG_DATA(nhp);
|
||||
if (rtp->rtm_table != RT_TABLE_MAIN || rtp->rtm_family != AF_INET)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
struct rtattr* attr = (struct rtattr*)RTM_RTA(rtp);
|
||||
int attrlen = RTM_PAYLOAD(nhp);
|
||||
for (; RTA_OK(attr, attrlen); attr = RTA_NEXT(attr, attrlen))
|
||||
{
|
||||
if (attr->rta_type != RTA_GATEWAY)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32_t gateway = *(uint32_t*)RTA_DATA(attr);
|
||||
char gwstr[INET_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET, &gateway, gwstr, sizeof(gwstr));
|
||||
close(fd);
|
||||
|
||||
return Poco::Net::IPAddress(std::string(gwstr));
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
|
||||
return invalid;
|
||||
}
|
||||
|
||||
bool Util::SystemInfo::executeCommand(const std::string& command, int timeout_sec, std::string& output)
|
||||
{
|
||||
if (timeout_sec <= 0)
|
||||
{
|
||||
std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(command.c_str(), "r"), pclose);
|
||||
if (!pipe)
|
||||
{
|
||||
logger().error("Failed to execute command: %s", command);
|
||||
return false;
|
||||
}
|
||||
|
||||
char buffer[128];
|
||||
while (fgets(buffer, sizeof(buffer), pipe.get()) != nullptr)
|
||||
{
|
||||
output += buffer;
|
||||
}
|
||||
|
||||
int status = pclose(pipe.release());
|
||||
int ret = WEXITSTATUS(status);
|
||||
if (ret != 0)
|
||||
{
|
||||
logger().error("Command failed: %s, exit code: %d, error: %s", command, ret, output);
|
||||
return false;
|
||||
}
|
||||
logger().information("Command succeeded: %s, exit code: %d", command, ret);
|
||||
return true;
|
||||
}
|
||||
|
||||
output.clear();
|
||||
std::string timeoutCommand = "timeout -s KILL " + std::to_string(timeout_sec) + " " + command;
|
||||
timeoutCommand += " 2>/dev/null || timeout -s KILL -t " + std::to_string(timeout_sec) + " " + command;
|
||||
|
||||
std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(timeoutCommand.c_str(), "r"), pclose);
|
||||
if (!pipe)
|
||||
{
|
||||
logger().error("2Failed to execute command: %s", timeoutCommand);
|
||||
return false;
|
||||
}
|
||||
|
||||
char buffer[128];
|
||||
while (fgets(buffer, sizeof(buffer), pipe.get()) != nullptr)
|
||||
{
|
||||
output += buffer;
|
||||
}
|
||||
|
||||
int status = pclose(pipe.release());
|
||||
int ret = WEXITSTATUS(status);
|
||||
|
||||
if (ret != 0)
|
||||
{
|
||||
if (ret == 124 || output.find("time") != std::string::npos)
|
||||
{
|
||||
logger().error("2Command timeout: %s", timeoutCommand);
|
||||
}
|
||||
else
|
||||
{
|
||||
logger().error("2Command failed: %s, exit code: %d, error: %s", timeoutCommand, ret, output);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
logger().information("2Command succeeded: %s, exit code: %d", timeoutCommand, ret);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue