131 lines
3.9 KiB
JavaScript
131 lines
3.9 KiB
JavaScript
|
'use strict'
|
||
|
|
||
|
var os = require('os')
|
||
|
var bin = require('./bin')
|
||
|
var history = require('./history')
|
||
|
|
||
|
function parseDate (datestr) {
|
||
|
var year = datestr.substring(0, 4)
|
||
|
var month = datestr.substring(4, 6)
|
||
|
var day = datestr.substring(6, 8)
|
||
|
var hour = datestr.substring(8, 10)
|
||
|
var minutes = datestr.substring(10, 12)
|
||
|
var seconds = datestr.substring(12, 14)
|
||
|
var useconds = datestr.substring(15, 21)
|
||
|
var sign = datestr.substring(21, 22)
|
||
|
var tmz = parseInt(datestr.substring(22, 25), 10)
|
||
|
var tmzh = Math.floor(tmz / 60)
|
||
|
var tmzm = tmz % 60
|
||
|
|
||
|
return new Date(
|
||
|
year + '-' + month + '-' + day + 'T' + hour +
|
||
|
':' + minutes + ':' + seconds +
|
||
|
'.' + useconds +
|
||
|
sign + (tmzh > 9 ? tmzh : '0' + tmzh) + '' + (tmzm > 9 ? tmzm : '0' + tmzm)
|
||
|
)
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get pid informations through wmic command.
|
||
|
* @param {Number[]} pids
|
||
|
* @param {Object} options
|
||
|
* @param {Function} done(err, stat)
|
||
|
*/
|
||
|
function wmic (pids, options, done) {
|
||
|
var whereClause = 'ProcessId=' + pids[0]
|
||
|
for (var i = 1; i < pids.length; i++) {
|
||
|
whereClause += ' or ' + 'ProcessId=' + pids[i]
|
||
|
}
|
||
|
|
||
|
var args = [
|
||
|
'PROCESS',
|
||
|
'where',
|
||
|
'"' + whereClause + '"',
|
||
|
'get',
|
||
|
'CreationDate,KernelModeTime,ParentProcessId,ProcessId,UserModeTime,WorkingSetSize'
|
||
|
]
|
||
|
|
||
|
bin('wmic', args, {windowsHide: true, windowsVerbatimArguments: true}, function (err, stdout, code) {
|
||
|
if (err) {
|
||
|
if (err.message.indexOf('No Instance(s) Available.') !== -1) {
|
||
|
return done(new Error('No maching pid found'))
|
||
|
}
|
||
|
return done(err)
|
||
|
}
|
||
|
if (code !== 0) {
|
||
|
return done(new Error('pidusage wmic command exited with code ' + code))
|
||
|
}
|
||
|
var date = Date.now()
|
||
|
|
||
|
// Note: On Windows the returned value includes fractions of a second.
|
||
|
// Use Math.floor() to get whole seconds.
|
||
|
var uptime = Math.floor(os.uptime())
|
||
|
|
||
|
// Example of stdout on Windows 10
|
||
|
// CreationDate: is in the format yyyymmddHHMMSS.mmmmmmsUUU
|
||
|
// KernelModeTime: is in units of 100 ns
|
||
|
// UserModeTime: is in units of 100 ns
|
||
|
// WorkingSetSize: is in bytes
|
||
|
//
|
||
|
// Refs: https://superuser.com/a/937401/470946
|
||
|
// Refs: https://msdn.microsoft.com/en-us/library/aa394372(v=vs.85).aspx
|
||
|
// NB: The columns are returned in lexicographical order
|
||
|
//
|
||
|
// CreationDate KernelModeTime ParentProcessId ProcessId UserModeTime WorkingSetSize
|
||
|
// 20150329221650.080654+060 153750000 0 777 8556250000 110821376
|
||
|
|
||
|
stdout = stdout.split(os.EOL)
|
||
|
|
||
|
var again = false
|
||
|
var statistics = {}
|
||
|
for (var i = 1; i < stdout.length; i++) {
|
||
|
var line = stdout[i].trim().split(/\s+/)
|
||
|
|
||
|
if (!line || line.length !== 6) {
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
var creation = parseDate(line[0])
|
||
|
var ppid = parseInt(line[2], 10)
|
||
|
var pid = parseInt(line[3], 10)
|
||
|
var kerneltime = Math.round(parseInt(line[1], 10) / 10000)
|
||
|
var usertime = Math.round(parseInt(line[4], 10) / 10000)
|
||
|
var memory = parseInt(line[5], 10)
|
||
|
|
||
|
var hst = history.get(pid, options.maxage)
|
||
|
if (hst === undefined) {
|
||
|
again = true
|
||
|
hst = {ctime: kerneltime + usertime, uptime: uptime}
|
||
|
}
|
||
|
|
||
|
// process usage since last call
|
||
|
var total = (kerneltime + usertime - hst.ctime) / 1000
|
||
|
// time elapsed between calls in seconds
|
||
|
var seconds = uptime - hst.uptime
|
||
|
var cpu = seconds > 0 ? (total / seconds) * 100 : 0
|
||
|
|
||
|
history.set(pid, {ctime: usertime + kerneltime, uptime: uptime}, options.maxage)
|
||
|
|
||
|
statistics[pid] = {
|
||
|
cpu: cpu,
|
||
|
memory: memory,
|
||
|
ppid: ppid,
|
||
|
pid: pid,
|
||
|
ctime: usertime + kerneltime,
|
||
|
elapsed: date - creation.getTime(),
|
||
|
timestamp: date
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (again) {
|
||
|
return wmic(pids, options, function (err, stats) {
|
||
|
if (err) return done(err)
|
||
|
done(null, Object.assign(statistics, stats))
|
||
|
})
|
||
|
}
|
||
|
done(null, statistics)
|
||
|
})
|
||
|
}
|
||
|
|
||
|
module.exports = wmic
|