2014-01-02 09:56:19 +01:00
|
|
|
#!/bin/bash -
|
|
|
|
#
|
|
|
|
#### Abstract ################################################################
|
|
|
|
#
|
|
|
|
# Munin contributed plugin to measure open, locked and files being hold by
|
|
|
|
# Netatalk version 3.*;
|
|
|
|
#
|
|
|
|
#### Author ##################################################################
|
|
|
|
#
|
|
|
|
# Otavio Fernandes <otaviof@gmail.com>
|
|
|
|
# Wednesday, 01/01/2014
|
|
|
|
#
|
|
|
|
|
|
|
|
#### Functions ###############################################################
|
|
|
|
#
|
|
|
|
|
|
|
|
function afpd_full_path () {
|
|
|
|
echo $(which afpd |head -n 1)
|
|
|
|
}
|
|
|
|
|
|
|
|
function afp_related_file_exists () {
|
|
|
|
local afp_file_path=$1
|
|
|
|
if [ -z "$afp_file_path" -o ! -f "$afp_file_path" ]; then
|
|
|
|
echo "ERROR: AFP related file not found: \"${afpd_bin_path}\";" >&2
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
|
|
|
function is_netatalk_version_3 () {
|
|
|
|
local afpd_bin_path=$1
|
|
|
|
version_string="$(${afpd_bin_path} -version |head -n1 |grep '^afpd' |cut -d' ' -f2)"
|
|
|
|
if [[ $version_string != 3\.* ]]; then
|
|
|
|
cat <<EOM >&2
|
|
|
|
ERROR: Netatalk is not version 3.
|
|
|
|
Binary: ${afpd_bin_path};
|
|
|
|
Version: ${version_string};
|
|
|
|
EOM
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
|
|
|
function count_running_procs () {
|
|
|
|
local afpd_bin_path=$1
|
|
|
|
echo $(ps ax --no-headers -o command |grep "^${afpd_bin_path}" |wc -l)
|
|
|
|
}
|
|
|
|
|
|
|
|
function count_connected_users () {
|
|
|
|
local afpd_bin_path=$1
|
|
|
|
afpd_procs=$(ps anx --no-headers -o uid,command |grep -E "\w+\d+*\s${afpd_bin_path}" |wc -l)
|
2017-04-17 22:43:38 +02:00
|
|
|
# one of those processes will be always from root user, so it's not being
|
2014-01-02 09:56:19 +01:00
|
|
|
# used to externaly connect volumes, therefor being disconsider.
|
|
|
|
echo $(echo "${afpd_procs} - 1" |bc)
|
|
|
|
}
|
|
|
|
|
|
|
|
function base_lsof () {
|
|
|
|
local afpd_bin_path=$1
|
|
|
|
process_name="$(basename ${afpd_bin_path})"
|
|
|
|
excluded_fds="^DEL,^err,^jld,^ltx,^Mxx,^m86,^mem,^mmap,^pd,^rtd,^tr,^txt,^v86"
|
|
|
|
echo "lsof -a -c ${process_name} -d ${excluded_fds}"
|
|
|
|
}
|
|
|
|
|
|
|
|
function count_locked_files () {
|
|
|
|
local afpd_bin_path=$1
|
|
|
|
cmd_suffix="$(base_lsof "${afpd_bin_path}")"
|
|
|
|
echo "$(${cmd_suffix} -F -l |grep '^l[rRwWu]' |wc -l)"
|
|
|
|
}
|
|
|
|
|
|
|
|
function probe_afp_conf_file () {
|
|
|
|
local afpd_bin_path=$1
|
|
|
|
echo "$(${afpd_bin_path} -version 2>&1 |grep -E '^\s+afp.conf\:' |awk '{print $2}')"
|
|
|
|
}
|
|
|
|
|
|
|
|
function count_open_shares () {
|
|
|
|
local afpd_bin_path=$1
|
|
|
|
local afp_conf_path=$2
|
|
|
|
|
|
|
|
mounted=0
|
|
|
|
declare -a shares=($(grep '^path.*\=' ${afp_conf_path} |awk -F '=' '{print $2}' |sed -E 's/^\s+//g'))
|
|
|
|
if [ ! -z "$shares" ]; then
|
|
|
|
# narrowing lsof results to only list configured mount directories
|
|
|
|
cmd_lookup_prefix=$(echo ${shares[@]} |tr " " "|")
|
|
|
|
cmd_suffix="$(base_lsof "${afpd_bin_path}")"
|
|
|
|
mounted=$(${cmd_suffix} -F n |grep '^n' |egrep "(${cmd_lookup_prefix})" |wc -l)
|
|
|
|
fi
|
|
|
|
echo $mounted
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#### Main ####################################################################
|
|
|
|
# For all routines, holds the entry points dealing with the informed parameter
|
|
|
|
# or lack of it, meaning just print out collected data.
|
|
|
|
#
|
|
|
|
|
|
|
|
case "$1" in
|
|
|
|
config)
|
|
|
|
# printing configuration for this plugin's produced data
|
|
|
|
cat <<EOM
|
|
|
|
graph_title Netatalk v3 Status
|
|
|
|
graph_title Netatalk status
|
|
|
|
graph_args --logarithmic --lower-limit 0.1
|
|
|
|
graph_vlabel Number
|
2017-02-24 05:01:30 +01:00
|
|
|
graph_category fs
|
2014-01-02 09:56:19 +01:00
|
|
|
proc.label Running processes
|
|
|
|
proc.info Running AFPd processes
|
|
|
|
proc.min 0
|
|
|
|
user.label Connected users
|
|
|
|
user.info Connected users
|
|
|
|
user.min 0
|
|
|
|
lock.label Locked files
|
|
|
|
lock.info AFPd locked files
|
|
|
|
lock.min 0
|
|
|
|
share.label Open shares
|
|
|
|
share.info Netatalk open shares
|
|
|
|
share.min 0
|
|
|
|
EOM
|
|
|
|
exit 0
|
|
|
|
;;
|
|
|
|
*)
|
|
|
|
#### Boilerplates ####################################################
|
|
|
|
# Locating AFP related files:
|
|
|
|
# * Binary: Using the first result of "which" command;
|
2017-04-17 22:43:38 +02:00
|
|
|
# * Config: Using "afpd" with parameters to pring configuration file
|
2014-01-02 09:56:19 +01:00
|
|
|
# location;
|
|
|
|
#
|
|
|
|
|
|
|
|
AFPD_PATH="$(afpd_full_path)"
|
|
|
|
afp_related_file_exists "${AFPD_PATH}"
|
|
|
|
is_netatalk_version_3 "${AFPD_PATH}"
|
|
|
|
|
|
|
|
AFP_CONF_PATH="$(probe_afp_conf_file "${AFPD_PATH}")"
|
|
|
|
afp_related_file_exists "${AFP_CONF_PATH}"
|
|
|
|
|
|
|
|
#### Collecting Metrics ##############################################
|
|
|
|
#
|
|
|
|
echo "proc.value" $(count_running_procs "${AFPD_PATH}")
|
|
|
|
echo "user.value" $(count_connected_users "${AFPD_PATH}")
|
|
|
|
echo "lock.value" $(count_locked_files "${AFPD_PATH}")
|
|
|
|
echo "share.value" $(count_open_shares "${AFPD_PATH}" "${AFP_CONF_PATH}")
|
|
|
|
|
|
|
|
exit 0
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
|
|
|
|
# EOF
|