From c22cdad6da39c3ed8caca33f7b652250af43e9c0 Mon Sep 17 00:00:00 2001 From: Sebastian Hildebrandt Date: Sat, 10 Feb 2018 19:19:53 +0100 Subject: [PATCH] first partial FreeBSD support --- CHANGELOG.md | 2 + README.md | 624 +++++++++++++++++++++++----------------------- lib/battery.js | 62 +++-- lib/cpu.js | 208 +++++++++++++--- lib/docker.js | 3 + lib/filesystem.js | 46 ++-- lib/graphics.js | 16 +- lib/index.js | 47 ++-- lib/internet.js | 20 +- lib/memory.js | 69 +++-- lib/network.js | 32 ++- lib/osinfo.js | 30 ++- lib/processes.js | 167 +++++++------ lib/system.js | 10 +- lib/users.js | 22 +- lib/util.js | 9 +- package.json | 5 +- 17 files changed, 827 insertions(+), 545 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2774a83..7825ee6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ New Functions +- FreeBSD support: for some basic functions (new in version 3.34 ff) - `diskLayout`: returns hard disk layout (new in version 3.23) - `memLayout`: returns memory chip layout (new in version 3.23) - Windows support: for some basic functions (new in version 3.17 ff) @@ -99,6 +100,7 @@ Other changes | Version | Date | Comment | | -------------- | -------------- | -------- | +| 3.34.0 | 2018-02-10 | first partial FreeBSD support | | 3.33.15 | 2018-01-21 | optimized OSX battery | | 3.33.14 | 2018-01-17 | bugfix `diskLayout()` (Windows) | | 3.33.13 | 2018-01-12 | bugfix `memLayout()` (Windows) | diff --git a/README.md b/README.md index e437b31..fd5b66e 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Simple system and OS information library for [node.js][nodejs-url] ## Quick Start -Lightweight collection of 35+ functions to retrieve detailed hardware, system and OS information (Linux, OSX and partial Windows support) - no npm dependencies. +Lightweight collection of 35+ functions to retrieve detailed hardware, system and OS information (Linux, OSX, partial Windows and FreeBSD support) - no npm dependencies. ### Installation @@ -53,13 +53,13 @@ async function cpu() { ### Latest Activity (last 7 major and minor version releases) +- Version 3.34.0: first partial FreeBSD support - Version 3.33.0: added bios `bios()` and main board `baseboard()` information - Version 3.32.0: extended `memLayout()` - added manufacturer - Version 3.31.0: extended windows support `cpuFlags()` (partially) - Version 3.30.0: extended `versions()` (added `yarn`, `gulp`, `grunt`, `tsc`, `git`) - Version 3.29.0: extended windows support `services()` - Version 3.28.0: extended windows support `processes()` -- Version 3.27.0: added raw data to `currentLoad()`, fixed `networkInterfaces()` MAC problem node 8.x - ... You can find all changes here: [detailed changelog][changelog-url] @@ -70,8 +70,8 @@ You can find all changes here: [detailed changelog][changelog-url] little library. This library is still work in progress. Version 3 comes with further improvements. First it requires now node.js version 4.0 and above. Another big change is, that all functions now return promises. You can use them like before with callbacks OR with promises (see example in this documentation). I am sure, there is for sure room for improvement. -I was only able to test it on several Debian, Raspbian, Ubuntu distributions as well as OS X (Mavericks, Yosemite, El Captain) and some Windows machines. -Since version 2 nearly all functionality is available for OS X/Darwin platforms. In Version 3 I started to add (limited!) windows support. +I was only able to test it on several Debian, Raspbian, Ubuntu distributions as well as OS X (Mavericks, Yosemite, El Captain) and some Windows and FreeBSD machines. +Since version 2 nearly all functionality is available for OS X/Darwin platforms. In Version 3 I started to add windows and (partial) FreeBSD support - see docs. If you have comments, suggestions & reports, please feel free to contact me! @@ -84,333 +84,334 @@ I also created a nice little command line tool called [mmon][mmon-github-url] ( #### 1. General -| Function | Result object | Linux | OSX | Win | Comments | -| --------------- | ----- | ----- | ---- | ------- | -------- | -| si.version() | : string | X | X | X | lib version (no callback/promise) | -| si.time() | {...} | X | X | X | (no callback/promise) | -| | current | X | X | X | local time | -| | uptime | X | X | X | uptime | -| | timezone | X | X | X | e.g. GMT+0200 | -| | timezoneName | X | X | X | e.g. CEST | +| Function | Result object | Linux | FreeBSD | OSX | Win | Comments | +| --------------- | ------------- | ----- | ------- | --- | --- | -------- | +| si.version() | : string | X | X | X | X | lib version (no callback/promise) | +| si.time() | {...} | X | X | X | X | (no callback/promise) | +| | current | X | X | X | X | local time | +| | uptime | X | X | X | X | uptime | +| | timezone | X | X | X | X | e.g. GMT+0200 | +| | timezoneName | X | X | X | X | e.g. CEST | #### 2. System (HW) -| Function | Result object | Linux | OSX | Win | Comments | -| --------------- | ----- | ----- | ---- | ------- | -------- | -| si.system(cb) | {...} | X | X | X | hardware information | -| | manufacturer | X | X | X | e.g. 'MSI' | -| | model | X | X | X | model/product e.g. 'MS-7823' | -| | version | X | X | X | version e.g. '1.0' | -| | serial | X | X | X | serial number | -| | uuid | X | X | X | UUID | -| | sku | X | | X | SKU number | -| si.bios(cb) | {...} | X | X | X | hardware information | -| | vendor | X | X | X | e.g. 'AMI' | -| | version | X | | X | version | -| | releaseDate | X | | X | release date | -| | revision | X | | X | revision | -| si.baseboard(cb) | {...} | X | X | X | hardware information | -| | manufacturer | X | X | X | e.g. 'ASUS' | -| | model | X | X | X | model / product name | -| | version | X | X | X | version | -| | serial | X | X | X | serial number | -| | assetTag | X | X | X | asset tag | +| Function | Result object | Linux | FreeBSD | OSX | Win | Comments | +| --------------- | ------------- | ----- | ------- | --- | --- | -------- | +| si.system(cb) | {...} | X | X | X | X | hardware information | +| | manufacturer | X | X | X | X | e.g. 'MSI' | +| | model | X | X | X | X | model/product e.g. 'MS-7823' | +| | version | X | X | X | X | version e.g. '1.0' | +| | serial | X | X | X | X | serial number | +| | uuid | X | X | X | X | UUID | +| | sku | X | X | | X | SKU number | +| si.bios(cb) | {...} | X | X | X | X | hardware information | +| | vendor | X | X | X | X | e.g. 'AMI' | +| | version | X | X | | X | version | +| | releaseDate | X | X | | X | release date | +| | revision | X | X | | X | revision | +| si.baseboard(cb) | {...} | X | X | X | X | hardware information | +| | manufacturer | X | X | X | X | e.g. 'ASUS' | +| | model | X | X | X | X | model / product name | +| | version | X | X | X | X | version | +| | serial | X | X | X | X | serial number | +| | assetTag | X | X | X | X | asset tag | #### 3. CPU, Memory, Disks, Battery, Graphics -| Function | Result object | Linux | OSX | Win | Comments | -| --------------- | ----- | ----- | ---- | ------- | -------- | -| si.cpu(cb) | {...} | X | X | X | CPU information| -| | manufacturer | X | X | X | e.g. 'Intel(R)' | -| | brand | X | X | X | e.g. 'Core(TM)2 Duo' | -| | speed | X | X | X | in GHz e.g. '3.40' | -| | speedmin | X | X | X | in GHz e.g. '0.80' | -| | speedmax | X | X | X | in GHz e.g. '3.90' | -| | cores | X | X | X | # cores | -| | vendor | X | X | X | vendor ID | -| | family | X | X | X | processor family | -| | Model | X | X | X | processor model | -| | stepping | X | X | X | processor stepping | -| | revision | X | X | X | revision | -| | cache | X | X | X | cache in bytes (object) | -| | cache.l1d | X | X | X | L1D (data) size | -| | cache.l1i | X | X | X | L1I (instruction) size | -| | cache.l2 | X | X | X | L2 size | -| | cache.l3 | X | X | X | L3 size | -| si.cpuFlags(cb) | : string | X | X | X | CPU flags| -| si.cpuCache(cb) | {...} | X | X | X | CPU cache sizes | -| | l1d | X | X | X | L1D size | -| | l1i | X | X | X | L1I size | -| | l2 | X | X | X | L2 size | -| | l3 | X | X | X | L3 size | -| si.cpuCurrentspeed(cb) | {...} | X | X | X | current CPU speed (in GHz)| -| | avg | X | X | X | avg CPU speed (all cores) | -| | min | X | X | X | min CPU speed (all cores) | -| | max | X | X | X | max CPU speed (all cores) | -| si.cpuTemperature(cb) | {...} | X | X* | X | CPU temperature (if supported) | -| | main | X | X | X | main temperature (avg) | -| | cores | X | X | X | array of temperatures | -| | max | X | X | X | max temperature | -| si.mem(cb) | {...} | X | X | X | Memory information (in bytes)| -| | total | X | X | X | total memory in bytes | -| | free | X | X | X | not used in bytes | -| | used | X | X | X | used (incl. buffers/cache) | -| | active | X | X | X | used actively (excl. buffers/cache) | -| | buffcache | X | X | | used by buffers+cache | -| | available | X | X | X | potentially available (total - active) | -| | swaptotal | X | X | X | | -| | swapused | X | X | X | | -| | swapfree | X | X | X | | -| si.memLayout(cb) | {...} | X | X | X | Memory Layout | -| | size | X | X | X | size in bytes | -| | bank | X | | X | memory bank | -| | type | X | X | X | memory type | -| | clockSpeed | X | X | X | clock speed | -| | formFactor | X | | X | form factor | -| | manufacturer | X | X | X | manufacturer | -| | partNum | X | X | X | part number | -| | serialNum | X | X | X | serial number | -| | voltageConfigured | X | | X | voltage conf. | -| | voltageMin | X | | X | voltage min | -| | voltageMax | X | | X | voltage max | -| si.diskLayout(cb) | {...} | X | X | X | physical disk layout (HD) | -| | type | X | X | X | HD, SSD | -| | name | X | X | X | disk name | -| | vendor | X | | X | vendor/producer | -| | firmwareRevision | X | X | X | firmware revision | -| | serialNum | X | X | X | serial number | -| | interfaceType | | | X | | -| | size | X | X | X | size in bytes | -| | totalCylinders | | | X | total cylinders | -| | totalHeads | | | X | total heads | -| | totalTracks | | | X | total tracks | -| | tracksPerCylinder | | | X | tracks per cylinder | -| | sectorsPerTrack | | | X | sectors per track | -| | totalSectors | | | X | total sectors | -| | bytesPerSector | | | X | bytes per sector | -| si.battery(cb) | {...} | X | X | X | battery information | -| | hasbattery | X | X | X | indicates presence of battery | -| | cyclecount | X | X | | numbers of recharges | -| | ischarging | X | X | X | indicates if battery is charging | -| | maxcapacity | X | X | X | max capacity of battery | -| | currentcapacity | X | X | X | current capacity of battery | -| | percent | X | X | X | charging level in percent | -| si.graphics(cb) | {...} | X | X | X | arrays of graphics controllers and displays | -| | controllers[]| X | X | X | graphics controllers array | -| | ...[0].model | X | X | X | graphics controller model | -| | ...[0].vendor | X | X | X | e.g. ATI | -| | ...[0].bus | X | X | X| on which bus (e.g. PCIe) | -| | ...[0].vram | X | X | X | VRAM size (in MB) | -| | ...[0].vramDynamic | X | X | X | true if dynamicly allocated ram | -| | displays[] | X | X | X | monitor/display Array | -| | ...[0].model | X | X | X | monitor/display Model | -| | ...[0].main | X | X | | true if main monitor | -| | ...[0].builtin | X | X | | true if built in monitor | -| | ...[0].connection | X | X | | e.g. DisplayPort or HDMI | -| | ...[0].resolutionx | X | X | X | pixel horizontal | -| | ...[0].resolutiony | X | X | X | pixel vertical | -| | ...[0].pixeldepth | X | X | X | color depth in bits | -| | ...[0].sizex | X | X | | size in mm horizontal | -| | ...[0].sizey | X | X | | size in mm vertical | +| Function | Result object | Linux | FreeBSD | OSX | Win | Comments | +| --------------- | ------------- | ----- | ------- | --- | --- | -------- | +| si.cpu(cb) | {...} | X | X | X | X | CPU information| +| | manufacturer | X | X | X | X | e.g. 'Intel(R)' | +| | brand | X | X | X | X | e.g. 'Core(TM)2 Duo' | +| | speed | X | X | X | X | in GHz e.g. '3.40' | +| | speedmin | X | | X | X | in GHz e.g. '0.80' | +| | speedmax | X | X | X | X | in GHz e.g. '3.90' | +| | cores | X | X | X | X | # cores | +| | vendor | X | X | X | X | vendor ID | +| | family | X | X | X | X | processor family | +| | Model | X | X | X | X | processor model | +| | stepping | X | X | X | X | processor stepping | +| | revision | X | | X | X | revision | +| | voltage | | X | | | voltage | +| | cache | X | X | X | X | cache in bytes (object) | +| | cache.l1d | X | X | X | X | L1D (data) size | +| | cache.l1i | X | X | X | X | L1I (instruction) size | +| | cache.l2 | X | X | X | X | L2 size | +| | cache.l3 | X | X | X | X | L3 size | +| si.cpuFlags(cb) | : string | X | X | X | X | CPU flags| +| si.cpuCache(cb) | {...} | X | X | X | X | CPU cache sizes | +| | l1d | X | X | X | X | L1D size | +| | l1i | X | X | X | X | L1I size | +| | l2 | X | X | X | X | L2 size | +| | l3 | X | X | X | X | L3 size | +| si.cpuCurrentspeed(cb) | {...} | X | X | X | X | current CPU speed (in GHz)| +| | avg | X | X | X | X | avg CPU speed (all cores) | +| | min | X | X | X | X | min CPU speed (all cores) | +| | max | X | X | X | X | max CPU speed (all cores) | +| si.cpuTemperature(cb) | {...} | X | X | X* | X | CPU temperature (if supported) | +| | main | X | X | X | X | main temperature (avg) | +| | cores | X | X | X | X | array of temperatures | +| | max | X | X | X | X | max temperature | +| si.mem(cb) | {...} | X | X | X | X | Memory information (in bytes)| +| | total | X | X | X | X | total memory in bytes | +| | free | X | X | X | X | not used in bytes | +| | used | X | X | X | X | used (incl. buffers/cache) | +| | active | X | X | X | X | used actively (excl. buffers/cache) | +| | buffcache | X | X | X | | used by buffers+cache | +| | available | X | X | X | X | potentially available (total - active) | +| | swaptotal | X | X | X | X | | +| | swapused | X | X | X | X | | +| | swapfree | X | X | X | X | | +| si.memLayout(cb) | {...} | X | X | X | X | Memory Layout | +| | size | X | X | X | X | size in bytes | +| | bank | X | X | | X | memory bank | +| | type | X | X | X | X | memory type | +| | clockSpeed | X | X | X | X | clock speed | +| | formFactor | X | X | | X | form factor | +| | manufacturer | X | X | X | X | manufacturer | +| | partNum | X | X | X | X | part number | +| | serialNum | X | X | X | X | serial number | +| | voltageConfigured | X | X | | X | voltage conf. | +| | voltageMin | X | X | | X | voltage min | +| | voltageMax | X | X | | X | voltage max | +| si.diskLayout(cb) | {...} | X | | X | X | physical disk layout (HD) | +| | type | X | | X | X | HD, SSD | +| | name | X | | X | X | disk name | +| | vendor | X | | | X | vendor/producer | +| | firmwareRevision | X | | X | X | firmware revision | +| | serialNum | X | | X | X | serial number | +| | interfaceType | | | | X | | +| | size | X | | X | X | size in bytes | +| | totalCylinders | | | | X | total cylinders | +| | totalHeads | | | | X | total heads | +| | totalTracks | | | | X | total tracks | +| | tracksPerCylinder | | | | X | tracks per cylinder | +| | sectorsPerTrack | | | | X | sectors per track | +| | totalSectors | | | | X | total sectors | +| | bytesPerSector | | | | X | bytes per sector | +| si.battery(cb) | {...} | X | X | X | X | battery information | +| | hasbattery | X | X | X | X | indicates presence of battery | +| | cyclecount | X | | X | | numbers of recharges | +| | ischarging | X | X | X | X | indicates if battery is charging | +| | maxcapacity | X | | X | X | max capacity of battery | +| | currentcapacity | X | | X | X | current capacity of battery | +| | percent | X | X | X | X | charging level in percent | +| si.graphics(cb) | {...} | X | | X | X | arrays of graphics controllers and displays | +| | controllers[]| X | | X | X | graphics controllers array | +| | ...[0].model | X | | X | X | graphics controller model | +| | ...[0].vendor | X | | X | X | e.g. ATI | +| | ...[0].bus | X | | X | X| on which bus (e.g. PCIe) | +| | ...[0].vram | X | | X | X | VRAM size (in MB) | +| | ...[0].vramDynamic | X | | X | X | true if dynamicly allocated ram | +| | displays[] | X | | X | X | monitor/display Array | +| | ...[0].model | X | | X | X | monitor/display Model | +| | ...[0].main | X | | X | | true if main monitor | +| | ...[0].builtin | X | | X | | true if built in monitor | +| | ...[0].connection | X | | X | | e.g. DisplayPort or HDMI | +| | ...[0].resolutionx | X | | X | X | pixel horizontal | +| | ...[0].resolutiony | X | | X | X | pixel vertical | +| | ...[0].pixeldepth | X | | X | X | color depth in bits | +| | ...[0].sizex | X | | X | | size in mm horizontal | +| | ...[0].sizey | X | | X | | size in mm vertical | #### 4. Operating System -| Function | Result object | Linux | OSX | Win | Comments | -| --------------- | ----- | ----- | ---- | ------- | -------- | -| si.osInfo(cb) | {...} | X | X | X | OS information | -| | platform | X | X | X | 'Linux', 'Darwin', 'Windows' | -| | distro | X | X | X | | -| | release | X | X | X | | -| | codename | | X | | | -| | kernel | X | X | X | kernel release - same as os.release() | -| | arch | X | X | X | same as os.arch() | -| | hostname | X | X | X | same as os.hostname() | -| | logofile | X | X | X | e.g. 'apple', 'debian', 'fedora', ... | -| si.versions(cb) | {...} | X | X | X | version information (kernel, ssl, node, ...) | -| si.shell(cb) | : string | X | X | | standard shell | -| si.users(cb) | [{...}] | X | X | X | array of users online | -| | [0].user | X | X | X | user name | -| | [0].tty | X | X | X | terminal | -| | [0].date | X | X | X | login date | -| | [0].time | X | X | X | login time | -| | [0].ip | X | X | | ip address (remote login) | -| | [0].command | X | X | | last command or shell | +| Function | Result object | Linux | FreeBSD | OSX | Win | Comments | +| --------------- | ------------- | ----- | ------- | --- | --- | -------- | +| si.osInfo(cb) | {...} | X | X | X | X | OS information | +| | platform | X | X | X | X | 'Linux', 'Darwin', 'Windows' | +| | distro | X | X | X | X | | +| | release | X | X | X | X | | +| | codename | | | X | | | +| | kernel | X | X | X | X | kernel release - same as os.release() | +| | arch | X | X | X | X | same as os.arch() | +| | hostname | X | X | X | X | same as os.hostname() | +| | logofile | X | X | X | X | e.g. 'apple', 'debian', 'fedora', ... | +| si.versions(cb) | {...} | X | X | X | X | version information (kernel, ssl, node, ...) | +| si.shell(cb) | : string | X | X | X | | standard shell | +| si.users(cb) | [{...}] | X | X | X | X | array of users online | +| | [0].user | X | X | X | X | user name | +| | [0].tty | X | X | X | X | terminal | +| | [0].date | X | X | X | X | login date | +| | [0].time | X | X | X | X | login time | +| | [0].ip | X | X | X | | ip address (remote login) | +| | [0].command | X | X | X | | last command or shell | #### 5. File System -| Function | Result object | Linux | OSX | Win | Comments | -| --------------- | ----- | ----- | ---- | ------- | -------- | -| si.fsSize(cb) | [{...}] | X | X | X | returns array of mounted file systems | -| | [0].fs | X | X | X | name of file system | -| | [0].type | X | X | X | type of file system | -| | [0].size | X | X | X | sizes in bytes | -| | [0].used | X | X | X | used in bytes | -| | [0].use | X | X | X | used in % | -| | [0].mount | X | X | X | mount point | -| si.blockDevices(cb) | [{...}] | X | X | X | returns array of disks, partitions,
raids and roms | -| | [0].name | X | X | X | name | -| | [0].type | X | X | X | type | -| | [0].fstype | X | X | X | file system type (e.g. ext4) | -| | [0].mount | X | X | X | mount point | -| | [0].size | X | X | X | size in bytes | -| | [0].physical | X | X | X | physical type (HDD, SSD, CD/DVD) | -| | [0].uuid | X | X | X | UUID | -| | [0].label | X | X | X | label | -| | [0].model | X | X | | model | -| | [0].serial | X | | X | serial | -| | [0].removable | X | X | X | serial | -| | [0].protocol | X | X | | protocol (SATA, PCI-Express, ...) | -| si.fsStats(cb) | {...} | X | X | | current transfer stats | -| | rx | X | X | | bytes read since startup | -| | wx | X | X | | bytes written since startup | -| | tx | X | X | | total bytes read + written since startup | -| | rx_sec | X | X | | bytes read / second (* see notes) | -| | wx_sec | X | X | | bytes written / second (* see notes) | -| | tx_sec | X | X | | total bytes reads + written / second | -| | ms | X | X | | interval length (for per second values) | -| si.disksIO(cb) | {...} | X | X | | current transfer stats | -| | rIO | X | X | | read IOs on all mounted drives | -| | wIO | X | X | | write IOs on all mounted drives | -| | tIO | X | X | | write IOs on all mounted drives | -| | rIO_sec | X | X | | read IO per sec (* see notes) | -| | wIO_sec | X | X | | write IO per sec (* see notes) | -| | tIO_sec | X | X | | total IO per sec (* see notes) | -| | ms | X | X | | interval length (for per second values) | +| Function | Result object | Linux | FreeBSD | OSX | Win | Comments | +| --------------- | ------------- | ----- | ------- | --- | --- | -------- | +| si.fsSize(cb) | [{...}] | X | X | X | X | returns array of mounted file systems | +| | [0].fs | X | X | X | X | name of file system | +| | [0].type | X | X | X | X | type of file system | +| | [0].size | X | X | X | X | sizes in bytes | +| | [0].used | X | X | X | X | used in bytes | +| | [0].use | X | X | X | X | used in % | +| | [0].mount | X | X | X | X | mount point | +| si.blockDevices(cb) | [{...}] | X | | X | X | returns array of disks, partitions,
raids and roms | +| | [0].name | X | | X | X | name | +| | [0].type | X | | X | X | type | +| | [0].fstype | X | | X | X | file system type (e.g. ext4) | +| | [0].mount | X | | X | X | mount point | +| | [0].size | X | | X | X | size in bytes | +| | [0].physical | X | | X | X | physical type (HDD, SSD, CD/DVD) | +| | [0].uuid | X | | X | X | UUID | +| | [0].label | X | | X | X | label | +| | [0].model | X | | X | | model | +| | [0].serial | X | | | X | serial | +| | [0].removable | X | | X | X | serial | +| | [0].protocol | X | | X | | protocol (SATA, PCI-Express, ...) | +| si.fsStats(cb) | {...} | X | | X | | current transfer stats | +| | rx | X | | X | | bytes read since startup | +| | wx | X | | X | | bytes written since startup | +| | tx | X | | X | | total bytes read + written since startup | +| | rx_sec | X | | X | | bytes read / second (* see notes) | +| | wx_sec | X | | X | | bytes written / second (* see notes) | +| | tx_sec | X | | X | | total bytes reads + written / second | +| | ms | X | | X | | interval length (for per second values) | +| si.disksIO(cb) | {...} | X | | X | | current transfer stats | +| | rIO | X | | X | | read IOs on all mounted drives | +| | wIO | X | | X | | write IOs on all mounted drives | +| | tIO | X | | X | | write IOs on all mounted drives | +| | rIO_sec | X | | X | | read IO per sec (* see notes) | +| | wIO_sec | X | | X | | write IO per sec (* see notes) | +| | tIO_sec | X | | X | | total IO per sec (* see notes) | +| | ms | X | | X | | interval length (for per second values) | #### 6. Network related functions -| Function | Result object | Linux | OSX | Win | Comments | -| --------------- | ----- | ----- | ---- | ------- | -------- | -| si.networkInterfaces(cb) | [{...}] | X | X | X | array of network interfaces | -| | [0].iface | X | X | X | interface name | -| | [0].ip4 | X | X | X | ip4 address | -| | [0].ip6 | X | X | X | ip6 address | -| | [0].mac | X | X | X | MAC address | -| | [0].internal | X | X | X | true if internal interface | -| si.networkInterfaceDefault(cb) | : string | X | X | X | get name of default network interface | -| si.networkStats(iface,cb) | {...} | X | X | X | current network stats of given interface
iface parameter is optional
defaults to first external network interface| -| | iface | X | X | X | interface | -| | operstate | X | X | X | up / down | -| | rx | X | X | X | received bytes overall | -| | tx | X | X | X | transferred bytes overall | -| | rx_sec | X | X | X | received bytes / second (* see notes) | -| | tx_sec | X | X | X | transferred bytes per second (* see notes) | -| | ms | X | X | X | interval length (for per second values) | -| si.networkConnections(cb) | [{...}] | X | X | X | current network network connections
returns an array of all connections| -| | [0].protocol | X | X | X | tcp or udp | -| | [0].localaddress | X | X | X | local address | -| | [0].localport | X | X | X | local port | -| | [0].peeraddress | X | X | X | peer address | -| | [0].peerport | X | X | X | peer port | -| | [0].state | X | X | X | like ESTABLISHED, TIME_WAIT, ... | -| si.inetChecksite(url, cb) | {...} | X | X | X | response-time (ms) to fetch given URL | -| | url | X | X | X | given url | -| | ok | X | X | X | status code OK (2xx, 3xx) | -| | status | X | X | X | status code | -| | ms | X | X | X | response time in ms | -| si.inetLatency(host, cb) | : number | X | X | X | response-time (ms) to external resource
host parameter is optional (default 8.8.8.8)| +| Function | Result object | Linux | FreeBSD | OSX | Win | Comments | +| --------------- | ------------- | ----- | ------- | --- | --- | -------- | +| si.networkInterfaces(cb) | [{...}] | X | X | X | X | array of network interfaces | +| | [0].iface | X | X | X | X | interface name | +| | [0].ip4 | X | X | X | X | ip4 address | +| | [0].ip6 | X | X | X | X | ip6 address | +| | [0].mac | X | X | X | X | MAC address | +| | [0].internal | X | X | X | X | true if internal interface | +| si.networkInterfaceDefault(cb) | : string | X | X | X | X | get name of default network interface | +| si.networkStats(iface,cb) | {...} | X | | X | X | current network stats of given interface
iface parameter is optional
defaults to first external network interface| +| | iface | X | | X | X | interface | +| | operstate | X | | X | X | up / down | +| | rx | X | | X | X | received bytes overall | +| | tx | X | | X | X | transferred bytes overall | +| | rx_sec | X | | X | X | received bytes / second (* see notes) | +| | tx_sec | X | | X | X | transferred bytes per second (* see notes) | +| | ms | X | | X | X | interval length (for per second values) | +| si.networkConnections(cb) | [{...}] | X | | X | X | current network network connections
returns an array of all connections| +| | [0].protocol | X | | X | X | tcp or udp | +| | [0].localaddress | X | | X | X | local address | +| | [0].localport | X | | X | X | local port | +| | [0].peeraddress | X | | X | X | peer address | +| | [0].peerport | X | | X | X | peer port | +| | [0].state | X | | X | X | like ESTABLISHED, TIME_WAIT, ... | +| si.inetChecksite(url, cb) | {...} | X | X | X | X | response-time (ms) to fetch given URL | +| | url | X | X | X | X | given url | +| | ok | X | X | X | X | status code OK (2xx, 3xx) | +| | status | X | X | X | X | status code | +| | ms | X | X | X | X | response time in ms | +| si.inetLatency(host, cb) | : number | X | X | X | X | response-time (ms) to external resource
host parameter is optional (default 8.8.8.8)| #### 7. Current Load, Processes & Services -| Function | Result object | Linux | OSX | Win | Comments | -| --------------- | ----- | ----- | ---- | ------- | -------- | -| si.currentLoad(cb) | {...} | X | X | X | CPU-Load | -| | avgload | X | X | X | average load | -| | currentload | X | X | X | CPU load in % | -| | currentload_user | X | X | X | CPU load user in % | -| | currentload_system | X | X | X | CPU load system in % | -| | currentload_nice | X | X | X | CPU load nice in % | -| | currentload_idle | X | X | X | CPU load idle in % | -| | currentload_irq | X | X | X | CPU load system in % | -| | raw_currentload... | X | X | X | CPU load raw values (ticks) | -| | cpus[] | X | X | X | current loads per CPU in % + raw ticks | -| si.fullLoad(cb) | : integer | X | X | X | CPU full load since bootup in % | -| si.processes(cb) | {...} | X | X | X | # running processes | -| | all | X | X | X | # of all processes | -| | running | X | X | X | # of all processes running | -| | blocked | X | X | X | # of all processes blocked | -| | sleeping | X | X | X | # of all processes sleeping | -| | unknown | | | X | # of all processes unknown status | -| | list[] | X | X | X | list of all processes incl. details | -| | ...[0].pid | X | X | X | process PID | -| | ...[0].name | X | X | X | process name | -| | ...[0].pcpu | X | X | X | process % CPU usage | -| | ...[0].pcpuu | X | | X | process % CPU usage (user) | -| | ...[0].pcpus | X | | X | process % CPU usage (system) | -| | ...[0].pmem | X | X | X | process memory % | -| | ...[0].priority | X | X | X | process priotity | -| | ...[0].mem_vsz | X | X | X | process virtual memory size | -| | ...[0].mem_rss | X | X | X | process mem resident set size | -| | ...[0].nice | X | X | | process nice value | -| | ...[0].started | X | X | X | process start time | -| | ...[0].state | X | X | X | process state (e.g. sleeping) | -| | ...[0].tty | X | X | | tty from which process was started | -| | ...[0].user | X | X | | user who started process | -| | ...[0].command | X | X | X | process starting command | -| si.processLoad('apache2',cb) | {...} | X | X | | detailed information about given process | -| | proc | X | X | | process name | -| | pid | X | X | | PID | -| | cpu | X | X | | process % CPU | -| | mem | X | X | | process % MEM | -| si.services('mysql, apache2', cb) | [{...}] | X | X | X | pass comma separated string of services | -| | [0].name | X | X | X | name of service | -| | [0].running | X | X | X | true / false | -| | [0].pcpu | X | X | | process % CPU | -| | [0].pmem | X | X | | process % MEM | +| Function | Result object | Linux | FreeBSD | OSX | Win | Comments | +| --------------- | ------------- | ----- | ------- | --- | --- | -------- | +| si.currentLoad(cb) | {...} | X | | X | X | CPU-Load | +| | avgload | X | | X | X | average load | +| | currentload | X | | X | X | CPU load in % | +| | currentload_user | X | | X | X | CPU load user in % | +| | currentload_system | X | | X | X | CPU load system in % | +| | currentload_nice | X | | X | X | CPU load nice in % | +| | currentload_idle | X | | X | X | CPU load idle in % | +| | currentload_irq | X | | X | X | CPU load system in % | +| | raw_currentload... | X | | X | X | CPU load raw values (ticks) | +| | cpus[] | X | | X | X | current loads per CPU in % + raw ticks | +| si.fullLoad(cb) | : integer | X | | X | X | CPU full load since bootup in % | +| si.processes(cb) | {...} | X | X | X | X | # running processes | +| | all | X | X | X | X | # of all processes | +| | running | X | X | X | X | # of all processes running | +| | blocked | X | X | X | X | # of all processes blocked | +| | sleeping | X | X | X | X | # of all processes sleeping | +| | unknown | | | | X | # of all processes unknown status | +| | list[] | X | X | X | X | list of all processes incl. details | +| | ...[0].pid | X | X | X | X | process PID | +| | ...[0].name | X | X | X | X | process name | +| | ...[0].pcpu | X | X | X | X | process % CPU usage | +| | ...[0].pcpuu | X | X | | X | process % CPU usage (user) | +| | ...[0].pcpus | X | X | | X | process % CPU usage (system) | +| | ...[0].pmem | X | X | X | X | process memory % | +| | ...[0].priority | X | X | X | X | process priotity | +| | ...[0].mem_vsz | X | X | X | X | process virtual memory size | +| | ...[0].mem_rss | X | X | X | X | process mem resident set size | +| | ...[0].nice | X | X | X | | process nice value | +| | ...[0].started | X | X | X | X | process start time | +| | ...[0].state | X | X | X | X | process state (e.g. sleeping) | +| | ...[0].tty | X | X | X | | tty from which process was started | +| | ...[0].user | X | X | X | | user who started process | +| | ...[0].command | X | X | X | X | process starting command | +| si.processLoad('apache2',cb) | {...} | X | | X | | detailed information about given process | +| | proc | X | | X | | process name | +| | pid | X | | X | | PID | +| | cpu | X | | X | | process % CPU | +| | mem | X | | X | | process % MEM | +| si.services('mysql, apache2', cb) | [{...}] | X | X | X | X | pass comma separated string of services | +| | [0].name | X | X | X | X | name of service | +| | [0].running | X | X | X | X | true / false | +| | [0].pcpu | X | X | X | | process % CPU | +| | [0].pmem | X | X | X | | process % MEM | #### 8. Docker -| Function | Result object | Linux | OSX | Win | Comments | -| --------------- | ----- | ----- | ---- | ------- | -------- | -| si.dockerContainers(all, cb) | [{...}] | X | X | X | returns array of active/all docker containers | -| | [0].id | X | X | X | ID of container | -| | [0].name | X | X | X | name of container | -| | [0].image | X | X | X | name of image | -| | [0].imageID | X | X | X | ID of image | -| | [0].command | X | X | X | command | -| | [0].created | X | X | X | creation time | -| | [0].state | X | X | X | created, running, exited | -| | [0].ports | X | X | X | array of ports | -| | [0].mounts | X | X | X | array of mounts | -| si.dockerContainerStats(id, cb) | {...} | X | X | X | statistics for a specific container | -| | id | X | X | X | Container ID | -| | mem_usage | X | X | X | memory usage in bytes | -| | mem_limit | X | X | X | memory limit (max mem) in bytes | -| | mem_percent | X | X | X | memory usage in percent | -| | cpu_percent | X | X | X | cpu usage in percent | -| | pids | X | X | X | number of processes | -| | netIO.rx | X | X | X | received bytes via network | -| | netIO.wx | X | X | X | sent bytes via network | -| | blockIO.r | X | X | X | bytes read from BlockIO | -| | blockIO.w | X | X | X | bytes written to BlockIO | -| | cpu_stats | X | X | X | detailed cpu stats | -| | percpu_stats | X | X | X | detailed per cpu stats | -| | memory_stats | X | X | X | detailed memory stats | -| | networks | X | X | X | detailed network stats per interface | -| si.dockerContainerProcesses(id, cb) | [{...}] | X | X | X | array of processes inside a container | -| | [0].pid_host | X | X | X | process ID (host) | -| | [0].ppid | X | X | X | parent process ID | -| | [0].pgid | X | X | X | process group ID | -| | [0].user | X | X | X | effective user name | -| | [0].ruser | X | X | X | real user name | -| | [0].group | X | X | X | effective group name | -| | [0].rgroup | X | X | X | real group name | -| | [0].stat | X | X | X | process state | -| | [0].time | X | X | X | accumulated CPU time | -| | [0].elapsed | X | X | X | elapsed running time | -| | [0].nice | X | X | X | nice value | -| | [0].rss | X | X | X | resident set size | -| | [0].vsz | X | X | X | virtual size in Kbytes | -| | [0].command | X | X | X | command and arguments | -| si.dockerAll(cb) | {...} | X | X | X | list of all containers including their stats
and processes in one single array | +| Function | Result object | Linux | FreeBSD | OSX | Win | Comments | +| --------------- | ------------- | ----- | ------- | --- | --- | -------- | +| si.dockerContainers(all, cb) | [{...}] | X | X | X | X | returns array of active/all docker containers | +| | [0].id | X | X | X | X | ID of container | +| | [0].name | X | X | X | X | name of container | +| | [0].image | X | X | X | X | name of image | +| | [0].imageID | X | X | X | X | ID of image | +| | [0].command | X | X | X | X | command | +| | [0].created | X | X | X | X | creation time | +| | [0].state | X | X | X | X | created, running, exited | +| | [0].ports | X | X | X | X | array of ports | +| | [0].mounts | X | X | X | X | array of mounts | +| si.dockerContainerStats(id, cb) | {...} | X | X | X | X | statistics for a specific container | +| | id | X | X | X | X | Container ID | +| | mem_usage | X | X | X | X | memory usage in bytes | +| | mem_limit | X | X | X | X | memory limit (max mem) in bytes | +| | mem_percent | X | X | X | X | memory usage in percent | +| | cpu_percent | X | X | X | X | cpu usage in percent | +| | pids | X | X | X | X | number of processes | +| | netIO.rx | X | X | X | X | received bytes via network | +| | netIO.wx | X | X | X | X | sent bytes via network | +| | blockIO.r | X | X | X | X | bytes read from BlockIO | +| | blockIO.w | X | X | X | X | bytes written to BlockIO | +| | cpu_stats | X | X | X | X | detailed cpu stats | +| | percpu_stats | X | X | X | X | detailed per cpu stats | +| | memory_stats | X | X | X | X | detailed memory stats | +| | networks | X | X | X | X | detailed network stats per interface | +| si.dockerContainerProcesses(id, cb) | [{...}] | X | X | X | X | array of processes inside a container | +| | [0].pid_host | X | X | X | X | process ID (host) | +| | [0].ppid | X | X | X | X | parent process ID | +| | [0].pgid | X | X | X | X | process group ID | +| | [0].user | X | X | X | X | effective user name | +| | [0].ruser | X | X | X | X | real user name | +| | [0].group | X | X | X | X | effective group name | +| | [0].rgroup | X | X | X | X | real group name | +| | [0].stat | X | X | X | X | process state | +| | [0].time | X | X | X | X | accumulated CPU time | +| | [0].elapsed | X | X | X | X | elapsed running time | +| | [0].nice | X | X | X | X | nice value | +| | [0].rss | X | X | X | X | resident set size | +| | [0].vsz | X | X | X | X | virtual size in Kbytes | +| | [0].command | X | X | X | X | command and arguments | +| si.dockerAll(cb) | {...} | X | X | X | X | list of all containers including their stats
and processes in one single array | #### 9. "Get All at once" - functions -| Function | Result object | Linux | OSX | Win | Comments | -| --------------- | ----- | ----- | ---- | ------- | -------- | -| si.getStaticData(cb) | {...} | X | X | X | all static data at once | -| si.getDynamicData(srv,iface,cb) | {...} | X | X | X | all dynamic data at once | -| si.getAllData(srv,iface,cb) | {...} | X | X | X | all data at once | +| Function | Result object | Linux | FreeBSD | OSX | Win | Comments | +| --------------- | ------------- | ----- | ------- | --- | --- | -------- | +| si.getStaticData(cb) | {...} | X | X | X | X | all static data at once | +| si.getDynamicData(srv,iface,cb) | {...} | X | X | X | X | all dynamic data at once | +| si.getAllData(srv,iface,cb) | {...} | X | X | X | X | all data at once | ### cb: Asynchronous Function Calls (callback) @@ -566,10 +567,13 @@ OSX Temperature: credits here are going to: ## Copyright Information -Linux is a registered trademark of Linus Torvalds, OS X is a registered trademark of Apple Inc., +Linux is a registered trademark of Linus Torvalds, Apple, Mac OS, OS X is a registered trademark of Apple Inc., Windows is a registered trademark of Microsoft Corporation. Node.js is a trademark of Joyent Inc., -Intel is a trademark of Intel Corporation, AMD is a trademark of Advanced Micro Devices Inc., Raspberry Pi is a trademark of the Raspberry Pi Foundation, -Debian is a trademark of the Debian Project, Ubuntu is a trademark of Canonical Ltd., Docker is a trademark of Docker, Inc. +Intel is a trademark of Intel Corporation, AMD is a trademark of Advanced Micro Devices Inc., +Raspberry Pi is a trademark of the Raspberry Pi Foundation, Debian is a trademark of the Debian Project, +Ubuntu is a trademark of Canonical Ltd., FreeBSD is a registered trademark of The FreeBSD Foundation, +Docker is a trademark of Docker, Inc. + All other trademarks are the property of their respective owners. ## License [![MIT license][license-img]][license-url] diff --git a/lib/battery.js b/lib/battery.js index 7f70d19..5660ca2 100644 --- a/lib/battery.js +++ b/lib/battery.js @@ -12,16 +12,17 @@ // 6. Battery // ---------------------------------------------------------------------------------- -const os = require('os'); const exec = require('child_process').exec; const fs = require('fs'); const util = require('./util'); -let _platform = os.type(); +let _platform = process.platform; -const _linux = (_platform === 'Linux'); -const _darwin = (_platform === 'Darwin'); -const _windows = (_platform === 'Windows_NT'); +const _linux = (_platform === 'linux'); +const _darwin = (_platform === 'darwin'); +const _windows = (_platform === 'win32'); +const _freebsd = (_platform === 'freebsd'); +const _openbsd = (_platform === 'openbsd'); module.exports = function (callback) { @@ -79,30 +80,41 @@ module.exports = function (callback) { resolve(result); } } + if (_freebsd || _openbsd) { + exec('sysctl hw.acpi.battery hw.acpi.acline', function (error, stdout) { + let lines = stdout.toString().split('\n'); + const batteries = parseInt('0' + util.getValue(lines,'hw.acpi.battery.units'), 10); + const percent = parseInt('0' + util.getValue(lines,'hw.acpi.battery.life'), 10); + result.hasbattery = (batteries > 0); + result.cyclecount = -1; + result.ischarging = util.getValue(lines,'hw.acpi.acline') !== '1'; + result.maxcapacity = -1; + result.currentcapacity = -1; + result.percent = batteries ? percent : -1; + if (callback) { callback(result); } + resolve(result); + }); + } + if (_darwin) { - exec("ioreg -n AppleSmartBattery -r | grep '\"CycleCount\"';ioreg -n AppleSmartBattery -r | grep '\"IsCharging\"';ioreg -n AppleSmartBattery -r | grep '\"MaxCapacity\"';ioreg -n AppleSmartBattery -r | grep '\"CurrentCapacity\"';pmset -g batt | grep %", function (error, stdout) { - if (!error) { - let lines = stdout.toString().replace(/ +/g, '').replace(/"+/g, '').split('\n'); - lines.forEach(function (line) { - if (line.indexOf('=') !== -1) { - if (line.toLowerCase().indexOf('cyclecount') !== -1) result.cyclecount = parseFloat(line.split('=')[1].trim()); - if (line.toLowerCase().indexOf('ischarging') !== -1) result.ischarging = (line.split('=')[1].trim().toLowerCase() === 'yes'); - if (line.toLowerCase().indexOf('maxcapacity') !== -1) result.maxcapacity = parseFloat(line.split('=')[1].trim()); - if (line.toLowerCase().indexOf('internalbattery') !== -1) { - let parts = line.split(';'); - if (parts && parts[0]) { - let parts2 = parts[0].split('\t'); - if (parts2 && parts2[1]) { - result.percent = parseFloat(parts2[1].trim().replace('%', '')); - } - } - } - } - }); + exec('ioreg -n AppleSmartBattery -r | egrep "CycleCount|IsCharging|MaxCapacity|CurrentCapacity";pmset -g batt | grep %', function (error, stdout) { + let lines = stdout.toString().replace(/ +/g, '').replace(/"+/g, '').replace(/-/g, '').split('\n'); + result.cyclecount = parseInt('0' + util.getValue(lines,'cyclecount', '='), 10); + result.ischarging = util.getValue(lines,'ischarging', '=').toLowerCase === 'yes'; + result.maxcapacity = parseInt('0' + util.getValue(lines,'maxcapacity', '='), 10); + result.currentcapacity = parseInt('0' + util.getValue(lines,'currentcapacity', '='), 10); + let percent = -1; + const line = util.getValue(lines,'internalbattery', '='); + let parts = line.split(';'); + if (parts && parts[0]) { + let parts2 = parts[0].split('\t'); + if (parts2 && parts2[1]) { + percent = parseFloat(parts2[1].trim().replace('%', '')); + } } if (result.maxcapacity && result.currentcapacity) { result.hasbattery = true; - result.percent = 100.0 * result.currentcapacity / result.maxcapacity; + result.percent = percent !== -1 ? percent : 100.0 * result.currentcapacity / result.maxcapacity; } if (callback) { callback(result); } resolve(result); diff --git a/lib/cpu.js b/lib/cpu.js index a677ba2..561a575 100644 --- a/lib/cpu.js +++ b/lib/cpu.js @@ -23,7 +23,7 @@ const _linux = (_platform === 'linux'); const _darwin = (_platform === 'darwin'); const _windows = (_platform === 'win32'); const _freebsd = (_platform === 'freebsd'); -const _sunos = (_platform === 'sunos'); +const _openbsd = (_platform === 'openbsd'); let _cpu_speed = '0.00'; let _current_cpu = { @@ -162,6 +162,7 @@ function getCpu() { model: '', stepping: '', revision: '', + voltage: '', speed: '0.00', speedmin: '', speedmax: '', @@ -193,42 +194,105 @@ function getCpu() { }); } if (_linux) { + let modelline = ''; + let lines = []; + if (os.cpus()[0] && os.cpus()[0].model) modelline = os.cpus()[0].model; exec('export LC_ALL=C; lscpu; unset LC_ALL', function (error, stdout) { if (!error) { - let lines = stdout.toString().split('\n'); - const modelline = util.getValue(lines, 'model name'); - result.brand = modelline.split('@')[0].trim(); - result.speed = modelline.split('@')[1] ? parseFloat(modelline.split('@')[1].trim()).toFixed(2) : '0.00'; - if (result.speed === '0.00' && result.brand.indexOf('AMD') > -1) { - result.speed = getAMDSpeed(result.brand); - } - if (result.speed === '0.00') { - let current = getCpuCurrentSpeedSync(); - if (current !== '0.00') result.speed = current.avg.toFixed(2); - } - _cpu_speed = result.speed; - result.speedmin = Math.round(parseFloat(util.getValue(lines, 'cpu min mhz').replace(/,/g, '.')) / 10.0) / 100; - result.speedmin = result.speedmin ? parseFloat(result.speedmin).toFixed(2) : ''; - result.speedmax = Math.round(parseFloat(util.getValue(lines, 'cpu max mhz').replace(/,/g, '.')) / 10.0) / 100; - result.speedmax = result.speedmax ? parseFloat(result.speedmax).toFixed(2) : ''; + lines = stdout.toString().split('\n'); + } + modelline = util.getValue(lines, 'model name') || modelline; + result.brand = modelline.split('@')[0].trim(); + result.speed = modelline.split('@')[1] ? parseFloat(modelline.split('@')[1].trim()).toFixed(2) : '0.00'; + if (result.speed === '0.00' && result.brand.indexOf('AMD') > -1) { + result.speed = getAMDSpeed(result.brand); + } + if (result.speed === '0.00') { + let current = getCpuCurrentSpeedSync(); + if (current !== '0.00') result.speed = current.avg.toFixed(2); + } + _cpu_speed = result.speed; + result.speedmin = Math.round(parseFloat(util.getValue(lines, 'cpu min mhz').replace(/,/g, '.')) / 10.0) / 100; + result.speedmin = result.speedmin ? parseFloat(result.speedmin).toFixed(2) : ''; + result.speedmax = Math.round(parseFloat(util.getValue(lines, 'cpu max mhz').replace(/,/g, '.')) / 10.0) / 100; + result.speedmax = result.speedmax ? parseFloat(result.speedmax).toFixed(2) : ''; - result = cpuBrandManufacturer(result); - result.vendor = util.getValue(lines, 'vendor id'); - // if (!result.vendor) { result.vendor = util.getValue(lines, 'anbieterkennung'); } - result.family = util.getValue(lines, 'cpu family'); - // if (!result.family) { result.family = util.getValue(lines, 'prozessorfamilie'); } - result.model = util.getValue(lines, 'model:'); - // if (!result.model) { result.model = util.getValue(lines, 'modell:'); } - result.stepping = util.getValue(lines, 'stepping'); - result.revision = util.getValue(lines, 'cpu revision'); - result.cache.l1d = util.getValue(lines, 'l1d cache'); - if (result.cache.l1d) { result.cache.l1d = parseInt(result.cache.l1d) * (result.cache.l1d.indexOf('K') !== -1 ? 1024 : 1); } - result.cache.l1i = util.getValue(lines, 'l1i cache'); - if (result.cache.l1i) { result.cache.l1i = parseInt(result.cache.l1i) * (result.cache.l1i.indexOf('K') !== -1 ? 1024 : 1); } - result.cache.l2 = util.getValue(lines, 'l2 cache'); - if (result.cache.l2) { result.cache.l2 = parseInt(result.cache.l2) * (result.cache.l2.indexOf('K') !== -1 ? 1024 : 1); } - result.cache.l3 = util.getValue(lines, 'l3 cache'); - if (result.cache.l3) { result.cache.l3 = parseInt(result.cache.l3) * (result.cache.l3.indexOf('K') !== -1 ? 1024 : 1); } + result = cpuBrandManufacturer(result); + result.vendor = util.getValue(lines, 'vendor id'); + // if (!result.vendor) { result.vendor = util.getValue(lines, 'anbieterkennung'); } + result.family = util.getValue(lines, 'cpu family'); + // if (!result.family) { result.family = util.getValue(lines, 'prozessorfamilie'); } + result.model = util.getValue(lines, 'model:'); + // if (!result.model) { result.model = util.getValue(lines, 'modell:'); } + result.stepping = util.getValue(lines, 'stepping'); + result.revision = util.getValue(lines, 'cpu revision'); + result.cache.l1d = util.getValue(lines, 'l1d cache'); + if (result.cache.l1d) { result.cache.l1d = parseInt(result.cache.l1d) * (result.cache.l1d.indexOf('K') !== -1 ? 1024 : 1); } + result.cache.l1i = util.getValue(lines, 'l1i cache'); + if (result.cache.l1i) { result.cache.l1i = parseInt(result.cache.l1i) * (result.cache.l1i.indexOf('K') !== -1 ? 1024 : 1); } + result.cache.l2 = util.getValue(lines, 'l2 cache'); + if (result.cache.l2) { result.cache.l2 = parseInt(result.cache.l2) * (result.cache.l2.indexOf('K') !== -1 ? 1024 : 1); } + result.cache.l3 = util.getValue(lines, 'l3 cache'); + if (result.cache.l3) { result.cache.l3 = parseInt(result.cache.l3) * (result.cache.l3.indexOf('K') !== -1 ? 1024 : 1); } + resolve(result); + }); + } + if (_freebsd || _openbsd) { + let modelline = ''; + let lines = []; + if (os.cpus()[0] && os.cpus()[0].model) modelline = os.cpus()[0].model; + exec('export LC_ALL=C; dmidecode -t 4; dmidecode -t 7 ; unset LC_ALL', function (error, stdout) { + let cache = []; + if (!error) { + const data = stdout.toString().split('# dmidecode'); + const processor = data.length > 0 ? data[1] : ''; + cache = data.length > 1 ? data[2].split('Cache Information') : []; + + lines = processor.split('\n'); + } + result.brand = modelline.split('@')[0].trim(); + result.speed = modelline.split('@')[1] ? parseFloat(modelline.split('@')[1].trim()).toFixed(2) : '0.00'; + if (result.speed === '0.00' && result.brand.indexOf('AMD') > -1) { + result.speed = getAMDSpeed(result.brand); + } + if (result.speed === '0.00') { + let current = getCpuCurrentSpeedSync(); + if (current !== '0.00') result.speed = current.avg.toFixed(2); + } + _cpu_speed = result.speed; + result.speedmin = ''; + result.speedmax = Math.round(parseFloat(util.getValue(lines, 'max speed').replace(/Mhz/g, '')) / 10.0) / 100; + result.speedmax = result.speedmax ? parseFloat(result.speedmax).toFixed(2) : ''; + + result = cpuBrandManufacturer(result); + result.vendor = util.getValue(lines, 'manufacturer'); + let sig = util.getValue(lines, 'signature'); + sig = sig.split(','); + for (var i = 0; i < sig.length; i++) { + sig[i] = sig[i].trim(); + } + result.family = util.getValue(sig, 'Family', ' ', true); + result.model = util.getValue(sig, 'Model', ' ', true); + result.stepping = util.getValue(sig, 'Stepping', ' ', true); + result.revision = ''; + const voltage = parseFloat(util.getValue(lines, 'voltage')); + result.voltage = isNaN(voltage) ? '' : voltage.toFixed(2); + for (let i = 0; i < cache.length; i++) { + lines = cache[i].split('\n'); + let cacheType = util.getValue(lines,'Socket Designation').toLowerCase().replace(' ', '-').split('-'); + cacheType = cacheType.length ? cacheType[0] : ''; + const sizeParts = util.getValue(lines,'Installed Size').split(' '); + let size = parseInt(sizeParts[0], 10); + const unit = sizeParts.length > 1 ? sizeParts[1] : 'kb'; + size = size * (unit === 'kb' ? 1024 : (unit === 'mb' ? 1024 * 1024 : (unit === 'gb' ? 1024 * 1024 * 1024 : 1))); + if (cacheType) { + if (cacheType === 'l1') { + result.cache[cacheType + 'd'] = size / 2; + result.cache[cacheType + 'i'] = size / 2; + } else { + result.cache[cacheType] = size; + } + } } resolve(result); }); @@ -433,6 +497,28 @@ function cpuTemperature(callback) { } }); } + if (_freebsd || _openbsd) { + exec('sysctl dev.cpu | grep temp', function (error, stdout) { + if (!error) { + let lines = stdout.toString().split('\n'); + let sum = 0; + lines.forEach(function (line) { + const parts = line.split(':'); + if (parts.length > 0) { + const temp = parseFloat(parts[1].replace(',', '.'), 10); + if (temp > result.max) result.max = temp; + sum = sum + temp; + result.cores.push(temp); + } + }); + if (result.cores.length) { + result.main = Math.round(sum / result.cores.length * 100) / 100; + } + } + if (callback) { callback(result); } + resolve(result); + }); + } if (_darwin) { let osxTemp = null; try { @@ -519,6 +605,24 @@ function cpuFlags(callback) { resolve(result); }); } + if (_freebsd || _openbsd) { + exec('export LC_ALL=C; dmidecode -t 4; unset LC_ALL', function (error, stdout) { + let flags = []; + if (!error) { + let parts = stdout.toString().split('\tFlags:'); + const lines = parts.length > 1 ? parts[1].split('\tVersion:')[0].split['\n'] : []; + lines.forEach(function (line) { + let flag = (line.indexOf('(') ? line .split('(')[0].toLowerCase() : '').trim().replace(/\t/g, ''); + if (flag) { + flags.push(flag); + } + }); + } + result = flags.join(' ').trim(); + if (callback) { callback(result); } + resolve(result); + }); + } if (_darwin) { exec('sysctl machdep.cpu.features', function (error, stdout) { if (!error) { @@ -545,7 +649,12 @@ function cpuCache(callback) { return new Promise((resolve) => { process.nextTick(() => { - let result = {}; + let result = { + l1d: -1, + l1i: -1, + l2: -1, + l3: -1, + }; if (_linux) { exec('lscpu', function (error, stdout) { if (!error) { @@ -570,6 +679,35 @@ function cpuCache(callback) { resolve(result); }); } + if (_freebsd || _openbsd) { + exec('export LC_ALL=C; dmidecode -t 7 ; unset LC_ALL', function (error, stdout) { + let cache = []; + if (!error) { + const data = stdout.toString(); + cache = data.split('Cache Information'); + cache.shift(); + } + for (let i = 0; i < cache.length; i++) { + const lines = cache[i].split('\n'); + let cacheType = util.getValue(lines,'Socket Designation').toLowerCase().replace(' ', '-').split('-'); + cacheType = cacheType.length ? cacheType[0] : ''; + const sizeParts = util.getValue(lines,'Installed Size').split(' '); + let size = parseInt(sizeParts[0], 10); + const unit = sizeParts.length > 1 ? sizeParts[1] : 'kb'; + size = size * (unit === 'kb' ? 1024 : (unit === 'mb' ? 1024 * 1024 : (unit === 'gb' ? 1024 * 1024 * 1024 : 1))); + if (cacheType) { + if (cacheType === 'l1') { + result.cache[cacheType + 'd'] = size / 2; + result.cache[cacheType + 'i'] = size / 2; + } else { + result.cache[cacheType] = size; + } + } + } + if (callback) { callback(result); } + resolve(result); + }); + } if (_darwin) { exec('sysctl hw.l1icachesize hw.l1dcachesize hw.l2cachesize hw.l3cachesize', function (error, stdout) { if (!error) { diff --git a/lib/docker.js b/lib/docker.js index 6f84214..253a4b0 100644 --- a/lib/docker.js +++ b/lib/docker.js @@ -88,6 +88,7 @@ function dockerContainers(all, callback) { }); } } catch (err) { + util.noop(); } // } @@ -244,6 +245,7 @@ function dockerContainerStats(containerID, callback) { result.networks = (stats.networks ? stats.networks : {}); } } catch (err) { + util.noop(); } // } if (callback) { callback(result); } @@ -319,6 +321,7 @@ function dockerContainerProcesses(containerID, callback) { }); } } catch (err) { + util.noop(); } if (callback) { callback(result); } resolve(result); diff --git a/lib/filesystem.js b/lib/filesystem.js index 683fd6d..6ec0f00 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -12,16 +12,18 @@ // 8. File System // ---------------------------------------------------------------------------------- -const os = require('os'); const exec = require('child_process').exec; const execSync = require('child_process').execSync; const util = require('./util'); -let _platform = os.type(); +let _platform = process.platform; + +const _linux = (_platform === 'linux'); +const _darwin = (_platform === 'darwin'); +const _windows = (_platform === 'win32'); +const _freebsd = (_platform === 'freebsd'); +const _openbsd = (_platform === 'openbsd'); -const _linux = (_platform === 'Linux'); -const _darwin = (_platform === 'Darwin'); -const _windows = (_platform === 'Windows_NT'); const NOT_SUPPORTED = 'not supported'; let _fs_speed = {}; @@ -35,8 +37,11 @@ function fsSize(callback) { return new Promise((resolve) => { process.nextTick(() => { let data = []; - if (_linux || _darwin) { - let cmd = (_darwin ? 'df -lkP | grep ^/' : 'df -lkPT | grep ^/'); + if (_linux || _freebsd || _openbsd || _darwin) { + let cmd = ''; + if (_darwin) cmd = 'df -lkP | grep ^/'; + if (_linux) cmd = 'df -lkPT | grep ^/'; + if (_freebsd || _openbsd) cmd = 'df -lkPT'; exec(cmd, function (error, stdout) { if (!error) { let lines = stdout.toString().split('\n'); @@ -44,14 +49,16 @@ function fsSize(callback) { lines.forEach(function (line) { if (line !== '') { line = line.replace(/ +/g, ' ').split(' '); - data.push({ - 'fs': line[0], - 'type': (_linux ? line[1] : 'HFS'), - 'size': parseInt((_linux ? line[2] : line[1])) * 1024, - 'used': parseInt((_linux ? line[3] : line[2])) * 1024, - 'use': parseFloat((100.0 * (_linux ? line[3] : line[2]) / (_linux ? line[2] : line[1])).toFixed(2)), - 'mount': line[line.length - 1] - }); + if (line && (line[0].startsWith('/')) || (line[6] && line[6] === '/')) { + data.push({ + 'fs': line[0], + 'type': ((_linux || _freebsd || _openbsd) ? line[1] : 'HFS'), + 'size': parseInt(((_linux || _freebsd || _openbsd) ? line[2] : line[1])) * 1024, + 'used': parseInt(((_linux || _freebsd || _openbsd) ? line[3] : line[2])) * 1024, + 'use': parseFloat((100.0 * ((_linux || _freebsd || _openbsd) ? line[3] : line[2]) / ((_linux || _freebsd || _openbsd) ? line[2] : line[1])).toFixed(2)), + 'mount': line[line.length - 1] + }); + } } }); } @@ -360,7 +367,7 @@ function fsStats(callback) { }); let output = fs_filter.join('|'); - exec("cat /proc/diskstats | egrep '" + output + "'", function (error, stdout) { + exec('cat /proc/diskstats | egrep "' + output + '"', function (error, stdout) { if (!error) { let lines = stdout.toString().split('\n'); lines.forEach(function (line) { @@ -492,7 +499,7 @@ function disksIO(callback) { let wIO = 0; if ((_disk_io && !_disk_io.ms) || (_disk_io && _disk_io.ms && Date.now() - _disk_io.ms >= 500)) { - if (_linux) { + if (_linux || _freebsd || _openbsd) { // prints Block layer statistics for all mounted volumes // var cmd = "for mount in `lsblk | grep / | sed -r 's/│ └─//' | cut -d ' ' -f 1`; do cat /sys/block/$mount/stat | sed -r 's/ +/;/g' | sed -r 's/^;//'; done"; // var cmd = "for mount in `lsblk | grep / | sed 's/[│└─├]//g' | awk '{$1=$1};1' | cut -d ' ' -f 1 | sort -u`; do cat /sys/block/$mount/stat | sed -r 's/ +/;/g' | sed -r 's/^;//'; done"; @@ -583,6 +590,7 @@ function diskLayout(callback) { try { mediumType = execSync('cat /sys/block/' + logical + '/queue/rotational').toString().split('\n')[0]; } catch (e) { + util.noop(); } const sizeString = util.getValue(lines, 'size', ':', true).trim(); @@ -613,6 +621,10 @@ function diskLayout(callback) { resolve(result); }); } + if (_freebsd || _openbsd) { + if (callback) { callback(result); } + resolve(result); + } if (_darwin) { exec('system_profiler SPSerialATADataType SPNVMeDataType', function (error, stdout) { diff --git a/lib/graphics.js b/lib/graphics.js index 6f283cc..9940e2e 100644 --- a/lib/graphics.js +++ b/lib/graphics.js @@ -12,15 +12,17 @@ // 7. Graphics (controller, display) // ---------------------------------------------------------------------------------- -const os = require('os'); const exec = require('child_process').exec; const util = require('./util'); -let _platform = os.type(); +let _platform = process.platform; + +const _linux = (_platform === 'linux'); +const _darwin = (_platform === 'darwin'); +const _windows = (_platform === 'win32'); +const _freebsd = (_platform === 'freebsd'); +const _openbsd = (_platform === 'openbsd'); -const _linux = (_platform === 'Linux'); -const _darwin = (_platform === 'Darwin'); -const _windows = (_platform === 'Windows_NT'); let _resolutionx = 0; let _resolutiony = 0; let _pixeldepth = 0; @@ -321,6 +323,10 @@ function graphics(callback) { }); }); } + if (_freebsd || _openbsd) { + if (callback) { callback(result); } + resolve(result); + } if (_windows) { // https://blogs.technet.microsoft.com/heyscriptingguy/2013/10/03/use-powershell-to-discover-multi-monitor-information/ exec(util.getWmic() + ' path win32_VideoController get AdapterCompatibility, AdapterDACType, name, PNPDeviceID, CurrentVerticalResolution, CurrentHorizontalResolution, CurrentNumberOfColors, AdapterRAM, CurrentBitsPerPixel, CurrentRefreshRate, MinRefreshRate, MaxRefreshRate, VideoMemoryType /value', function (error, stdout) { diff --git a/lib/index.js b/lib/index.js index 815f54e..e782c39 100644 --- a/lib/index.js +++ b/lib/index.js @@ -83,8 +83,6 @@ // Dependencies // ---------------------------------------------------------------------------------- -const os = require('os'); - const lib_version = require('../package.json').version; const util = require('./util'); const system = require('./system'); @@ -100,8 +98,10 @@ const users = require('./users'); const internet = require('./internet'); const docker = require('./docker'); -let _platform = os.type(); -let _windows = (_platform === 'Windows_NT'); +let _platform = process.platform; +const _windows = (_platform === 'win32'); +const _freebsd = (_platform === 'freebsd'); +const _openbsd = (_platform === 'openbsd'); // ---------------------------------------------------------------------------------- // 1. General @@ -185,7 +185,9 @@ function getDynamicData(srv, iface, callback) { // use closure to track ƒ completion let functionProcessed = (function () { - let totalFunctions = (_windows ? 10 : 14); + let totalFunctions = 14; + if (_windows) totalFunctions = 10; + if (_freebsd || _openbsd) totalFunctions = 10; return function () { if (--totalFunctions === 0) { @@ -246,15 +248,19 @@ function getDynamicData(srv, iface, callback) { functionProcessed(); }); - network.networkStats(iface).then(res => { - data.networkStats = res; - functionProcessed(); - }); + if (!_openbsd && !_freebsd) { + network.networkStats(iface).then(res => { + data.networkStats = res; + functionProcessed(); + }); + } - network.networkConnections().then(res => { - data.networkConnections = res; - functionProcessed(); - }); + if (!_openbsd && !_freebsd) { + network.networkConnections().then(res => { + data.networkConnections = res; + functionProcessed(); + }); + } memory.mem().then(res => { data.mem = res; @@ -278,14 +284,14 @@ function getDynamicData(srv, iface, callback) { functionProcessed(); }); - if (!_windows) { + if (!_windows && !_openbsd && !_freebsd) { filesystem.fsStats().then(res => { data.fsStats = res; functionProcessed(); }); } - if (!_windows) { + if (!_windows && !_openbsd && !_freebsd) { filesystem.disksIO().then(res => { data.disksIO = res; functionProcessed(); @@ -313,6 +319,17 @@ function getAllData(srv, iface, callback) { process.nextTick(() => { let data = {}; + if (iface && util.isFunction(iface) && !callback) { + callback = iface; + iface = ''; + } + + if (srv && util.isFunction(srv) && !iface && !callback) { + callback = srv; + srv = ''; + iface = ''; + } + getStaticData().then(res => { data = res; getDynamicData(srv, iface).then(res => { diff --git a/lib/internet.js b/lib/internet.js index 34aaa3a..eb86f09 100644 --- a/lib/internet.js +++ b/lib/internet.js @@ -12,15 +12,16 @@ // 12. Internet // ---------------------------------------------------------------------------------- -const os = require('os'); const exec = require('child_process').exec; const util = require('./util'); -let _platform = os.type(); +let _platform = process.platform; -const _linux = (_platform === 'Linux'); -const _darwin = (_platform === 'Darwin'); -const _windows = (_platform === 'Windows_NT'); +const _linux = (_platform === 'linux'); +const _darwin = (_platform === 'darwin'); +const _windows = (_platform === 'win32'); +const _freebsd = (_platform === 'freebsd'); +const _openbsd = (_platform === 'openbsd'); // -------------------------- // check if external site is available @@ -39,7 +40,7 @@ function inetChecksite(url, callback) { if (url) { url = url.toLowerCase(); let t = Date.now(); - if (_linux || _darwin) { + if (_linux || _freebsd || _openbsd || _darwin) { let args = ' -I --connect-timeout 5 -m 5 ' + url + ' 2>/dev/null | head -n 1 | cut -d " " -f2'; let cmd = 'curl'; exec(cmd + args, function (error, stdout) { @@ -73,7 +74,7 @@ function inetChecksite(url, callback) { resolve(result); }); } - }).on('error', err => { + }).on('error', () => { if (callback) { callback(result); } resolve(result); }); @@ -108,10 +109,13 @@ function inetLatency(host, callback) { return new Promise((resolve) => { process.nextTick(() => { let cmd; - if (_linux || _darwin) { + if (_linux || _freebsd || _openbsd || _darwin) { if (_linux) { cmd = 'ping -c 2 -w 3 ' + host + ' | grep rtt'; } + if (_freebsd || _openbsd) { + cmd = 'ping -c 2 -t 3 ' + host + ' | grep round-trip'; + } if (_darwin) { cmd = 'ping -c 2 -t 3 ' + host + ' | grep avg'; } diff --git a/lib/memory.js b/lib/memory.js index 91cdf6f..37548a7 100644 --- a/lib/memory.js +++ b/lib/memory.js @@ -16,11 +16,14 @@ const os = require('os'); const exec = require('child_process').exec; const util = require('./util'); -let _platform = os.type(); +let _platform = process.platform; + +const _linux = (_platform === 'linux'); +const _darwin = (_platform === 'darwin'); +const _windows = (_platform === 'win32'); +const _freebsd = (_platform === 'freebsd'); +const _openbsd = (_platform === 'openbsd'); -const _linux = (_platform === 'Linux'); -const _darwin = (_platform === 'Darwin'); -const _windows = (_platform === 'Windows_NT'); const OSX_RAM_manufacturers = { '0x014F': 'Transcend Information', @@ -134,8 +137,32 @@ function mem(callback) { resolve(result); }); } + if (_freebsd || _openbsd) { + exec('/sbin/sysctl -a | grep -E "hw.realmem|hw.physmem|vm.stats.vm.v_page_count|vm.stats.vm.v_wire_count|vm.stats.vm.v_active_count|vm.stats.vm.v_inactive_count|vm.stats.vm.v_cache_count|vm.stats.vm.v_free_count|vm.stats.vm.v_page_size"', function (error, stdout) { + if (!error) { + let lines = stdout.toString().split('\n'); + const pagesize = parseInt(util.getValue(lines, 'vm.stats.vm.v_page_size'), 10); + const inactive = parseInt(util.getValue(lines, 'vm.stats.vm.v_inactive_count'), 10) * pagesize; + const cache = parseInt(util.getValue(lines, 'vm.stats.vm.v_cache_count'), 10) * pagesize; + + result.total = parseInt(util.getValue(lines, 'hw.realmem'), 10); + if (isNaN(result.total)) result.total = parseInt(util.getValue(lines, 'hw.physmem'), 10); + result.free = parseInt(util.getValue(lines, 'vm.stats.vm.v_free_count'), 10) * pagesize; + result.buffcache = inactive + cache; + result.available = result.buffcache + result.free; + result.active = result.total - result.free - result.buffcache; + + result.swaptotal = 0; + result.swapfree = 0; + result.swapused = 0; + + } + if (callback) { callback(result); } + resolve(result); + }); + } if (_darwin) { - exec("vm_stat | grep 'Pages active'", function (error, stdout) { + exec('vm_stat | grep "Pages active"', function (error, stdout) { if (!error) { let lines = stdout.toString().split('\n'); @@ -203,34 +230,34 @@ function memLayout(callback) { let result = []; - if (_linux) { - exec("dmidecode -t memory | grep -iE 'Size:|Type|Speed|Manufacturer|Form Factor|Locator|Memory Device|Serial Number|Voltage|Part Number'", function (error, stdout) { + if (_linux || _freebsd || _openbsd) { + exec('dmidecode -t memory | grep -iE "Size:|Type|Speed|Manufacturer|Form Factor|Locator|Memory Device|Serial Number|Voltage|Part Number"', function (error, stdout) { if (!error) { let devices = stdout.toString().split('Memory Device'); devices.shift(); devices.forEach(function (device) { let lines = device.split('\n'); - if (parseInt(util.getValue(lines, ' Size'), 10) > 0) { + if (parseInt(util.getValue(lines, 'Size'), 10) > 0) { result.push({ - size: parseInt(util.getValue(lines, ' Size'), 10)*1024*1024, - bank: util.getValue(lines, ' Bank Locator'), - type: util.getValue(lines, ' Type:'), - clockSpeed: (util.getValue(lines, ' Configured Clock Speed:') ? parseInt(util.getValue(lines, ' Configured Clock Speed:'), 10) : parseInt(util.getValue(lines, ' Speed:'), 10)), - formFactor: util.getValue(lines, ' Form Factor:'), - manufacturer: util.getValue(lines, ' Manufacturer:'), - partNum: util.getValue(lines, ' Part Number:'), - serialNum: util.getValue(lines, ' Serial Number:'), - voltageConfigured: parseFloat(util.getValue(lines, ' Configured Voltage:') || -1), - voltageMin: parseFloat(util.getValue(lines, ' Minimum Voltage:') || -1), - voltageMax: parseFloat(util.getValue(lines, ' Maximum Voltage:') || -1), + size: parseInt(util.getValue(lines, 'Size'), 10)*1024*1024, + bank: util.getValue(lines, 'Bank Locator'), + type: util.getValue(lines, 'Type:'), + clockSpeed: (util.getValue(lines, 'Configured Clock Speed:') ? parseInt(util.getValue(lines, 'Configured Clock Speed:'), 10) : (util.getValue(lines, 'Speed:') ? parseInt(util.getValue(lines, 'Speed:'), 10) : -1)), + formFactor: util.getValue(lines, 'Form Factor:'), + manufacturer: util.getValue(lines, 'Manufacturer:'), + partNum: util.getValue(lines, 'Part Number:'), + serialNum: util.getValue(lines, 'Serial Number:'), + voltageConfigured: parseFloat(util.getValue(lines, 'Configured Voltage:') || -1), + voltageMin: parseFloat(util.getValue(lines, 'Minimum Voltage:') || -1), + voltageMax: parseFloat(util.getValue(lines, 'Maximum Voltage:') || -1), }); } else { result.push({ size: 0, - bank: util.getValue(lines, ' Bank Locator'), + bank: util.getValue(lines, 'Bank Locator'), type: 'Empty', clockSpeed: 0, - formFactor: util.getValue(lines, ' Form Factor:'), + formFactor: util.getValue(lines, 'Form Factor:'), partNum: '', serialNum: '', voltageConfigured: -1, diff --git a/lib/network.js b/lib/network.js index 9ae305b..b853682 100644 --- a/lib/network.js +++ b/lib/network.js @@ -18,11 +18,13 @@ const execSync = require('child_process').execSync; const fs = require('fs'); const util = require('./util'); -let _platform = os.type(); +let _platform = process.platform; -const _linux = (_platform === 'Linux'); -const _darwin = (_platform === 'Darwin'); -const _windows = (_platform === 'Windows_NT'); +const _linux = (_platform === 'linux'); +const _darwin = (_platform === 'darwin'); +const _windows = (_platform === 'win32'); +const _freebsd = (_platform === 'freebsd'); +const _openbsd = (_platform === 'openbsd'); let _network = {}; let _default_iface; @@ -33,10 +35,16 @@ function getDefaultNetworkInterface() { if (!_default_iface) { let ifacename = ''; let scopeid = 9999; - if (_linux || _darwin) { - let cmd = (_linux ? "route 2>/dev/null | grep default | awk '{print $8}'" : "route get 0.0.0.0 2>/dev/null | grep interface: | awk '{print $2}'"); + if (_linux || _darwin || _freebsd || _openbsd) { + let cmd = ''; + if (_linux) cmd = 'route 2>/dev/null | grep default | awk "{print $8}"'; + if (_darwin) cmd = 'route get 0.0.0.0 2>/dev/null | grep interface: | awk "{print $2}"'; + if (_freebsd || _openbsd) cmd = 'route get 0.0.0.0 | grep interface:'; let result = execSync(cmd); ifacename = result.toString().split('\n')[0]; + if (ifacename.indexOf(':') > -1) { + ifacename = ifacename.split(':')[1].trim(); + } } if (!ifacename) { // fallback - "first" external interface (sorted by scopeid) @@ -65,7 +73,7 @@ function getMacAddresses() { let iface = ''; let mac = ''; let result = {}; - if (_linux) { + if (_linux || _freebsd || _openbsd) { const cmd = 'export LC_ALL=C; /sbin/ifconfig; unset LC_ALL'; let res = execSync(cmd); const lines = res.toString().split('\n'); @@ -265,7 +273,7 @@ function networkStats(iface, callback) { let cmd, lines, stats; if (!_network[iface] || (_network[iface] && !_network[iface].ms) || (_network[iface] && _network[iface].ms && Date.now() - _network[iface].ms >= 500)) { - if (_linux) { + if (_linux || _freebsd || _openbsd) { if (fs.existsSync('/sys/class/net/' + iface)) { cmd = 'cat /sys/class/net/' + iface + '/operstate; ' + @@ -290,7 +298,7 @@ function networkStats(iface, callback) { } } if (_darwin) { - cmd = "ifconfig " + iface + " | grep 'status'"; + cmd = 'ifconfig ' + iface + ' | grep "status"'; exec(cmd, function (error, stdout) { result.operstate = (stdout.toString().split(':')[1] || '').trim(); result.operstate = (result.operstate || '').toLowerCase(); @@ -396,7 +404,7 @@ function networkConnections(callback) { process.nextTick(() => { let result = []; if (_linux) { - let cmd = "netstat -tuna | grep 'ESTABLISHED\\|SYN_SENT\\|SYN_RECV\\|FIN_WAIT1\\|FIN_WAIT2\\|TIME_WAIT\\|CLOSE\\|CLOSE_WAIT\\|LAST_ACK\\|LISTEN\\|CLOSING\\|UNKNOWN\\|VERBUNDEN'"; + let cmd = 'netstat -tuna | grep "ESTABLISHED\\|SYN_SENT\\|SYN_RECV\\|FIN_WAIT1\\|FIN_WAIT2\\|TIME_WAIT\\|CLOSE\\|CLOSE_WAIT\\|LAST_ACK\\|LISTEN\\|CLOSING\\|UNKNOWN\\|VERBUNDEN"'; exec(cmd, function (error, stdout) { if (!error) { let lines = stdout.toString().split('\n'); @@ -438,7 +446,7 @@ function networkConnections(callback) { } resolve(result); } else { - cmd = "ss -tuna | grep 'ESTAB\\|SYN-SENT\\|SYN-RECV\\|FIN-WAIT1\\|FIN-WAIT2\\|TIME-WAIT\\|CLOSE\\|CLOSE-WAIT\\|LAST-ACK\\|LISTEN\\|CLOSING'"; + cmd = 'ss -tuna | grep "ESTAB\\|SYN-SENT\\|SYN-RECV\\|FIN-WAIT1\\|FIN-WAIT2\\|TIME-WAIT\\|CLOSE\\|CLOSE-WAIT\\|LAST-ACK\\|LISTEN\\|CLOSING"'; exec(cmd, function (error, stdout) { if (!error) { @@ -487,7 +495,7 @@ function networkConnections(callback) { }); } if (_darwin) { - let cmd = "netstat -nat | grep 'ESTABLISHED\\|SYN_SENT\\|SYN_RECV\\|FIN_WAIT1\\|FIN_WAIT2\\|TIME_WAIT\\|CLOSE\\|CLOSE_WAIT\\|LAST_ACK\\|LISTEN\\|CLOSING\\|UNKNOWN'"; + let cmd = 'netstat -nat | grep "ESTABLISHED\\|SYN_SENT\\|SYN_RECV\\|FIN_WAIT1\\|FIN_WAIT2\\|TIME_WAIT\\|CLOSE\\|CLOSE_WAIT\\|LAST_ACK\\|LISTEN\\|CLOSING\\|UNKNOWN"'; exec(cmd, function (error, stdout) { if (!error) { diff --git a/lib/osinfo.js b/lib/osinfo.js index ef84739..1631f2c 100644 --- a/lib/osinfo.js +++ b/lib/osinfo.js @@ -16,11 +16,14 @@ const os = require('os'); const exec = require('child_process').exec; const util = require('./util'); -let _platform = os.type(); +let _platform = process.platform; + +const _linux = (_platform === 'linux'); +const _darwin = (_platform === 'darwin'); +const _windows = (_platform === 'win32'); +const _freebsd = (_platform === 'freebsd'); +const _openbsd = (_platform === 'openbsd'); -const _linux = (_platform === 'Linux'); -const _darwin = (_platform === 'Darwin'); -const _windows = (_platform === 'Windows_NT'); const NOT_SUPPORTED = 'not supported'; // -------------------------- @@ -91,6 +94,9 @@ function getLogoFile(distro) { else if (distro.indexOf('openbsd') !== -1) { result = 'openbsd'; } + else if (distro.indexOf('freebsd') !== -1) { + result = 'freebsd'; + } else if (distro.indexOf('opensuse') !== -1) { result = 'opensuse'; } @@ -185,6 +191,22 @@ function osInfo(callback) { resolve(result); }); } + if (_freebsd || _openbsd) { + + exec('sysctl kern.ostype kern.osrelease kern.osrevision', function (error, stdout) { + if (!error) { + let lines = stdout.toString().split('\n'); + result.distro = util.getValue(lines, 'kern.ostype'); + result.logofile = getLogoFile(result.distro); + result.release = util.getValue(lines, 'kern.osrelease').split('-')[0]; + result.codename = ''; + } + if (callback) { + callback(result); + } + resolve(result); + }); + } if (_darwin) { exec('sw_vers', function (error, stdout) { let lines = stdout.toString().split('\n'); diff --git a/lib/processes.js b/lib/processes.js index 5cef6a3..ed535cf 100644 --- a/lib/processes.js +++ b/lib/processes.js @@ -16,11 +16,14 @@ const os = require('os'); const exec = require('child_process').exec; const util = require('./util'); -let _platform = os.type(); +let _platform = process.platform; + +const _linux = (_platform === 'linux'); +const _darwin = (_platform === 'darwin'); +const _windows = (_platform === 'win32'); +const _freebsd = (_platform === 'freebsd'); +const _openbsd = (_platform === 'openbsd'); -const _linux = (_platform === 'Linux'); -const _darwin = (_platform === 'Darwin'); -const _windows = (_platform === 'Windows_NT'); const NOT_SUPPORTED = 'not supported'; let _process_cpu = { @@ -69,32 +72,85 @@ function services(srv, callback) { return new Promise((resolve) => { process.nextTick(() => { - srv = srv.trim().toLowerCase().replace(/,+/g, ' ').replace(/ +/g, ' ').replace(/ +/g, '|'); - let srvs = srv.split('|'); - let data = []; - let dataSrv = []; - - if (_linux || _darwin) { - let comm = (_darwin) ? 'ps -caxm -o pcpu,pmem,comm' : 'ps axo pcpu,pmem,comm'; - if (srv !== '' && srvs.length > 0) { - exec(comm + " | grep -v grep | egrep '" + srv + "'", function (error, stdout) { - if (!error) { - let lines = stdout.toString().replace(/ +/g, ' ').replace(/,+/g, '.').split('\n'); - srvs.forEach(function (srv) { - let ps = lines.filter(function (e) { - return e.indexOf(srv) !== -1; + if (srv) { + srv = srv.trim().toLowerCase().replace(/,+/g, ' ').replace(/ +/g, ' ').replace(/ +/g, '|'); + let srvs = srv.split('|'); + let data = []; + let dataSrv = []; + + if (_linux || _freebsd || _openbsd || _darwin) { + let comm = (_darwin) ? 'ps -caxm -o pcpu,pmem,comm' : 'ps axo pcpu,pmem,comm'; + if (srv !== '' && srvs.length > 0) { + exec(comm + " | grep -v grep | egrep '" + srv + "'", function (error, stdout) { + if (!error) { + let lines = stdout.toString().replace(/ +/g, ' ').replace(/,+/g, '.').split('\n'); + srvs.forEach(function (srv) { + let ps = lines.filter(function (e) { + return e.indexOf(srv) !== -1; + }); + data.push({ + 'name': srv, + 'running': ps.length > 0, + 'pcpu': parseFloat((ps.reduce(function (pv, cv) { + return pv + parseFloat(cv.trim().split(' ')[0]); + }, 0)).toFixed(2)), + 'pmem': parseFloat((ps.reduce(function (pv, cv) { + return pv + parseFloat(cv.trim().split(' ')[1]); + }, 0)).toFixed(2)) + }); }); + if (callback) { callback(data); } + resolve(data); + } else { + srvs.forEach(function (srv) { + data.push({ + 'name': srv, + 'running': false, + 'pcpu': 0, + 'pmem': 0 + }); + }); + if (callback) { callback(data); } + resolve(data); + } + }); + } else { + if (callback) { callback(data); } + resolve(data); + } + } + if (_windows) { + exec(util.getWmic() + ' service get /value', {maxBuffer: 1024 * 1000}, function (error, stdout) { + if (!error) { + let serviceSections = stdout.split(/\n\s*\n/); + for (let i = 0; i < serviceSections.length; i++) { + if (serviceSections[i].trim() !== '') { + let lines = serviceSections[i].trim().split('\r\n'); + let srv = util.getValue(lines, 'Name', '=', true).toLowerCase(); + let started = util.getValue(lines, 'Started', '=', true); + if (srvs.indexOf(srv) >= 0) { + data.push({ + 'name': srv, + 'running': (started === 'TRUE'), + 'pcpu': 0, + 'pmem': 0 + }); + dataSrv.push(srv); + } + } + } + let srvsMissing = srvs.filter(function (e) { + return dataSrv.indexOf(e) === -1; + }); + srvsMissing.forEach(function (srv) { data.push({ 'name': srv, - 'running': ps.length > 0, - 'pcpu': parseFloat((ps.reduce(function (pv, cv) { - return pv + parseFloat(cv.trim().split(' ')[0]); - }, 0)).toFixed(2)), - 'pmem': parseFloat((ps.reduce(function (pv, cv) { - return pv + parseFloat(cv.trim().split(' ')[1]); - }, 0)).toFixed(2)) + 'running': false, + 'pcpu': 0, + 'pmem': 0 }); }); + if (callback) { callback(data); } resolve(data); } else { @@ -110,58 +166,10 @@ function services(srv, callback) { resolve(data); } }); - } else { - if (callback) { callback(data); } - resolve(data); - } - } - if (_windows) { - exec(util.getWmic() + ' service get /value', {maxBuffer: 1024 * 1000}, function (error, stdout) { - if (!error) { - let serviceSections = stdout.split(/\n\s*\n/); - for (let i = 0; i < serviceSections.length; i++) { - if (serviceSections[i].trim() !== '') { - let lines = serviceSections[i].trim().split('\r\n'); - let srv = util.getValue(lines, 'Name', '=', true).toLowerCase(); - let started = util.getValue(lines, 'Started', '=', true); - if (srvs.indexOf(srv) >= 0) { - data.push({ - 'name': srv, - 'running': (started === 'TRUE'), - 'pcpu': 0, - 'pmem': 0 - }); - dataSrv.push(srv); - } - } - } - let srvsMissing = srvs.filter(function (e) { - return dataSrv.indexOf(e) === -1; - }); - srvsMissing.forEach(function (srv) { - data.push({ - 'name': srv, - 'running': false, - 'pcpu': 0, - 'pmem': 0 - }); - }); - - if (callback) { callback(data); } - resolve(data); - } else { - srvs.forEach(function (srv) { - data.push({ - 'name': srv, - 'running': false, - 'pcpu': 0, - 'pmem': 0 - }); - }); - if (callback) { callback(data); } - resolve(data); - } - }); + } + } else { + if (callback) { callback({}); } + resolve({}); } }); }); @@ -407,8 +415,9 @@ function processes(callback) { let cmd = ''; if ((_process_cpu.ms && Date.now() - _process_cpu.ms >= 500) || _process_cpu.ms === 0) { - if (_linux || _darwin) { + if (_linux || _freebsd || _openbsd || _darwin) { if (_linux) cmd = 'ps axo pid:10,pcpu:6,pmem:6,pri:5,vsz:10,rss:10,ni:5,start:20,state:20,tty:20,user:20,command'; + if (_freebsd || _openbsd) cmd = 'ps axo pid,pcpu,pmem,pri,vsz,rss,ni,start,state,tty,user,command'; if (_darwin) cmd = 'ps acxo pid,pcpu,pmem,pri,vsz,rss,nice,start,state,tty,user,command -r'; exec(cmd, function (error, stdout) { if (!error) { @@ -426,7 +435,7 @@ function processes(callback) { if (_linux) { // calc process_cpu - ps is not accurate in linux! - cmd = "cat /proc/stat | grep 'cpu '"; + cmd = 'cat /proc/stat | grep "cpu "'; for (let i = 0; i < result.list.length; i++) { cmd += (';cat /proc/' + result.list[i].pid + '/stat'); } diff --git a/lib/system.js b/lib/system.js index 4f684a4..ac8145b 100644 --- a/lib/system.js +++ b/lib/system.js @@ -22,7 +22,7 @@ const _linux = (_platform === 'linux'); const _darwin = (_platform === 'darwin'); const _windows = (_platform === 'win32'); const _freebsd = (_platform === 'freebsd'); -const _sunos = (_platform === 'sunos'); +const _openbsd = (_platform === 'openbsd'); function system(callback) { @@ -38,7 +38,7 @@ function system(callback) { sku: '-', }; - if (_linux) { + if (_linux || _freebsd || _openbsd) { exec('dmidecode -t system', function (error, stdout) { if (!error) { let lines = stdout.toString().split('\n'); @@ -194,7 +194,7 @@ function bios(callback) { revision: '', }; let cmd = ''; - if (_linux) { + if (_linux || _freebsd || _openbsd) { if (process.arch === 'arm') { cmd = 'cat /proc/cpuinfo | grep Serial'; @@ -207,7 +207,7 @@ function bios(callback) { result.vendor = util.getValue(lines, 'Vendor'); result.version = util.getValue(lines, 'Version'); const datetime = util.getValue(lines, 'Release Date'); - result.releaseDate = datetime.date; + result.releaseDate = util.parseDateTime(datetime).date; result.revision = util.getValue(lines, 'BIOS Revision'); } @@ -268,7 +268,7 @@ function baseboard(callback) { assetTag: '-', }; let cmd = ''; - if (_linux) { + if (_linux || _freebsd || _openbsd) { if (process.arch === 'arm') { cmd = 'cat /proc/cpuinfo | grep Serial'; // 'BCM2709', 'BCM2835', 'BCM2708' --> diff --git a/lib/users.js b/lib/users.js index 981aaa9..d622da9 100644 --- a/lib/users.js +++ b/lib/users.js @@ -12,15 +12,16 @@ // 11. Users/Sessions // ---------------------------------------------------------------------------------- -const os = require('os'); const exec = require('child_process').exec; const util = require('./util'); -let _platform = os.type(); +let _platform = process.platform; -const _linux = (_platform === 'Linux'); -const _darwin = (_platform === 'Darwin'); -const _windows = (_platform === 'Windows_NT'); +const _linux = (_platform === 'linux'); +const _darwin = (_platform === 'darwin'); +const _windows = (_platform === 'win32'); +const _freebsd = (_platform === 'freebsd'); +const _openbsd = (_platform === 'openbsd'); // -------------------------- // array of users online = sessions @@ -204,6 +205,17 @@ function users(callback) { } }); } + if (_freebsd || _openbsd) { + exec('who; echo "---"; w -ih', function (error, stdout) { + if (!error) { + // lines / split + let lines = stdout.toString().split('\n'); + result = parseUsersDarwin(lines); + } + if (callback) { callback(result); } + resolve(result); + }); + } if (_darwin) { exec('who; echo "---"; w -ih', function (error, stdout) { diff --git a/lib/util.js b/lib/util.js index 257bda1..aad4f9c 100644 --- a/lib/util.js +++ b/lib/util.js @@ -65,11 +65,11 @@ function getValue(lines, property, separator, trimmed) { property = property.toLowerCase(); trimmed = trimmed || false; for (let i = 0; i < lines.length; i++) { - let line = lines[i].toLowerCase(); + let line = lines[i].toLowerCase().replace(/\t/g, ''); if (trimmed) { line = line.trim(); } - if (line.toLowerCase().startsWith(property)) { + if (line.startsWith(property)) { const parts = lines[i].split(separator); if (parts.length >= 2) { parts.shift(); @@ -128,11 +128,13 @@ function getWmic() { if (os.type() === 'Windows_NT' && !wmic) { if (fs.existsSync(process.env.WINDIR + '\\system32\\wbem\\wmic.exe')) { wmic = process.env.WINDIR + '\\system32\\wbem\\wmic.exe'; - } else wmic = 'wmic' + } else wmic = 'wmic'; } return wmic; } +function noop(){} + exports.isFunction = isFunction; exports.unique = unique; exports.sortByKey= sortByKey; @@ -141,3 +143,4 @@ exports.getValue = getValue; exports.decodeEscapeSequence = decodeEscapeSequence; exports.parseDateTime = parseDateTime; exports.getWmic = getWmic; +exports.noop = noop; diff --git a/package.json b/package.json index 3b3f9e6..1dcd08e 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "linux", "osx", "windows", + "freebsd", "cpu", "cpuload", "memory", @@ -48,7 +49,9 @@ "os": [ "darwin", "linux", - "win32" + "win32", + "freebsd", + "openbsd" ], "engines": { "node": ">=4.0.0"