Encontrei esse problema e nenhuma dessas respostas fornece a resposta "quantos relógios cada processo está usando atualmente?" Todos os itens de uma linha fornecem quantas instâncias estão abertas, o que é apenas parte da história, e o material de rastreamento é útil apenas para ver novos relógios sendo abertos.
TL; DR: você receberá um arquivo com uma lista de inotify
instâncias abertas e o número de relógios que eles têm, juntamente com os pids e binários que os geraram, classificados em ordem decrescente pela contagem de visualizações:
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 aqui está como cheguei lá. Para começar, eu corri um tail
arquivo de teste e observei os arquivos abertos:
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 valor que queremos investigar. Vamos ver o que há 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 inotifywait
utilitário, apenas observando o que estiver 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! Portanto, devemos ter seis coisas /tmp
:
joel@opx1:~$ ls /tmp/ | wc -l
6
Excelente. Meu novo inotifywait
tem uma entrada em sua fd
lista (que é o que os outros itens aqui estão contando), mas seis entradas em seu fdinfo
arquivo. Assim, podemos descobrir quantos relógios um determinado fd para um determinado processo está usando consultando seu fdinfo
arquivo. Agora, junte-o a algumas das opções acima para obter uma lista de processos que notificaram a abertura de relógios e use isso para contar as entradas em cada um fdinfo
. Isso é semelhante ao acima, então eu vou despejar 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 criar um fdinfo
caminho a partir da lsof
saída, pegando o número pid e fd, retirando a bandeira u / r / w do último. Então, para cada fdinfo
caminho construído , conto o número de inotify
linhas e produzo a contagem e o pid.
Seria bom se eu tivesse quais processos esses pids representam no mesmo lugar, certo? Eu pensei assim. Assim, em um pouco particularmente confuso, eu estabeleci-me em chamar dirname
duas vezes no fdinfo
caminho para chegar pack para /proc/<pid>
, adicionando /exe
a ele, e depois correndo readlink
em que para obter o nome exe do processo. Jogue isso lá também, classifique-o pelo número de relógios e redirecione-o para um arquivo para proteção e obteremos:
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
Executando isso sem o sudo para apenas mostrar meus processos que iniciei acima, 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 cada um está usando, exatamente o que eu precisava.
find /proc/*/fd/* -type l -lname 'anon_inode:inotify' -print