Eu me deparei com esse problema, e nenhuma dessas respostas dá a você a resposta de "quantos relógios cada processo está usando atualmente?" Os one-liners dão a você quantas instâncias estão abertas, o que é apenas parte da história, e o material de rastreamento só é útil para ver novos relógios sendo abertos.
TL; DR: Isso gerará um arquivo com uma lista de inotify
instâncias abertas e o número de relógios que eles têm, junto com os pids e binários que os gerou, classificados em ordem decrescente por contagem de relógios:
sudo lsof | awk '/anon_inode/ { gsub(/[urw]$/,"",$4); print "/proc/"$2"/fdinfo/"$4; }' | while read fdi; do count=$(sudo grep -c inotify $fdi); exe=$(sudo readlink $(dirname $(dirname $fdi))/exe); echo -e $count"\t"$fdi"\t"$exe; done | sort -nr > watches
É uma grande bagunça, então é assim que cheguei lá. Para começar, eu corri um tail
em um arquivo de teste e olhei para o fd que ele abriu:
joel@gladstone:~$ tail -f test > /dev/null &
[3] 22734
joel@opx1:~$ ls -ahltr /proc/22734/fd
total 0
dr-xr-xr-x 9 joel joel 0 Feb 22 22:34 ..
dr-x------ 2 joel joel 0 Feb 22 22:34 .
lr-x------ 1 joel joel 64 Feb 22 22:35 4 -> anon_inode:inotify
lr-x------ 1 joel joel 64 Feb 22 22:35 3 -> /home/joel/test
lrwx------ 1 joel joel 64 Feb 22 22:35 2 -> /dev/pts/2
l-wx------ 1 joel joel 64 Feb 22 22:35 1 -> /dev/null
lrwx------ 1 joel joel 64 Feb 22 22:35 0 -> /dev/pts/2
Então, 4 é o fd que queremos investigar. Vamos ver o que está no fdinfo
para isso:
joel@opx1:~$ cat /proc/22734/fdinfo/4
pos: 0
flags: 00
mnt_id: 11
inotify wd:1 ino:15f51d sdev:ca00003 mask:c06 ignored_mask:0 fhandle-bytes:8 fhandle-type:1 f_handle:1df51500a75e538c
Parece uma entrada para o relógio na parte inferior!
Vamos tentar algo com mais relógios, desta vez com o utilitário inotifywait
, apenas observando o que está em /tmp
:
joel@gladstone:~$ inotifywait /tmp/* &
[4] 27862
joel@gladstone:~$ Setting up watches.
Watches established.
joel@gladstone:~$ ls -ahtlr /proc/27862/fd | grep inotify
lr-x------ 1 joel joel 64 Feb 22 22:41 3 -> anon_inode:inotify
joel@gladstone:~$ cat /proc/27862/fdinfo/3
pos: 0
flags: 00
mnt_id: 11
inotify wd:6 ino:7fdc sdev:ca00003 mask:fff ignored_mask:0 fhandle-bytes:8 fhandle-type:1 f_handle:dc7f0000551e9d88
inotify wd:5 ino:7fcb sdev:ca00003 mask:fff ignored_mask:0 fhandle-bytes:8 fhandle-type:1 f_handle:cb7f00005b1f9d88
inotify wd:4 ino:7fcc sdev:ca00003 mask:fff ignored_mask:0 fhandle-bytes:8 fhandle-type:1 f_handle:cc7f00006a1d9d88
inotify wd:3 ino:7fc6 sdev:ca00003 mask:fff ignored_mask:0 fhandle-bytes:8 fhandle-type:1 f_handle:c67f00005d1d9d88
inotify wd:2 ino:7fc7 sdev:ca00003 mask:fff ignored_mask:0 fhandle-bytes:8 fhandle-type:1 f_handle:c77f0000461d9d88
inotify wd:1 ino:7fd7 sdev:ca00003 mask:fff ignored_mask:0 fhandle-bytes:8 fhandle-type:1 f_handle:d77f00000053c98b
Aha! Mais entradas! Então devemos ter seis coisas em /tmp
então:
joel@opx1:~$ ls /tmp/ | wc -l
6
Excelente. Meu novo inotifywait
tem uma entrada em sua lista fd
(que é o que os outros marcadores estão contando aqui), mas seis entradas em seu arquivo fdinfo
. Assim, podemos descobrir quantos relógios um dado fd para um determinado processo está usando consultando o arquivo fdinfo
. Agora, para colocá-lo em conjunto com alguns dos itens acima, pegue uma lista de processos que notificam os relógios abertos e use isso para contar as entradas em cada fdinfo
. Isso é semelhante ao acima, então eu vou apenas jogar o one-liner aqui:
sudo lsof | awk '/anon_inode/ { gsub(/[urw]$/,"",$4); print "/proc/"$2"/fdinfo/"$4; }' | while read fdi; do count=$(sudo grep -c inotify $fdi); echo -e $count"\t"$fdi; done
Há algumas coisas grossas aqui, mas o básico é que eu uso awk
para construir um caminho fdinfo
da lsof
output, pegando o número pid e fd, removendo o sinalizador u / r / w de o último. Então, para cada caminho fdinfo
construído, eu conto o número de inotify
linhas e imprimo a contagem e o pid.
Seria legal se eu tivesse os processos que esses pids representam no mesmo lugar, certo? Eu pensei assim. Então, em um momento particularmente complicado, resolvi chamar dirname
duas vezes no caminho fdinfo
para obter o pacote para /proc/<pid>
, adicionando /exe
a ele e, em seguida, executando readlink
em esse para obter o nome exe do processo. Jogue isso lá também, classifique-o por número de relógios e redirecione-o para um arquivo para salvaguardar e ficamos:
sudo lsof | awk '/anon_inode/ { gsub(/[urw]$/,"",$4); print "/proc/"$2"/fdinfo/"$4; }' | while read fdi; do count=$(sudo grep -c inotify $fdi); exe=$(sudo readlink $(dirname $(dirname $fdi))/exe); echo -e $count"\t"$fdi"\t"$exe; done | sort -n > watches
Rodando o sem sudo para mostrar meus processos que eu lancei acima, eu recebo:
joel@gladstone:~$ cat watches
6 /proc/4906/fdinfo/3 /usr/bin/inotifywait
1 /proc/22734/fdinfo/4 /usr/bin/tail
Perfeito! Uma lista de processos, fd's e quantos relógios estão usando, exatamente o que eu precisava.