Natknąłem się na ten problem i żadna z tych odpowiedzi nie daje odpowiedzi „ile zegarków obecnie używa każdy proces?” Wszystkie linijki pokazują, ile instancji jest otwartych, co jest tylko częścią historii, a ślady są przydatne tylko do oglądania nowych zegarków.
TL; DR: Otrzymasz plik z listą otwartych inotify
instancji i liczbą posiadanych zegarków , wraz z pidami i plikami binarnymi, które je zrodziły, posortowanymi w kolejności malejącej według liczby zegarków:
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
To wielka kula bałaganu, więc oto jak się tam dostałem. Aby rozpocząć, uruchomiłem tail
plik testowy i spojrzałem na otwarte fd:
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
Tak więc 4 to fd, który chcemy zbadać. Zobaczmy, co w fdinfo
tym jest:
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
To wygląda jak wpis do zegarka na dole!
Spróbujmy czegoś z większą liczbą zegarków, tym razem z inotifywait
narzędziem, po prostu oglądając wszystko, co jest w /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! Więcej wpisów! Powinniśmy zatem mieć sześć rzeczy /tmp
:
joel@opx1:~$ ls /tmp/ | wc -l
6
Doskonały. Mój nowy inotifywait
ma jeden wpis na fd
liście (to, co liczą inne tutaj jednowierszowe), ale sześć wpisów w swoim fdinfo
pliku. Możemy więc dowiedzieć się, ile zegarków używa dany FD dla danego procesu, sprawdzając jego fdinfo
plik. Teraz, aby połączyć to z niektórymi z powyższych, aby pobrać listę procesów, które powiadomiły zegarki otwarte i użyj tego, aby policzyć wpisy w każdym z nich fdinfo
. Jest to podobne do powyższego, więc po prostu zrzucę tutaj linijkę:
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
Jest tu trochę grubych rzeczy, ale podstawy są takie, że używam awk
do budowania fdinfo
ścieżki z danych lsof
wyjściowych, chwytając numer pid i fd, usuwając z niego flagę u / r / w. Następnie dla każdej skonstruowanej fdinfo
ścieżki liczę liczbę inotify
wierszy i wyprowadzam liczbę i pid.
Byłoby miło, gdybym miał procesy, które te pidy reprezentują w tym samym miejscu, prawda? Tak myślałem. Tak więc, w szczególnie brudny bit, zdecydowałem się na wywołanie dirname
dwukrotnie na fdinfo
drodze do uzyskania Pack /proc/<pid>
, dodając /exe
do niego, a następnie uruchomić readlink
na to , aby uzyskać nazwę exe procesu. Wrzuć to tam, posortuj według liczby zegarków i przekieruj do pliku w celu bezpiecznego przechowywania, a otrzymamy:
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
Działając bez sudo, aby pokazać moje procesy, które uruchomiłem powyżej, otrzymuję:
joel@gladstone:~$ cat watches
6 /proc/4906/fdinfo/3 /usr/bin/inotifywait
1 /proc/22734/fdinfo/4 /usr/bin/tail
Doskonały! Lista procesów, fd i liczba używanych zegarków , dokładnie tego potrzebowałem.
find /proc/*/fd/* -type l -lname 'anon_inode:inotify' -print