Skip to content

Instantly share code, notes, and snippets.

@yurynix
Last active November 26, 2018 12:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yurynix/16ef0fabef1f996e3cbc819ba9bb89b7 to your computer and use it in GitHub Desktop.
Save yurynix/16ef0fabef1f996e3cbc819ba9bb89b7 to your computer and use it in GitHub Desktop.
Get process with their inotify handles and watches counts
// based on https://unix.stackexchange.com/questions/15509/whos-consuming-my-inotify-resources/426001#426001
const fs = require('fs');
const { promisify } = require('util');
const readdirAsync = promisify(fs.readdir);
const readFileAsync = promisify(fs.readFile);
const readlinkAsync = promisify(fs.readlink);
(async function () {
if (process.platform !== 'linux') {
console.log('This script useful only on linux')
return;
}
const procEntries = await readdirAsync('/proc');
const pids = procEntries.filter(e => e.match(/\d+/));
const intofiyPidMap = {};
await Promise.all(
pids.map(async pid => {
try {
const procFds = await readdirAsync(`/proc/${pid}/fd`);
const procFdsWithLinks = await Promise.all(
procFds.map(async fd => ({
fd,
link: await readlinkAsync(`/proc/${pid}/fd/${fd}`),
})),
);
const intofiyFds = procFdsWithLinks.filter(
({ link }) => link && link.includes('inotify'),
);
const allPidInfo = await Promise.all(
intofiyFds.map(async ifd => {
try {
const fdinfo = (await readFileAsync(
`/proc/${pid}/fdinfo/${ifd.fd}`,
)).toString();
const fdinfoIntofiyFdsCount = (fdinfo.match(/inotify/g) || [])
.length;
return {
...ifd,
pid,
fdinfoIntofiyFdsCount,
};
} catch (e) {
console.log(
`Error reading /proc/${pid}/fdinfo/${ifd.fd} - ${e.message}`,
);
return null;
}
}),
);
intofiyPidMap[pid] = allPidInfo;
} catch (e) {
// I don't care about permission denined, probably pid not owned by user
// console.log(`Error reading /proc/${pid}/fd - ${e.message}`);
}
}),
);
const stats = Object.keys(intofiyPidMap)
.filter(k => intofiyPidMap[k].length > 0)
.map(k => {
const pid = intofiyPidMap[k][0].pid;
const handlesCount = intofiyPidMap[k].length;
const watchesCount = intofiyPidMap[k].reduce(
(acc, fdInfo) => acc + fdInfo.fdinfoIntofiyFdsCount,
0,
);
return {
pid,
handlesCount,
watchesCount,
};
})
.sort((a, b) => a.watchesCount - b.watchesCount);
stats.forEach(async stat => {
const cmdline = (await readFileAsync(
`/proc/${stat.pid}/cmdline`,
)).toString();
const cwd = await readlinkAsync(`/proc/${stat.pid}/cwd`);
console.log(`PID ${stat.pid} handles: ${stat.handlesCount} watches: ${stat.watchesCount} cmd: "${cmdline}" cwd: ${cwd}`);
});
console.log('Count inotify fds in /proc done:', stats.length);
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment