Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Modifying for use with destruct #5

Open
wants to merge 1 commit into from

2 participants

Dave Eddy Daniel Shaw
Dave Eddy
Collaborator

I leave this up to you if you want to merge it or not.

I modified this to use the node destruct module I wrote to make unpacking values easier and cleaner.

Thought?

(tag @papertigers)

Daniel Shaw dshaw commented on the diff
lib/usage.js
((29 lines not shown))
22 18 if (typeof pid === 'function') {
23 19 callback = pid;
24 20 pid = 'self';
25 21 }
26   -
27   - fs.readFile('/proc/'+pid+'/usage', function (err, buf) {
  22 + parseProc('psinfo', 'iia8a8a8a8a8a8a8a8a8a8a8a8a8a8a48LLLLLLLLLLLLa40', keys, timespec_keys, pid, function(err, res) {
1
Daniel Shaw Owner
dshaw added a note

'iia8a8a8a8a8a8a8a8a8a8a8a8a8a8a48LLLLLLLLLLLLa40' - that's a crazy string. I love where you're going with this though. Seems much easier to manage.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Dave Eddy
Collaborator

oh yeah, it's definitely a crazy string. I modeled the unpack function after the one in perl. if you search for one of those crazy strings you'll see 2 results. the node destruct module, and brendan gregg's prustat script.

https://duckduckgo.com/?q=iiiiiiiiiiIiiiiSSa8a8a8Z16Z80iiIIaa3iiiiii

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 1 unique commit by 1 author.

Jul 18, 2012
Dave Eddy bahamas10 Modifying for use with destruct 30fe47c
This page is out of date. Refresh to see the latest.
10 lib/cred.js
... ... @@ -0,0 +1,10 @@
  1 +/**
  2 + * Parse /proc/<pid>/cred
  3 + */
  4 +var parseProc = require('./lib').parseProc,
  5 + keys = [ 'euid', 'ruid', 'suid', 'egid', 'rgid', 'sgid', 'ngroups',
  6 + 'groups' ];
  7 +
  8 +module.exports = function(pid, callback) {
  9 + parseProc('cred', 'iiiiiiii', keys, [], pid, callback);
  10 +};
58 lib/lib.js
... ... @@ -0,0 +1,58 @@
  1 +/*!
  2 + * parseProc
  3 + * MIT Licensed
  4 + */
  5 +
  6 +var fs = require('fs'),
  7 + destruct = require('destruct');
  8 +
  9 +// Read time spec of a given buffer
  10 +function readTimespec(buf, offset) {
  11 + return buf.readInt32LE(offset) + (buf.readInt32LE(offset + 4) / 1000000000);
  12 +}
  13 +
  14 +/**
  15 + * Generic proc parsing function
  16 + *
  17 + * @param file file in proc to parse. ex 'usage', 'psinfo', etc.
  18 + * @param fmt format for binary unpacking of the file
  19 + * @param keys keys to map to the resultant binary unpacking operation
  20 + * @parama timespec_keys keys to run the readTimespec function on
  21 + * @param pid pid of the process, defaults to 'self'
  22 + * @param callback callback with the results (err, res)
  23 + */
  24 +module.exports.parseProc = function(file, fmt, keys, timespec_keys, pid, callback) {
  25 + if (typeof pid === 'function') {
  26 + callback = pid;
  27 + pid = 'self';
  28 + }
  29 +
  30 + fs.readFile('/proc/'+pid+'/'+file, function (err, buf) {
  31 + if (err) return callback(err);
  32 +
  33 + // Unpack the values
  34 + var unpacked = destruct.unpack(fmt, buf);
  35 +
  36 + // Merge the keys array with the unpacked values to make an associative array
  37 + var ret = {};
  38 + for (var i = 0; i < keys.length; i++) {
  39 + ret[keys[i]] = unpacked[i];
  40 + }
  41 +
  42 + // Delete padding
  43 + delete ret['pad'];
  44 +
  45 + // Convert time specs
  46 + timespec_keys.forEach(function(key) {
  47 + ret[key] = readTimespec(ret[key], 0);
  48 + });
  49 +
  50 + // Check for buffers that need to be toString'd
  51 + keys.forEach(function(key) {
  52 + ret[key] = (typeof ret[key] === 'object') ? ret[key].toString() : ret[key];
  53 + });
  54 +
  55 + // Callback
  56 + callback(null, ret);
  57 + });
  58 +};
65 lib/psinfo.js
@@ -2,66 +2,15 @@
2 2 * psinfo
3 3 * MIT Licensed
4 4 * reference: http://src.illumos.org/source/xref/illumos-gate/usr/src/uts/common/sys/procfs.h#275
5   - *
6 5 */
7 6
8   -var fs = require('fs');
9   -
10   -function readTimespec(buf, offset) {
11   - return buf.readInt32LE(offset) + (buf.readInt32LE(offset + 4) / 1000000000);
12   -}
  7 +var parseProc = require('./lib').parseProc,
  8 + timespec_keys = [ 'ctime', 'time', 'start' ],
  9 + keys = ['flag', 'nlwp', 'pid', 'ppid', 'pgid', 'sid', 'uid', 'euid', 'gid',
  10 + 'egid', 'addr', 'size', 'rssize', 'pad', 'ttydev', 'pctcpu', 'pctmem', 'start',
  11 + 'time', 'ctime', 'fname', 'psargs', 'wstat', 'argc', 'argv', 'envp',
  12 + 'dmodel', 'pad', 'taskid', 'projid', 'nzomb', 'poolid', 'zoneid', 'contract', 'filler'];
13 13
14 14 module.exports = function(pid, callback) {
15   - if (typeof pid === 'function') {
16   - callback = pid;
17   - pid = 'self';
18   - }
19   -
20   - fs.readFile('/proc/'+pid+'/psinfo', function (err, buf) {
21   - if (err) return callback(err);
22   -
23   - var data = {}, offset = 0;
24   - data.flag = buf.readInt32LE(offset); offset+=4; /* process flags (DEPRECATED; do not use) */
25   - data.nlwp = buf.readInt32LE(offset); offset+=4; /* number of active lwps in the process */
26   - data.pid = buf.readInt32LE(offset); offset+=4; /* unique process id */
27   - data.ppid = buf.readInt32LE(offset); offset+=4; /* process id of parent */
28   - data.pgid = buf.readInt32LE(offset); offset+=4; /* pid of process group leader */
29   - data.sid = buf.readInt32LE(offset); offset+=4; /* session id */
30   - data.uid = buf.readInt32LE(offset); offset+=4; /* real user id */
31   - data.euid = buf.readInt32LE(offset); offset+=4; /* effective user id */
32   - data.gid = buf.readInt32LE(offset); offset+=4; /* real group id */
33   - data.egid = buf.readInt32LE(offset); offset+=4; /* effective group id */
34   - data.addr = buf.readUInt32LE(offset); offset+=4; /* address of process */
35   - data.size = buf.readInt32LE(offset); offset+=4; /* size of process image in Kbytes */
36   - data.rssize = buf.readInt32LE(offset); offset+=4; /* resident set size in Kbytes */
37   - offset += 4; /* pad1 */
38   - data.ttydev = buf.readInt32LE(offset); offset+=4; /* controlling tty device (or PRNODEV) */
39   - /* The following percent numbers are 16-bit binary */
40   - /* fractions [0 .. 1] with the binary point to the */
41   - /* right of the high-order bit (1.0 == 0x8000) */
42   - data.pctcpu = buf.readUInt16LE(offset); offset+=2; /* % of recent cpu time used by all lwps */
43   - data.pctmem = buf.readUInt16LE(offset); offset+=2; /* % of system memory used by process */
44   - data.start = readTimespec(buf, offset); offset+=8; /* process start time, from the epoch */
45   - data.time = readTimespec(buf, offset); offset+=8; /* usr+sys cpu time for this process */
46   - data.ctime = readTimespec(buf, offset); offset+=8; /* usr+sys cpu time for reaped children */
47   - data.fname = buf.toString('ascii', offset, offset+=16) /* name of execed file */
48   - .split('\u0000')[0];
49   - data.psargs = buf.toString('ascii', offset, offset+=80) /* initial characters of arg list */
50   - .split('\u0000')[0];
51   - data.wstat = buf.readInt32LE(offset); offset+=4; /* if zombie, the wait() status */
52   - data.argc = buf.readInt32LE(offset); offset+=4; /* initial argument count */
53   - data.argv = buf.readUInt32LE(offset); offset+=4; /* address of initial argument vector */
54   - data.envp = buf.readUInt32LE(offset); offset+=4; /* address of initial environment vector */
55   - data.dmodel = buf.toString('ascii', offset, offset+=1); /* data model of the process */
56   - offset += 3; /* pad2 */
57   - data.taskid = buf.readInt32LE(offset); offset+=4; /* task id */
58   - data.projid = buf.readInt32LE(offset); offset+=4; /* project id */
59   - data.nzomb = buf.readInt32LE(offset); offset+=4; /* number of zombie lwps in the process */
60   - data.poolid = buf.readInt32LE(offset); offset+=4; /* pool id */
61   - data.zoneid = buf.readInt32LE(offset); offset+=4; /* zone id */
62   - data.contract = buf.readInt32LE(offset); offset+=4; /* process contract */
63   - offset += 1; /* filler */
64   -
65   - callback(null, data);
66   - });
  15 + parseProc('psinfo', 'iiiiiiiiiiIiiiiSSa8a8a8Z16Z80iiIIaa3iiiiii', keys, timespec_keys, pid, callback);
67 16 };
65 lib/usage.js
@@ -4,60 +4,29 @@
4 4 * MIT Licensed
5 5 */
6 6
7   -/**
8   - * Module dependencies.
9   - */
10   -
11   -var fs = require('fs');
12   -
13   -/**
14   - * Exports.
15   - */
  7 +var parseProc = require('./lib').parseProc,
  8 + timespec_keys = [ 'tstamp', 'create', 'term', 'rtime', 'utime', 'stime',
  9 + 'ttime', 'tftime', 'dftime', 'kftime', 'ltime', 'slptime', 'wtime',
  10 + 'stoptime' ],
  11 + keys = ['lwpid', 'count', 'tstamp', 'create', 'term', 'rtime', 'utime',
  12 + 'stime', 'ttime', 'tftime', 'dftime', 'kftime', 'ltime', 'slptime',
  13 + 'wtime', 'stoptime', 'pad', 'minf', 'majf', 'nswap', 'inblk',
  14 + 'outblk', 'msnd', 'mrcv', 'sigs', 'vctx', 'ictx', 'sysc', 'ioch',
  15 + 'pad'];
16 16
17   -function readTimespec(buf, offset) {
18   - return buf.readInt32LE(offset) + (buf.readInt32LE(offset + 4) / 1000000000);
19   -}
20   -
21   -module.exports = function usage (pid, callback) {
  17 +module.exports = function(pid, callback) {
22 18 if (typeof pid === 'function') {
23 19 callback = pid;
24 20 pid = 'self';
25 21 }
26   -
27   - fs.readFile('/proc/'+pid+'/usage', function (err, buf) {
  22 + parseProc('psinfo', 'iia8a8a8a8a8a8a8a8a8a8a8a8a8a8a48LLLLLLLLLLLLa40', keys, timespec_keys, pid, function(err, res) {
28 23 if (err) return callback(err);
29 24
30   - var data = {};
31   - data.lwpid = buf.readUInt32LE(0); // lwp id. 0: process or defunct
32   - data.count = buf.readUInt32LE(4); // number of contributing lwps
33   - data.tstamp = readTimespec(buf, 8); // current time stamp
34   - data.create = readTimespec(buf, 16) / data.count; // process/lwp creation time stamp
35   - data.term = readTimespec(buf, 24) / data.count; // process/lwp termination time stamp
36   - data.rtime = readTimespec(buf, 32) / data.count; // total lwp real (elapsed) time
37   - data.utime = readTimespec(buf, 40); // user level cpu time
38   - data.stime = readTimespec(buf, 48); // system call cpu time
39   - data.ttime = readTimespec(buf, 56); // other system trap cpu time
40   - data.tftime = readTimespec(buf, 64); // text page fault sleep time
41   - data.dftime = readTimespec(buf, 72); // data page fault sleep time
42   - data.kftime = readTimespec(buf, 80); // kernel page fault sleep time
43   - data.ltime = readTimespec(buf, 88); // user lock wait sleep time
44   - data.slptime = readTimespec(buf, 96); // all other sleep time
45   - data.wtime = readTimespec(buf, 104); // wait-cpu (latency) time
46   - data.stoptime = readTimespec(buf, 112); // stopped time
47   - // filler for future expansion
48   - data.minf = buf.readUInt32LE(168); // minor page faults
49   - data.majf = buf.readUInt32LE(172); // major page faults
50   - data.nswap = buf.readUInt32LE(176); // swaps
51   - data.inblk = buf.readUInt32LE(180); // input blocks
52   - data.outblk = buf.readUInt32LE(184); // output blocks
53   - data.msnd = buf.readUInt32LE(188); // messages sent
54   - data.mrcv = buf.readUInt32LE(192); // messages received
55   - data.sigs = buf.readUInt32LE(196); // signals received
56   - data.vctx = buf.readUInt32LE(200); // voluntary context switches
57   - data.ictx = buf.readUInt32LE(204); // involuntary context switches
58   - data.sysc = buf.readUInt32LE(208); // system calls
59   - data.ioch = buf.readUInt32LE(212); // chars read and written
60   - // filler for future expansion
61   - callback(null, data);
  25 + // divide by #lwp
  26 + res.create = res.create / res.count;
  27 + res.term = res.term / res.count;
  28 + res.rtime = res.rtime / res.count;
  29 +
  30 + callback(null, res);
62 31 });
63 32 };
5 package.json
@@ -17,5 +17,8 @@
17 17 "url": "http://github.com/dshaw/proc/issues"
18 18 },
19 19 "main": "./proc",
20   - "bin": { "proc": "./bin/proc-cli.js" }
  20 + "bin": { "proc": "./bin/proc-cli.js" },
  21 + "dependencies": {
  22 + "destruct": "~ 0.0.0"
  23 + }
21 24 }
1  proc.js
@@ -11,3 +11,4 @@
11 11 exports.version = require('./package.json').version;
12 12 exports.usage = require('./lib/usage');
13 13 exports.psinfo = require('./lib/psinfo');
  14 +exports.cred = require('./lib/cred');

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.