Last active
November 26, 2018 12:55
-
-
Save yurynix/16ef0fabef1f996e3cbc819ba9bb89b7 to your computer and use it in GitHub Desktop.
Get process with their inotify handles and watches counts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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