index.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513
  1. 'use strict';
  2. // @ts-check
  3. // ==================================================================================
  4. // index.js
  5. // ----------------------------------------------------------------------------------
  6. // Description: System Information - library
  7. // for Node.js
  8. // Copyright: (c) 2014 - 2022
  9. // Author: Sebastian Hildebrandt
  10. // ----------------------------------------------------------------------------------
  11. // Contributors: Guillaume Legrain (https://github.com/glegrain)
  12. // Riccardo Novaglia (https://github.com/richy24)
  13. // Quentin Busuttil (https://github.com/Buzut)
  14. // Lapsio (https://github.com/lapsio)
  15. // csy (https://github.com/csy1983)
  16. // ----------------------------------------------------------------------------------
  17. // License: MIT
  18. // ==================================================================================
  19. // ----------------------------------------------------------------------------------
  20. // Dependencies
  21. // ----------------------------------------------------------------------------------
  22. const lib_version = require('../package.json').version;
  23. const util = require('./util');
  24. const system = require('./system');
  25. const osInfo = require('./osinfo');
  26. const cpu = require('./cpu');
  27. const memory = require('./memory');
  28. const battery = require('./battery');
  29. const graphics = require('./graphics');
  30. const filesystem = require('./filesystem');
  31. const network = require('./network');
  32. const wifi = require('./wifi');
  33. const processes = require('./processes');
  34. const users = require('./users');
  35. const internet = require('./internet');
  36. const docker = require('./docker');
  37. const vbox = require('./virtualbox');
  38. const printer = require('./printer');
  39. const usb = require('./usb');
  40. const audio = require('./audio');
  41. const bluetooth = require('./bluetooth');
  42. let _platform = process.platform;
  43. const _windows = (_platform === 'win32');
  44. const _freebsd = (_platform === 'freebsd');
  45. const _openbsd = (_platform === 'openbsd');
  46. const _netbsd = (_platform === 'netbsd');
  47. const _sunos = (_platform === 'sunos');
  48. // ----------------------------------------------------------------------------------
  49. // init
  50. // ----------------------------------------------------------------------------------
  51. if (_windows) {
  52. util.getCodepage();
  53. }
  54. // ----------------------------------------------------------------------------------
  55. // General
  56. // ----------------------------------------------------------------------------------
  57. function version() {
  58. return lib_version;
  59. }
  60. // ----------------------------------------------------------------------------------
  61. // Get static and dynamic data (all)
  62. // ----------------------------------------------------------------------------------
  63. // --------------------------
  64. // get static data - they should not change until restarted
  65. function getStaticData(callback) {
  66. return new Promise((resolve) => {
  67. process.nextTick(() => {
  68. let data = {};
  69. data.version = version();
  70. Promise.all([
  71. system.system(),
  72. system.bios(),
  73. system.baseboard(),
  74. system.chassis(),
  75. osInfo.osInfo(),
  76. osInfo.uuid(),
  77. osInfo.versions(),
  78. cpu.cpu(),
  79. cpu.cpuFlags(),
  80. graphics.graphics(),
  81. network.networkInterfaces(),
  82. memory.memLayout(),
  83. filesystem.diskLayout()
  84. ]).then(res => {
  85. data.system = res[0];
  86. data.bios = res[1];
  87. data.baseboard = res[2];
  88. data.chassis = res[3];
  89. data.os = res[4];
  90. data.uuid = res[5];
  91. data.versions = res[6];
  92. data.cpu = res[7];
  93. data.cpu.flags = res[8];
  94. data.graphics = res[9];
  95. data.net = res[10];
  96. data.memLayout = res[11];
  97. data.diskLayout = res[12];
  98. if (callback) { callback(data); }
  99. resolve(data);
  100. });
  101. });
  102. });
  103. }
  104. // --------------------------
  105. // get all dynamic data - e.g. for monitoring agents
  106. // may take some seconds to get all data
  107. // --------------------------
  108. // 2 additional parameters needed
  109. // - srv: comma separated list of services to monitor e.g. "mysql, apache, postgresql"
  110. // - iface: define network interface for which you like to monitor network speed e.g. "eth0"
  111. function getDynamicData(srv, iface, callback) {
  112. if (util.isFunction(iface)) {
  113. callback = iface;
  114. iface = '';
  115. }
  116. if (util.isFunction(srv)) {
  117. callback = srv;
  118. srv = '';
  119. }
  120. return new Promise((resolve) => {
  121. process.nextTick(() => {
  122. iface = iface || network.getDefaultNetworkInterface();
  123. srv = srv || '';
  124. // use closure to track ƒ completion
  125. let functionProcessed = (function () {
  126. let totalFunctions = 15;
  127. if (_windows) { totalFunctions = 13; }
  128. if (_freebsd || _openbsd || _netbsd) { totalFunctions = 11; }
  129. if (_sunos) { totalFunctions = 6; }
  130. return function () {
  131. if (--totalFunctions === 0) {
  132. if (callback) {
  133. callback(data);
  134. }
  135. resolve(data);
  136. }
  137. };
  138. })();
  139. // var totalFunctions = 14;
  140. // function functionProcessed() {
  141. // if (--totalFunctions === 0) {
  142. // if (callback) { callback(data) }
  143. // resolve(data);
  144. // }
  145. // }
  146. let data = {};
  147. // get time
  148. data.time = osInfo.time();
  149. /**
  150. * @namespace
  151. * @property {Object} versions
  152. * @property {string} versions.node
  153. * @property {string} versions.v8
  154. */
  155. data.node = process.versions.node;
  156. data.v8 = process.versions.v8;
  157. cpu.cpuCurrentSpeed().then(res => {
  158. data.cpuCurrentSpeed = res;
  159. functionProcessed();
  160. });
  161. users.users().then(res => {
  162. data.users = res;
  163. functionProcessed();
  164. });
  165. processes.processes().then(res => {
  166. data.processes = res;
  167. functionProcessed();
  168. });
  169. cpu.currentLoad().then(res => {
  170. data.currentLoad = res;
  171. functionProcessed();
  172. });
  173. if (!_sunos) {
  174. cpu.cpuTemperature().then(res => {
  175. data.temp = res;
  176. functionProcessed();
  177. });
  178. }
  179. if (!_openbsd && !_freebsd && !_netbsd && !_sunos) {
  180. network.networkStats(iface).then(res => {
  181. data.networkStats = res;
  182. functionProcessed();
  183. });
  184. }
  185. if (!_sunos) {
  186. network.networkConnections().then(res => {
  187. data.networkConnections = res;
  188. functionProcessed();
  189. });
  190. }
  191. memory.mem().then(res => {
  192. data.mem = res;
  193. functionProcessed();
  194. });
  195. if (!_sunos) {
  196. battery().then(res => {
  197. data.battery = res;
  198. functionProcessed();
  199. });
  200. }
  201. if (!_sunos) {
  202. processes.services(srv).then(res => {
  203. data.services = res;
  204. functionProcessed();
  205. });
  206. }
  207. if (!_sunos) {
  208. filesystem.fsSize().then(res => {
  209. data.fsSize = res;
  210. functionProcessed();
  211. });
  212. }
  213. if (!_windows && !_openbsd && !_freebsd && !_netbsd && !_sunos) {
  214. filesystem.fsStats().then(res => {
  215. data.fsStats = res;
  216. functionProcessed();
  217. });
  218. }
  219. if (!_windows && !_openbsd && !_freebsd && !_netbsd && !_sunos) {
  220. filesystem.disksIO().then(res => {
  221. data.disksIO = res;
  222. functionProcessed();
  223. });
  224. }
  225. if (!_openbsd && !_freebsd && !_netbsd && !_sunos) {
  226. wifi.wifiNetworks().then(res => {
  227. data.wifiNetworks = res;
  228. functionProcessed();
  229. });
  230. }
  231. internet.inetLatency().then(res => {
  232. data.inetLatency = res;
  233. functionProcessed();
  234. });
  235. });
  236. });
  237. }
  238. // --------------------------
  239. // get all data at once
  240. // --------------------------
  241. // 2 additional parameters needed
  242. // - srv: comma separated list of services to monitor e.g. "mysql, apache, postgresql"
  243. // - iface: define network interface for which you like to monitor network speed e.g. "eth0"
  244. function getAllData(srv, iface, callback) {
  245. return new Promise((resolve) => {
  246. process.nextTick(() => {
  247. let data = {};
  248. if (iface && util.isFunction(iface) && !callback) {
  249. callback = iface;
  250. iface = '';
  251. }
  252. if (srv && util.isFunction(srv) && !iface && !callback) {
  253. callback = srv;
  254. srv = '';
  255. iface = '';
  256. }
  257. getStaticData().then(res => {
  258. data = res;
  259. getDynamicData(srv, iface).then(res => {
  260. for (let key in res) {
  261. if ({}.hasOwnProperty.call(res, key)) {
  262. data[key] = res[key];
  263. }
  264. }
  265. if (callback) { callback(data); }
  266. resolve(data);
  267. });
  268. });
  269. });
  270. });
  271. }
  272. function get(valueObject, callback) {
  273. return new Promise((resolve) => {
  274. process.nextTick(() => {
  275. const allPromises = Object.keys(valueObject)
  276. .filter(func => ({}.hasOwnProperty.call(exports, func)))
  277. .map(func => {
  278. const params = valueObject[func].substring(valueObject[func].lastIndexOf('(') + 1, valueObject[func].lastIndexOf(')'));
  279. let funcWithoutParams = func.indexOf(')') >= 0 ? func.split(')')[1].trim() : func;
  280. funcWithoutParams = func.indexOf('|') >= 0 ? func.split('|')[0].trim() : funcWithoutParams;
  281. if (params) {
  282. return exports[funcWithoutParams](params);
  283. } else {
  284. return exports[funcWithoutParams]('');
  285. }
  286. });
  287. Promise.all(allPromises).then(data => {
  288. const result = {};
  289. let i = 0;
  290. for (let key in valueObject) {
  291. if ({}.hasOwnProperty.call(valueObject, key) && {}.hasOwnProperty.call(exports, key) && data.length > i) {
  292. if (valueObject[key] === '*' || valueObject[key] === 'all') {
  293. result[key] = data[i];
  294. } else {
  295. let keys = valueObject[key];
  296. // let params = '';
  297. let filter = '';
  298. let filterParts = [];
  299. // remove params
  300. if (keys.indexOf(')') >= 0) {
  301. keys = keys.split(')')[1].trim();
  302. }
  303. // extract filter and remove it from keys
  304. if (keys.indexOf('|') >= 0) {
  305. filter = keys.split('|')[1].trim();
  306. filterParts = filter.split(':');
  307. keys = keys.split('|')[0].trim();
  308. }
  309. keys = keys.replace(/,/g, ' ').replace(/ +/g, ' ').split(' ');
  310. if (data[i]) {
  311. if (Array.isArray(data[i])) {
  312. // result is in an array, go through all elements of array and pick only the right ones
  313. const partialArray = [];
  314. data[i].forEach(element => {
  315. let partialRes = {};
  316. if (keys.length === 1 && (keys[0] === '*' || keys[0] === 'all')) {
  317. partialRes = element;
  318. } else {
  319. keys.forEach(k => {
  320. if ({}.hasOwnProperty.call(element, k)) {
  321. partialRes[k] = element[k];
  322. }
  323. });
  324. }
  325. // if there is a filter, then just take those elements
  326. if (filter && filterParts.length === 2) {
  327. if ({}.hasOwnProperty.call(partialRes, filterParts[0].trim())) {
  328. const val = partialRes[filterParts[0].trim()];
  329. if (typeof val == 'number') {
  330. if (val === parseFloat(filterParts[1].trim())) {
  331. partialArray.push(partialRes);
  332. }
  333. } else if (typeof val == 'string') {
  334. if (val.toLowerCase() === filterParts[1].trim().toLowerCase()) {
  335. partialArray.push(partialRes);
  336. }
  337. }
  338. }
  339. } else {
  340. partialArray.push(partialRes);
  341. }
  342. });
  343. result[key] = partialArray;
  344. } else {
  345. const partialRes = {};
  346. keys.forEach(k => {
  347. if ({}.hasOwnProperty.call(data[i], k)) {
  348. partialRes[k] = data[i][k];
  349. }
  350. });
  351. result[key] = partialRes;
  352. }
  353. } else {
  354. result[key] = {};
  355. }
  356. }
  357. i++;
  358. }
  359. }
  360. if (callback) { callback(result); }
  361. resolve(result);
  362. });
  363. });
  364. });
  365. }
  366. function observe(valueObject, interval, callback) {
  367. let _data = null;
  368. const result = setInterval(() => {
  369. get(valueObject).then(data => {
  370. if (JSON.stringify(_data) !== JSON.stringify(data)) {
  371. _data = Object.assign({}, data);
  372. callback(data);
  373. }
  374. });
  375. }, interval);
  376. return result;
  377. }
  378. // ----------------------------------------------------------------------------------
  379. // export all libs
  380. // ----------------------------------------------------------------------------------
  381. exports.version = version;
  382. exports.system = system.system;
  383. exports.bios = system.bios;
  384. exports.baseboard = system.baseboard;
  385. exports.chassis = system.chassis;
  386. exports.time = osInfo.time;
  387. exports.osInfo = osInfo.osInfo;
  388. exports.versions = osInfo.versions;
  389. exports.shell = osInfo.shell;
  390. exports.uuid = osInfo.uuid;
  391. exports.cpu = cpu.cpu;
  392. exports.cpuFlags = cpu.cpuFlags;
  393. exports.cpuCache = cpu.cpuCache;
  394. exports.cpuCurrentSpeed = cpu.cpuCurrentSpeed;
  395. exports.cpuTemperature = cpu.cpuTemperature;
  396. exports.currentLoad = cpu.currentLoad;
  397. exports.fullLoad = cpu.fullLoad;
  398. exports.mem = memory.mem;
  399. exports.memLayout = memory.memLayout;
  400. exports.battery = battery;
  401. exports.graphics = graphics.graphics;
  402. exports.fsSize = filesystem.fsSize;
  403. exports.fsOpenFiles = filesystem.fsOpenFiles;
  404. exports.blockDevices = filesystem.blockDevices;
  405. exports.fsStats = filesystem.fsStats;
  406. exports.disksIO = filesystem.disksIO;
  407. exports.diskLayout = filesystem.diskLayout;
  408. exports.networkInterfaceDefault = network.networkInterfaceDefault;
  409. exports.networkGatewayDefault = network.networkGatewayDefault;
  410. exports.networkInterfaces = network.networkInterfaces;
  411. exports.networkStats = network.networkStats;
  412. exports.networkConnections = network.networkConnections;
  413. exports.wifiNetworks = wifi.wifiNetworks;
  414. exports.wifiInterfaces = wifi.wifiInterfaces;
  415. exports.wifiConnections = wifi.wifiConnections;
  416. exports.services = processes.services;
  417. exports.processes = processes.processes;
  418. exports.processLoad = processes.processLoad;
  419. exports.users = users.users;
  420. exports.inetChecksite = internet.inetChecksite;
  421. exports.inetLatency = internet.inetLatency;
  422. exports.dockerInfo = docker.dockerInfo;
  423. exports.dockerImages = docker.dockerImages;
  424. exports.dockerContainers = docker.dockerContainers;
  425. exports.dockerContainerStats = docker.dockerContainerStats;
  426. exports.dockerContainerProcesses = docker.dockerContainerProcesses;
  427. exports.dockerVolumes = docker.dockerVolumes;
  428. exports.dockerAll = docker.dockerAll;
  429. exports.vboxInfo = vbox.vboxInfo;
  430. exports.printer = printer.printer;
  431. exports.usb = usb.usb;
  432. exports.audio = audio.audio;
  433. exports.bluetoothDevices = bluetooth.bluetoothDevices;
  434. exports.getStaticData = getStaticData;
  435. exports.getDynamicData = getDynamicData;
  436. exports.getAllData = getAllData;
  437. exports.get = get;
  438. exports.observe = observe;
  439. exports.powerShellStart = util.powerShellStart;
  440. exports.powerShellRelease = util.powerShellRelease;