Skip to content

Instantly share code, notes, and snippets.

@yurynix
Created February 13, 2020 10:27
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yurynix/6beef61ec4189b37fad0c86bf9fe21b7 to your computer and use it in GitHub Desktop.
Save yurynix/6beef61ec4189b37fad0c86bf9fe21b7 to your computer and use it in GitHub Desktop.
Some useful stats from the proc filesystem
const util = require('util');
const fs = require('fs');
const readfile = util.promisify(fs.readFile);
const readdir = util.promisify(fs.readdir);
const readlink = util.promisify(fs.readlink);
const stat = util.promisify(fs.stat);
async function getProcessRSSMemory(pid) {
try {
const statsFile = `/proc/${pid}/status`;
const statsFileContent = await readfile(statsFile, { encoding: 'utf8' });
const rssRegex = /vmRSS:\s*([^\n]+)/ig
const rssMatch = rssRegex.exec(statsFileContent);
if (rssMatch && rssMatch.length > 1) {
return rssMatch[1];
}
} catch (ex) {
console.log(`Failure getProcessRSSMemory(${pid})`, ex);
}
return null;
}
async function getRunningPids() {
const files = await readdir('/proc');
const pids = files
.map(file => parseInt(file, 10))
.filter(pid => !isNaN(pid) && pid !== process.pid && pid !== 1);
return pids;
}
async function getRunningExecutables() {
const pids = await getRunningPids();
const results = await Promise.all(
pids.map(async pid => {
try {
const exe = await readlink(`/proc/${pid}/exe`);
return {
exe,
pid,
};
} catch (ex) {
// We might get EACCESS here, since we get the list of all process
// and not all of them belongs to us.
return null;
}
}),
);
return results.filter(result => result);
}
async function getProcessFds(pid) {
const fdLinks = await readdir(`/proc/${pid}/fd`);
const fdNames = await Promise.all(fdLinks.map(async fd => {
try {
const fdLink = `/proc/${pid}/fd/${fd}`;
const name = await readlink(fdLink);
const fdStat = await stat(fdLink);
return {
name,
fd,
stat: fdStat
};
} catch (ex) {
return null;
}
}));
return fdNames.filter(fdInfo => !!fdInfo);
}
async function getAllProcessFds() {
const pids = await getRunningPids();
pids.push(process.pid); // Add myself
const processFds = await Promise.all(pids.map(async pid => {
try {
const fds = await getProcessFds(pid);
const name = await readlink(`/proc/${pid}/exe`);
return {
name,
pid,
fds
}
} catch (ex) {
return { pid };
}
}));
return processFds;
}
// based on https://unix.stackexchange.com/questions/62154/when-was-a-process-started
async function getProcessUptimeInSeconds(pid) {
try {
const processStat = await readfile(`/proc/${pid}/stat`, { encoding: 'utf8' });
const systeUptime = await readfile('/proc/uptime', { encoding: 'utf8' });
const processStartTime = parseInt(processStat.split(' ')[21], 10) / 100;
const uptime = parseInt(systeUptime.split(' ')[0], 10);
return uptime - processStartTime;
} catch (ex) {
console.log(`Failure getProcessUptimeInSeconds(${pid})`, ex);
}
return null;
}
async function getProcessStats() {
const runningPids = await getRunningExecutables();
const runningPidsWithUptime = await Promise.all(runningPids.map(async processInfo => {
const uptime = await getProcessUptimeInSeconds(processInfo.pid);
return {
...processInfo,
uptime,
}
}));
return runningPidsWithUptime;
}
function printProcessStats(processStats) {
processStats.forEach(processInfo => {
console.log(`[process_stats] pid: ${processInfo.pid} exe: ${processInfo.exe} uptime: ${processInfo.uptime}`);
});
if (processStats.length === 0) {
console.log('[process_stats] No processes running');
}
}
module.exports = {
getProcessRSSMemory,
getProcessStats,
printProcessStats,
getProcessFds,
getAllProcessFds
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment