-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This commit factors out several common ZEDLET code blocks into zed-functions.sh. This shortens the length of the scripts, thereby (hopefully) making them easier to understand and maintain. In addition, this commit revamps the coding style used by the scripts to be more consistent and (again, hopefully) maintainable. It now mostly follows the Google Shell Style Guide. I've tried to assimilate the following resources: Google Shell Style Guide https://google-styleguide.googlecode.com/svn/trunk/shell.xml Dash as /bin/sh https://wiki.ubuntu.com/DashAsBinSh Filenames and Pathnames in Shell: How to do it Correctly http://www.dwheeler.com/essays/filenames-in-shell.html Common shell script mistakes http://www.pixelbeat.org/programming/shell_script_mistakes.html Finally, this commit updates the exit codes used by the ZEDLETs to be more consistent with one another. All scripts run cleanly through ShellCheck <http://www.shellcheck.net/>. All scripts have been tested on bash and dash. Signed-off-by: Chris Dunlap <[email protected]>
- Loading branch information
1 parent
0336f3d
commit aded9a6
Showing
11 changed files
with
630 additions
and
337 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
Shell scripts are the recommended choice for ZEDLETs that mostly call | ||
other utilities and do relatively little data manipulation. | ||
|
||
Shell scripts MUST work on both bash and dash. | ||
|
||
Shell scripts MUST run cleanly through ShellCheck: | ||
http://www.shellcheck.net/ | ||
|
||
General functions reside in "zed-functions.sh". Use them where applicable. | ||
|
||
Additional references that may be of use: | ||
|
||
Google Shell Style Guide | ||
https://google-styleguide.googlecode.com/svn/trunk/shell.xml | ||
|
||
Dash as /bin/sh | ||
https://wiki.ubuntu.com/DashAsBinSh | ||
|
||
Common shell script mistakes | ||
http://www.pixelbeat.org/programming/shell_script_mistakes.html | ||
|
||
Filenames and Pathnames in Shell: How to do it Correctly | ||
http://www.dwheeler.com/essays/filenames-in-shell.html | ||
|
||
Autoconf: Portable Shell Programming | ||
https://www.gnu.org/software/autoconf/manual/autoconf.html#Portable-Shell | ||
|
||
Please BE CONSISTENT with the existing style, check for errors, | ||
minimize dependencies where possible, try to be portable, | ||
and comment anything non-obvious. Festina lente. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,10 @@ | ||
#!/bin/sh | ||
# | ||
# Log the zevent via syslog. | ||
# | ||
test -f "${ZED_ZEDLET_DIR}/zed.rc" && . "${ZED_ZEDLET_DIR}/zed.rc" | ||
|
||
logger -t "${ZED_SYSLOG_TAG:=zed}" -p "${ZED_SYSLOG_PRIORITY:=daemon.notice}" \ | ||
eid="${ZEVENT_EID}" class="${ZEVENT_SUBCLASS}" \ | ||
"${ZEVENT_POOL:+pool=$ZEVENT_POOL}" | ||
[ -f "${ZED_ZEDLET_DIR}/zed.rc" ] && . "${ZED_ZEDLET_DIR}/zed.rc" | ||
. "${ZED_ZEDLET_DIR}/zed-functions.sh" | ||
|
||
zed_log_msg "eid=${ZEVENT_EID}" "class=${ZEVENT_SUBCLASS}" \ | ||
"${ZEVENT_POOL:+"pool=${ZEVENT_POOL}"}" | ||
exit 0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,81 +1,53 @@ | ||
#!/bin/sh | ||
# | ||
# Send email to ZED_EMAIL in response to a DATA zevent. | ||
# Only one message per ZED_EMAIL_INTERVAL_SECS will be sent for a given | ||
# class/pool combination. This protects against spamming the recipient | ||
# should multiple events occur together in time for the same pool. | ||
# Send email to ZED_EMAIL in response to a DATA error. | ||
# | ||
# Only one email per ZED_EMAIL_INTERVAL_SECS will be sent for a given | ||
# class/pool combination. This protects against spamming the recipient | ||
# should multiple events occur together in time for the same pool. | ||
# | ||
# Exit codes: | ||
# 0: email sent | ||
# 1: email failed | ||
# 2: email suppressed | ||
# 3: missing executable | ||
# 4: unsupported event class | ||
# 5: internal error | ||
# State File Format: | ||
# POOL;TIME_OF_LAST_EMAIL | ||
# | ||
test -f "${ZED_ZEDLET_DIR}/zed.rc" && . "${ZED_ZEDLET_DIR}/zed.rc" | ||
# 2: email not configured | ||
# 3: email suppressed | ||
# 9: internal error | ||
|
||
test -n "${ZEVENT_POOL}" || exit 5 | ||
test -n "${ZEVENT_SUBCLASS}" || exit 5 | ||
[ -f "${ZED_ZEDLET_DIR}/zed.rc" ] && . "${ZED_ZEDLET_DIR}/zed.rc" | ||
. "${ZED_ZEDLET_DIR}/zed-functions.sh" | ||
|
||
if test "${ZEVENT_SUBCLASS}" != "data"; then \ | ||
logger -t "${ZED_SYSLOG_TAG:=zed}" \ | ||
-p "${ZED_SYSLOG_PRIORITY:=daemon.warning}" \ | ||
`basename "$0"`: unsupported event class \"${ZEVENT_SUBCLASS}\" | ||
exit 4 | ||
fi | ||
[ -n "${ZED_EMAIL}" ] || exit 2 | ||
|
||
# Only send email if ZED_EMAIL has been configured. | ||
test -n "${ZED_EMAIL}" || exit 2 | ||
[ -n "${ZEVENT_POOL}" ] || exit 9 | ||
[ -n "${ZEVENT_SUBCLASS}" ] || exit 9 | ||
|
||
# Ensure requisite executables are installed. | ||
if ! command -v "${MAIL:=mail}" >/dev/null 2>&1; then | ||
logger -t "${ZED_SYSLOG_TAG:=zed}" \ | ||
-p "${ZED_SYSLOG_PRIORITY:=daemon.warning}" \ | ||
`basename "$0"`: "${MAIL}" not installed | ||
exit 3 | ||
if [ "${ZEVENT_SUBCLASS}" != "data" ]; then \ | ||
zed_log_err "unsupported event class \"${ZEVENT_SUBCLASS}\"" | ||
exit 9 | ||
fi | ||
|
||
NAME="zed.${ZEVENT_SUBCLASS}.email" | ||
LOCKFILE="${ZED_LOCKDIR:=/var/lock}/${NAME}.lock" | ||
STATEFILE="${ZED_RUNDIR:=/var/run}/${NAME}.state" | ||
zed_check_cmd "mail" || exit 9 | ||
|
||
# Obtain lock to ensure mutual exclusion for accessing state. | ||
exec 8> "${LOCKFILE}" | ||
flock -x 8 | ||
zed_rate_limit "${ZEVENT_POOL};${ZEVENT_SUBCLASS};email" || exit 3 | ||
|
||
# Query state for last time email was sent for this pool. | ||
TIME_NOW=`date +%s` | ||
TIME_LAST=`egrep "^${ZEVENT_POOL};" "${STATEFILE}" 2>/dev/null | cut -d ";" -f2` | ||
if test -n "${TIME_LAST}"; then | ||
TIME_DELTA=`expr "${TIME_NOW}" - "${TIME_LAST}"` | ||
if test "${TIME_DELTA}" -lt "${ZED_EMAIL_INTERVAL_SECS:=3600}"; then | ||
exit 2 | ||
fi | ||
fi | ||
|
||
"${MAIL}" -s "ZFS ${ZEVENT_SUBCLASS} error for ${ZEVENT_POOL} on `hostname`" \ | ||
"${ZED_EMAIL}" <<EOF | ||
umask 077 | ||
email_subject="ZFS ${ZEVENT_SUBCLASS} error for ${ZEVENT_POOL} on $(hostname)" | ||
email_pathname="${TMPDIR:="/tmp"}/$(basename -- "$0").${ZEVENT_EID}.$$" | ||
cat > "${email_pathname}" <<EOF | ||
A ZFS ${ZEVENT_SUBCLASS} error has been detected: | ||
eid: ${ZEVENT_EID} | ||
host: `hostname` | ||
host: $(hostname) | ||
time: ${ZEVENT_TIME_STRING} | ||
pool: ${ZEVENT_POOL} | ||
EOF | ||
MAIL_STATUS=$? | ||
|
||
# Update state. | ||
egrep -v "^${ZEVENT_POOL};" "${STATEFILE}" 2>/dev/null > "${STATEFILE}.$$" | ||
echo "${ZEVENT_POOL};${TIME_NOW}" >> "${STATEFILE}.$$" | ||
mv -f "${STATEFILE}.$$" "${STATEFILE}" | ||
mail -s "${email_subject}" "${ZED_EMAIL}" < "${email_pathname}" | ||
mail_status=$? | ||
|
||
if test "${MAIL_STATUS}" -ne 0; then | ||
logger -t "${ZED_SYSLOG_TAG:=zed}" \ | ||
-p "${ZED_SYSLOG_PRIORITY:=daemon.warning}" \ | ||
`basename "$0"`: "${MAIL}" exit="${MAIL_STATUS}" | ||
exit 1 | ||
if [ "${mail_status}" -ne 0 ]; then | ||
zed_log_msg "mail exit=${mail_status}" | ||
exit 1 | ||
fi | ||
|
||
rm -f "${email_pathname}" | ||
exit 0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,59 +1,59 @@ | ||
#!/bin/sh | ||
# | ||
# Send email to ZED_EMAIL in response to a given zevent. | ||
# This is a generic script than can be symlinked to a file in the zed | ||
# enabled-scripts directory in order to have email sent when a particular | ||
# class of zevents occurs. The symlink filename must begin with the zevent | ||
# (sub)class string (eg, "probe_failure-email.sh" for the "probe_failure" | ||
# subclass). Refer to the zed(8) manpage for details. | ||
# | ||
# This is a generic script than can be symlinked to a file in the | ||
# enabled-zedlets directory to have an email sent when a particular class of | ||
# zevents occurs. The symlink filename must begin with the zevent (sub)class | ||
# string (e.g., "probe_failure-email.sh" for the "probe_failure" subclass). | ||
# Refer to the zed(8) manpage for details. | ||
# | ||
# Exit codes: | ||
# 0: email sent | ||
# 1: email failed | ||
# 2: email suppressed | ||
# 3: missing executable | ||
# | ||
test -f "${ZED_ZEDLET_DIR}/zed.rc" && . "${ZED_ZEDLET_DIR}/zed.rc" | ||
# 2: email not configured | ||
# 3: email suppressed | ||
|
||
# Only send email if ZED_EMAIL has been configured. | ||
test -n "${ZED_EMAIL}" || exit 2 | ||
[ -f "${ZED_ZEDLET_DIR}/zed.rc" ] && . "${ZED_ZEDLET_DIR}/zed.rc" | ||
. "${ZED_ZEDLET_DIR}/zed-functions.sh" | ||
|
||
# Ensure requisite executables are installed. | ||
if ! command -v "${MAIL:=mail}" >/dev/null 2>&1; then | ||
logger -t "${ZED_SYSLOG_TAG:=zed}" \ | ||
-p "${ZED_SYSLOG_PRIORITY:=daemon.warning}" \ | ||
`basename "$0"`: "${MAIL}" not installed | ||
exit 3 | ||
fi | ||
[ -n "${ZED_EMAIL}" ] || exit 2 | ||
|
||
# Rate-limit the message based in part on the filename. | ||
# | ||
rate_limit_tag="${ZEVENT_POOL};${ZEVENT_SUBCLASS};$(basename -- "$0")" | ||
rate_limit_interval="${ZED_EMAIL_INTERVAL_SECS}" | ||
zed_rate_limit "${rate_limit_tag}" "${rate_limit_interval}" || exit 3 | ||
|
||
# Override the default umask to restrict access to the msgbody tmpfile. | ||
umask 077 | ||
pool_str="${ZEVENT_POOL:+" for ${ZEVENT_POOL}"}" | ||
host_str=" on $(hostname)" | ||
email_subject="ZFS ${ZEVENT_SUBCLASS} event${pool_str}${host_str}" | ||
email_pathname="${TMPDIR:="/tmp"}/$(basename -- "$0").${ZEVENT_EID}.$$" | ||
{ | ||
echo "ZFS has posted the following event:" | ||
echo | ||
echo " eid: ${ZEVENT_EID}" | ||
echo " class: ${ZEVENT_SUBCLASS}" | ||
echo " host: $(hostname)" | ||
echo " time: ${ZEVENT_TIME_STRING}" | ||
|
||
SUBJECT="ZFS ${ZEVENT_SUBCLASS} event" | ||
test -n "${ZEVENT_POOL}" && SUBJECT="${SUBJECT} for ${ZEVENT_POOL}" | ||
SUBJECT="${SUBJECT} on `hostname`" | ||
if [ -n "${ZEVENT_VDEV_PATH}" ]; then | ||
echo " vpath: ${ZEVENT_VDEV_PATH}" | ||
[ -n "${ZEVENT_VDEV_TYPE}" ] && echo " vtype: ${ZEVENT_VDEV_TYPE}" | ||
fi | ||
|
||
MSGBODY="${TMPDIR:=/tmp}/`basename \"$0\"`.$$" | ||
{ | ||
echo "A ZFS ${ZEVENT_SUBCLASS} event has been posted:" | ||
echo | ||
echo " eid: ${ZEVENT_EID}" | ||
echo " host: `hostname`" | ||
echo " time: ${ZEVENT_TIME_STRING}" | ||
test -n "${ZEVENT_VDEV_TYPE}" -a -n "${ZEVENT_VDEV_PATH}" && \ | ||
echo " vdev: ${ZEVENT_VDEV_TYPE}:${ZEVENT_VDEV_PATH}" | ||
test -n "${ZEVENT_POOL}" -a -x "${ZPOOL}" && \ | ||
"${ZPOOL}" status "${ZEVENT_POOL}" | ||
} > "${MSGBODY}" | ||
|
||
test -f "${MSGBODY}" && "${MAIL}" -s "${SUBJECT}" "${ZED_EMAIL}" < "${MSGBODY}" | ||
MAIL_STATUS=$? | ||
rm -f "${MSGBODY}" | ||
|
||
if test "${MAIL_STATUS}" -ne 0; then | ||
logger -t "${ZED_SYSLOG_TAG:=zed}" \ | ||
-p "${ZED_SYSLOG_PRIORITY:=daemon.warning}" \ | ||
`basename "$0"`: "${MAIL}" exit="${MAIL_STATUS}" | ||
exit 1 | ||
fi | ||
[ -n "${ZEVENT_POOL}" ] && [ -x "${ZPOOL}" ] \ | ||
&& "${ZPOOL}" status "${ZEVENT_POOL}" | ||
|
||
} > "${email_pathname}" | ||
|
||
mail -s "${email_subject}" "${ZED_EMAIL}" < "${email_pathname}" | ||
mail_status=$? | ||
|
||
if [ "${mail_status}" -ne 0 ]; then | ||
zed_log_msg "mail exit=${mail_status}" | ||
exit 1 | ||
fi | ||
rm -f "${email_pathname}" | ||
exit 0 |
Oops, something went wrong.