Projet

Général

Profil

Paste
Télécharger au format
Statistiques
| Branche: | Révision:

root / plugins / network / netatalk @ 2e5b796e

Historique | Voir | Annoter | Télécharger (5,51 ko)

1
#!/bin/bash
2

    
3
: << =cut
4

    
5
=head1 NAME
6

    
7
netatalk - Plugin to monitor number of files held open by the Netatalk/AFP clients
8

    
9
=head1 CONFIGURATION
10

    
11
This plugin uses the following configuration variables
12

    
13
  [netatalk]
14
  user root		- Plugin must run under root for lsof
15
  env.afpd		- Path to "afpd" executable (defaults to what afpd -v says, usually "/usr/sbin/afpd")
16
  env.afpdconf	- Path to "afpd.conf" file (defaults to what afpd -v says, usually "/etc/netatalk/afpd.conf")
17

    
18
=head1 VERSION
19

    
20
0.1 (2012-05-23)
21

    
22
=head1 AUTHOR
23

    
24
DUVERGIER Claude (http://claude.duvergier.fr)
25

    
26
=head1 LICENSE
27

    
28
GPLv2
29

    
30
=head1 BUGS
31

    
32
Known bugs:
33
* A bug can occur if a shared path is located inside another shared path (eg. "/mnt/afpShares/foo" and  "/mnt/afpShares/foo/subFoo/bar").
34
  Depending of the order the shares are found, the script might say the less-deeper one is opened whereas he is processing the other one.
35

    
36
=head1 TODO
37

    
38
Features to-do list:
39
* Support multiple servers
40

    
41
=head1 MAGIC MARKERS
42

    
43
 #%# family=contrib
44
 #%# capabilities=autoconf
45

    
46
=cut
47

    
48
# Find "afpd" location:
49
afpdPath=${afpd:-`which afpd`}
50
afpdPath=${afpdPath:-/usr/sbin/afpd}
51

    
52

    
53

    
54
#####
55
## Munin configuration ("autoconf" and "config")
56
#####
57

    
58
if [ "$1" = "autoconf" ]; then
59
	if [ -x $afpdPath ]; then
60
		echo yes
61
		exit 0
62
	else
63
		echo no '(afpd not found)'
64
		exit 0
65
	fi
66
fi
67

    
68
if [ "$1" = "config" ]; then
69
	echo 'graph_title Netatalk status'
70
	echo 'graph_args --logarithmic --lower-limit 0.1'
71
	echo 'graph_vlabel Number'
72
	echo 'graph_category network'
73
	echo 'proc.label Running processes'
74
	echo 'proc.info Number of running afpd processes'
75
	echo 'proc.min 0'
76
	echo 'user.label Connected users'
77
	echo 'user.info Number of users connected to netatalk service'
78
	echo 'user.min 0'
79
	echo 'lock.label Locked files'
80
	echo 'lock.info Number of files locked by afpd'
81
	echo 'lock.min 0'
82
	echo 'share.label Open shares'
83
	echo 'share.info Number of open netatalk shares'
84
	echo 'share.min 0'
85
	exit 0
86
fi
87

    
88
##########
89

    
90

    
91

    
92
#####
93
## Script environment
94
#####
95

    
96
# Find "afpd.conf" location:
97
afpdConfPath=${afpdconf:-`$afpdPath -v 2>/dev/null | grep "afpd.conf" | awk '{print $2}'`}
98

    
99
baseLsofCommand="lsof -a -c $(basename $afpdPath) -d ^DEL,^err,^jld,^ltx,^Mxx,^m86,^mem,^mmap,^pd,^rtd,^tr,^txt,^v86"
100

    
101
#TODO: Support multiple servers
102
defaultServer_defaultVolConfigLine=$(cat $afpdConfPath | grep "^[^#]" | grep "\-defaultvol")
103
if [ -z "$defaultServer_defaultVolConfigLine" ]; then
104
	defaultServer_volumesFile=`$afpdPath -v 2>/dev/null | grep "AppleVolumes.default" | awk '{print $2}'` # Default location "AppleVolumes.default"
105
else
106
	defaultVol_pathIsQuoted="-defaultvol ('|\")"
107
	defaultVol_quotedPattern="-defaultvol ('|\")([^\1]*)\1"
108
	# Following regex is from http://stackoverflow.com/questions/537772/what-is-the-most-correct-regular-expression-for-a-unix-file-path
109
	defaultVol_nonQuotedPattern='-defaultvo(l) (([^\0 !$`&*()+]|\\( |!|$|`|&|\*|\(|\)|\+))+)'
110
	defaultVol_pathPattern=$defaultVol_nonQuotedPattern
111
	[[ $defaultServer_defaultVolConfigLine =~ $defaultVol_pathIsQuoted ]] && defaultVol_pathPattern=$defaultVol_quotedPattern
112
	[[ $defaultServer_defaultVolConfigLine =~ $defaultVol_pathPattern ]] && defaultServer_volumesFile=${BASH_REMATCH[2]}
113
fi
114

    
115
##########
116

    
117

    
118

    
119
#####
120
## Actual monitoring
121
#####
122

    
123
# Running processes (proc):
124
echo "proc.value" $(ps ax --no-headers -o command | grep "^$afpdPath" | wc -l)
125

    
126
# Connected users (user):
127
# We will ignore root (having UID=0 it's line will be first) (assomption done: there will have only one line corresponding to root in `ps` output)
128
connectedUsers=$(ps anx --no-headers -o uid,command | sed 's/^ *//g' | grep "^[0-9]* $afpdPath" | sort -n | tail -n +2 | awk '{print $1}')
129
echo "user.value" `echo $connectedUsers | wc -w`
130

    
131
# Locked files (lock):
132
echo "lock.value" $($baseLsofCommand -F l | grep "^l[rRwWu]" | wc -l)
133

    
134
# Open shares (share):
135
openShares=0
136

    
137
#TOFIX: A bug can occur if a shared path is located inside another shared path (eg. "/mnt/afpShares/foo" and  "/mnt/afpShares/foo/subFoo/bar"):
138
#       Depending of the order the shares are found, the script might say the less-deeper one is opened whereas he is processing the other one
139
#       Solution: sort shares per descending depth
140

    
141
# Following regex is from http://stackoverflow.com/questions/10134129/generic-shell-bash-method-to-parse-string-for-possibly-quoted-fields
142
for shareName in `cat $defaultServer_volumesFile | grep "^[^#:]" | grep -oP "^(['\"]).*?\1|^(\\\\ |[^ '\"])*"`; do
143
	if [[ "$shareName" =~ "~" ]]; then
144
		for currentUid in $connectedUsers; do # For each connected users
145
			currentUserHomeDir=`getent passwd $currentUid | cut -d ':' -f6` # Fetch it's the home directory
146
			currentUserHomeDir=`readlink -f "$currentUserHomeDir"` # We want the realpath (resolves symbolic links and normalize the path)
147
			
148
			#FIX: We use pipe `lsof` outputs to `echo -e` with `xargs` because lsof "displays only printable ASCII characters" (cf. http://ftp.cerias.purdue.edu/pub/tools/unix/sysutils/lsof/00FAQ #14.5)
149
			#     Then if a share with non-ASCII characters in it's path were to be opened, lsof would return them on \xNN form and grep wouldn't match: `echo -e /the/path` fixes this
150
			[ `$baseLsofCommand -F n | xargs -0 echo -e | grep "^n$currentUserHomeDir" | wc -l` -gt 0 ] && let openShares++ # If found in lsof output: increment the openShares counter
151
		done
152
	else
153
		shareName=`readlink -f "$shareName"` # We want the realpath (resolves symbolic links and normalize the path)
154
		[ `$baseLsofCommand -F n | xargs -0 echo -e | grep "^n$shareName" | wc -l` -gt 0 ] && let openShares++ # If found in lsof output: increment the openShares counter
155
	fi
156
done
157
echo "share.value" $openShares
158

    
159
##########