diff --git a/cmd/zed/Makefile.am b/cmd/zed/Makefile.am index 8bdc097c77a3..09be2ca6c3ea 100644 --- a/cmd/zed/Makefile.am +++ b/cmd/zed/Makefile.am @@ -1,71 +1,71 @@ include $(top_srcdir)/config/Rules.am DEFAULT_INCLUDES += \ -I$(top_srcdir)/include \ -I$(top_srcdir)/lib/libspl/include EXTRA_DIST = $(top_srcdir)/cmd/zed/zed.d/README sbin_PROGRAMS = zed zed_SOURCES = \ $(top_srcdir)/cmd/zed/zed.c \ $(top_srcdir)/cmd/zed/zed.h \ $(top_srcdir)/cmd/zed/zed_conf.c \ $(top_srcdir)/cmd/zed/zed_conf.h \ $(top_srcdir)/cmd/zed/zed_event.c \ $(top_srcdir)/cmd/zed/zed_event.h \ $(top_srcdir)/cmd/zed/zed_exec.c \ $(top_srcdir)/cmd/zed/zed_exec.h \ $(top_srcdir)/cmd/zed/zed_file.c \ $(top_srcdir)/cmd/zed/zed_file.h \ $(top_srcdir)/cmd/zed/zed_log.c \ $(top_srcdir)/cmd/zed/zed_log.h \ $(top_srcdir)/cmd/zed/zed_strings.c \ $(top_srcdir)/cmd/zed/zed_strings.h zed_LDADD = \ $(top_builddir)/lib/libavl/libavl.la \ $(top_builddir)/lib/libnvpair/libnvpair.la \ $(top_builddir)/lib/libspl/libspl.la \ $(top_builddir)/lib/libzpool/libzpool.la \ $(top_builddir)/lib/libzfs/libzfs.la \ $(top_builddir)/lib/libzfs_core/libzfs_core.la zedconfdir = $(sysconfdir)/zfs/zed.d dist_zedconf_DATA = \ $(top_srcdir)/cmd/zed/zed.d/zed-functions.sh \ $(top_srcdir)/cmd/zed/zed.d/zed.rc zedexecdir = $(libexecdir)/zfs/zed.d dist_zedexec_SCRIPTS = \ $(top_srcdir)/cmd/zed/zed.d/all-debug.sh \ $(top_srcdir)/cmd/zed/zed.d/all-syslog.sh \ - $(top_srcdir)/cmd/zed/zed.d/checksum-email.sh \ + $(top_srcdir)/cmd/zed/zed.d/checksum-notify.sh \ $(top_srcdir)/cmd/zed/zed.d/checksum-spare.sh \ - $(top_srcdir)/cmd/zed/zed.d/data-email.sh \ - $(top_srcdir)/cmd/zed/zed.d/generic-email.sh \ - $(top_srcdir)/cmd/zed/zed.d/io-email.sh \ + $(top_srcdir)/cmd/zed/zed.d/data-notify.sh \ + $(top_srcdir)/cmd/zed/zed.d/generic-notify.sh \ + $(top_srcdir)/cmd/zed/zed.d/io-notify.sh \ $(top_srcdir)/cmd/zed/zed.d/io-spare.sh \ - $(top_srcdir)/cmd/zed/zed.d/resilver.finish-email.sh \ - $(top_srcdir)/cmd/zed/zed.d/scrub.finish-email.sh + $(top_srcdir)/cmd/zed/zed.d/resilver.finish-notify.sh \ + $(top_srcdir)/cmd/zed/zed.d/scrub.finish-notify.sh zedconfdefaults = \ all-syslog.sh \ - checksum-email.sh \ + checksum-notify.sh \ checksum-spare.sh \ - data-email.sh \ - io-email.sh \ + data-notify.sh \ + io-notify.sh \ io-spare.sh \ - resilver.finish-email.sh \ - scrub.finish-email.sh + resilver.finish-notify.sh \ + scrub.finish-notify.sh install-data-local: $(MKDIR_P) "$(DESTDIR)$(zedconfdir)" for f in $(zedconfdefaults); do \ test -f "$(DESTDIR)$(zedconfdir)/$${f}" -o \ -L "$(DESTDIR)$(zedconfdir)/$${f}" || \ ln -s "$(zedexecdir)/$${f}" "$(DESTDIR)$(zedconfdir)"; \ done diff --git a/cmd/zed/zed.d/checksum-email.sh b/cmd/zed/zed.d/checksum-email.sh deleted file mode 120000 index f95bec21532a..000000000000 --- a/cmd/zed/zed.d/checksum-email.sh +++ /dev/null @@ -1 +0,0 @@ -io-email.sh \ No newline at end of file diff --git a/cmd/zed/zed.d/checksum-notify.sh b/cmd/zed/zed.d/checksum-notify.sh new file mode 120000 index 000000000000..9008738073c9 --- /dev/null +++ b/cmd/zed/zed.d/checksum-notify.sh @@ -0,0 +1 @@ +io-notify.sh \ No newline at end of file diff --git a/cmd/zed/zed.d/data-email.sh b/cmd/zed/zed.d/data-email.sh deleted file mode 100755 index 2dae8ff6b468..000000000000 --- a/cmd/zed/zed.d/data-email.sh +++ /dev/null @@ -1,53 +0,0 @@ -#!/bin/sh -# -# 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 not configured -# 3: email suppressed -# 9: internal error - -[ -f "${ZED_ZEDLET_DIR}/zed.rc" ] && . "${ZED_ZEDLET_DIR}/zed.rc" -. "${ZED_ZEDLET_DIR}/zed-functions.sh" - -[ -n "${ZED_EMAIL}" ] || exit 2 - -[ -n "${ZEVENT_POOL}" ] || exit 9 -[ -n "${ZEVENT_SUBCLASS}" ] || exit 9 - -if [ "${ZEVENT_SUBCLASS}" != "data" ]; then \ - zed_log_err "unsupported event class \"${ZEVENT_SUBCLASS}\"" - exit 9 -fi - -zed_check_cmd "mail" || exit 9 - -zed_rate_limit "${ZEVENT_POOL};${ZEVENT_SUBCLASS};email" || exit 3 - -umask 077 -email_subject="ZFS ${ZEVENT_SUBCLASS} error for ${ZEVENT_POOL} on $(hostname)" -email_pathname="${TMPDIR:="/tmp"}/$(basename -- "$0").${ZEVENT_EID}.$$" -cat > "${email_pathname}" < "${note_pathname}" + +zed_notify "${note_subject}" "${note_pathname}"; rv=$? +rm -f "${note_pathname}" +exit "${rv}" diff --git a/cmd/zed/zed.d/generic-email.sh b/cmd/zed/zed.d/generic-email.sh deleted file mode 100755 index ad022e034388..000000000000 --- a/cmd/zed/zed.d/generic-email.sh +++ /dev/null @@ -1,59 +0,0 @@ -#!/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 -# 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 not configured -# 3: email suppressed - -[ -f "${ZED_ZEDLET_DIR}/zed.rc" ] && . "${ZED_ZEDLET_DIR}/zed.rc" -. "${ZED_ZEDLET_DIR}/zed-functions.sh" - -[ -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 - -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}" - - if [ -n "${ZEVENT_VDEV_PATH}" ]; then - echo " vpath: ${ZEVENT_VDEV_PATH}" - [ -n "${ZEVENT_VDEV_TYPE}" ] && echo " vtype: ${ZEVENT_VDEV_TYPE}" - 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 diff --git a/cmd/zed/zed.d/generic-notify.sh b/cmd/zed/zed.d/generic-notify.sh new file mode 100755 index 000000000000..e438031a088a --- /dev/null +++ b/cmd/zed/zed.d/generic-notify.sh @@ -0,0 +1,54 @@ +#!/bin/sh +# +# Send notification in response to a given zevent. +# +# This is a generic script than can be symlinked to a file in the +# enabled-zedlets directory to have a notification sent when a particular +# class of zevents occurs. The symlink filename must begin with the zevent +# (sub)class string (e.g., "probe_failure-notify.sh" for the "probe_failure" +# subclass). Refer to the zed(8) manpage for details. +# +# Only one notification per ZED_NOTIFY_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: notification sent +# 1: notification failed +# 2: notification not configured +# 3: notification suppressed + +[ -f "${ZED_ZEDLET_DIR}/zed.rc" ] && . "${ZED_ZEDLET_DIR}/zed.rc" +. "${ZED_ZEDLET_DIR}/zed-functions.sh" + +# Rate-limit the notification based in part on the filename. +# +rate_limit_tag="${ZEVENT_POOL};${ZEVENT_SUBCLASS};$(basename -- "$0")" +rate_limit_interval="${ZED_NOTIFY_INTERVAL_SECS}" +zed_rate_limit "${rate_limit_tag}" "${rate_limit_interval}" || exit 3 + +umask 077 +pool_str="${ZEVENT_POOL:+" for ${ZEVENT_POOL}"}" +host_str=" on $(hostname)" +note_subject="ZFS ${ZEVENT_SUBCLASS} event${pool_str}${host_str}" +note_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}" + + [ -n "${ZEVENT_VDEV_TYPE}" ] && echo " vtype: ${ZEVENT_VDEV_TYPE}" + [ -n "${ZEVENT_VDEV_PATH}" ] && echo " vpath: ${ZEVENT_VDEV_PATH}" + [ -n "${ZEVENT_VDEV_GUID}" ] && echo " vguid: ${ZEVENT_VDEV_GUID}" + + [ -n "${ZEVENT_POOL}" ] && [ -x "${ZPOOL}" ] \ + && "${ZPOOL}" status "${ZEVENT_POOL}" + +} > "${note_pathname}" + +zed_notify "${note_subject}" "${note_pathname}"; rv=$? +rm -f "${note_pathname}" +exit "${rv}" diff --git a/cmd/zed/zed.d/io-email.sh b/cmd/zed/zed.d/io-email.sh deleted file mode 100755 index 1854b15933ae..000000000000 --- a/cmd/zed/zed.d/io-email.sh +++ /dev/null @@ -1,57 +0,0 @@ -#!/bin/sh -# -# Send email to ZED_EMAIL in response to a CHECKSUM or IO error. -# -# Only one email per ZED_EMAIL_INTERVAL_SECS will be sent for a given -# class/pool/vdev combination. This protects against spamming the recipient -# should multiple events occur together in time for the same pool/device. -# -# Exit codes: -# 0: email sent -# 1: email failed -# 2: email not configured -# 3: email suppressed -# 9: internal error - -[ -f "${ZED_ZEDLET_DIR}/zed.rc" ] && . "${ZED_ZEDLET_DIR}/zed.rc" -. "${ZED_ZEDLET_DIR}/zed-functions.sh" - -[ -n "${ZED_EMAIL}" ] || exit 2 - -[ -n "${ZEVENT_POOL}" ] || exit 9 -[ -n "${ZEVENT_SUBCLASS}" ] || exit 9 -[ -n "${ZEVENT_VDEV_PATH}" ] || exit 9 - -if [ "${ZEVENT_SUBCLASS}" != "checksum" ] \ - && [ "${ZEVENT_SUBCLASS}" != "io" ]; then - zed_log_err "unsupported event class \"${ZEVENT_SUBCLASS}\"" - exit 9 -fi - -zed_check_cmd "mail" || exit 9 - -zed_rate_limit "${ZEVENT_POOL};${ZEVENT_VDEV_PATH};${ZEVENT_SUBCLASS};email" \ - || exit 3 - -umask 077 -email_subject="ZFS ${ZEVENT_SUBCLASS} error for ${ZEVENT_POOL} on $(hostname)" -email_pathname="${TMPDIR:="/tmp"}/$(basename -- "$0").${ZEVENT_EID}.$$" -cat > "${email_pathname}" < "${note_pathname}" + +zed_notify "${note_subject}" "${note_pathname}"; rv=$? +rm -f "${note_pathname}" +exit "${rv}" diff --git a/cmd/zed/zed.d/resilver.finish-email.sh b/cmd/zed/zed.d/resilver.finish-email.sh deleted file mode 120000 index 1afad3258d5e..000000000000 --- a/cmd/zed/zed.d/resilver.finish-email.sh +++ /dev/null @@ -1 +0,0 @@ -scrub.finish-email.sh \ No newline at end of file diff --git a/cmd/zed/zed.d/resilver.finish-notify.sh b/cmd/zed/zed.d/resilver.finish-notify.sh new file mode 120000 index 000000000000..2635dcce118b --- /dev/null +++ b/cmd/zed/zed.d/resilver.finish-notify.sh @@ -0,0 +1 @@ +scrub.finish-notify.sh \ No newline at end of file diff --git a/cmd/zed/zed.d/scrub.finish-email.sh b/cmd/zed/zed.d/scrub.finish-email.sh deleted file mode 100755 index 4a8155caf082..000000000000 --- a/cmd/zed/zed.d/scrub.finish-email.sh +++ /dev/null @@ -1,63 +0,0 @@ -#!/bin/sh -# -# Send email to ZED_EMAIL in response to a RESILVER.FINISH or SCRUB.FINISH. -# -# By default, "zpool status" output will only be included for a scrub.finish -# zevent if the pool is not healthy; to always include its output, set -# ZED_EMAIL_VERBOSE=1. -# -# Exit codes: -# 0: email sent -# 1: email failed -# 2: email not configured -# 3: email suppressed -# 9: internal error - -[ -f "${ZED_ZEDLET_DIR}/zed.rc" ] && . "${ZED_ZEDLET_DIR}/zed.rc" -. "${ZED_ZEDLET_DIR}/zed-functions.sh" - -[ -n "${ZED_EMAIL}" ] || exit 2 - -[ -n "${ZEVENT_POOL}" ] || exit 9 -[ -n "${ZEVENT_SUBCLASS}" ] || exit 9 - -if [ "${ZEVENT_SUBCLASS}" = "resilver.finish" ]; then - action="resilver" -elif [ "${ZEVENT_SUBCLASS}" = "scrub.finish" ]; then - action="scrub" -else - zed_log_err "unsupported event class \"${ZEVENT_SUBCLASS}\"" - exit 9 -fi - -zed_check_cmd "mail" "${ZPOOL}" || exit 9 - -# For scrub, suppress email if pool is healthy and verbosity is not enabled. -# -if [ "${ZEVENT_SUBCLASS}" = "scrub.finish" ]; then - healthy="$("${ZPOOL}" status -x "${ZEVENT_POOL}" \ - | grep "'${ZEVENT_POOL}' is healthy")" - [ -n "${healthy}" ] && [ "${ZED_EMAIL_VERBOSE}" -eq 0 ] && exit 3 -fi - -umask 077 -email_subject="ZFS ${ZEVENT_SUBCLASS} event for ${ZEVENT_POOL} on $(hostname)" -email_pathname="${TMPDIR:="/tmp"}/$(basename -- "$0").${ZEVENT_EID}.$$" -cat > "${email_pathname}" < "${note_pathname}" + +zed_notify "${note_subject}" "${note_pathname}"; rv=$? +rm -f "${note_pathname}" +exit "${rv}" diff --git a/cmd/zed/zed.d/zed-functions.sh b/cmd/zed/zed.d/zed-functions.sh index b42911b2ee48..14909d38cb54 100644 --- a/cmd/zed/zed.d/zed-functions.sh +++ b/cmd/zed/zed.d/zed-functions.sh @@ -1,230 +1,302 @@ # zed-functions.sh # # ZED helper functions for use in ZEDLETs # Variable Defaults # -: "${ZED_EMAIL_INTERVAL_SECS:=3600}" -: "${ZED_EMAIL_VERBOSE:=0}" : "${ZED_LOCKDIR:="/var/lock"}" +: "${ZED_NOTIFY_INTERVAL_SECS:=3600}" +: "${ZED_NOTIFY_VERBOSE:=0}" : "${ZED_RUNDIR:="/var/run"}" : "${ZED_SYSLOG_PRIORITY:="daemon.notice"}" : "${ZED_SYSLOG_TAG:="zed"}" ZED_FLOCK_FD=8 # zed_check_cmd (cmd, ...) # # For each argument given, search PATH for the executable command [cmd]. # Log a message if [cmd] is not found. # # Arguments # cmd: name of executable command for which to search # # Return # 0 if all commands are found in PATH and are executable # n for a count of the command executables that are not found # zed_check_cmd() { local cmd local rv=0 for cmd; do if ! command -v "${cmd}" >/dev/null 2>&1; then zed_log_err "\"${cmd}\" not installed" rv=$((rv + 1)) fi done return "${rv}" } # zed_log_msg (msg, ...) # # Write all argument strings to the system log. # # Globals # ZED_SYSLOG_PRIORITY # ZED_SYSLOG_TAG # # Return # nothing # zed_log_msg() { logger -p "${ZED_SYSLOG_PRIORITY}" -t "${ZED_SYSLOG_TAG}" -- "$@" } # zed_log_err (msg, ...) # # Write an error message to the system log. This message will contain the # script name, EID, and all argument strings. # # Globals # ZED_SYSLOG_PRIORITY # ZED_SYSLOG_TAG # ZEVENT_EID # # Return # nothing # zed_log_err() { logger -p "${ZED_SYSLOG_PRIORITY}" -t "${ZED_SYSLOG_TAG}" -- "error:" \ "$(basename -- "$0"):" "${ZEVENT_EID:+"eid=${ZEVENT_EID}:"}" "$@" } # zed_lock (lockfile, [fd]) # # Obtain an exclusive (write) lock on [lockfile]. If the lock cannot be # immediately acquired, wait until it becomes available. # # Every zed_lock() must be paired with a corresponding zed_unlock(). # # By default, flock-style locks associate the lockfile with file descriptor 8. # The bash manpage warns that file descriptors >9 should be used with care as # they may conflict with file descriptors used internally by the shell. File # descriptor 9 is reserved for zed_rate_limit(). If concurrent locks are held # within the same process, they must use different file descriptors (preferably # decrementing from 8); otherwise, obtaining a new lock with a given file # descriptor will release the previous lock associated with that descriptor. # # Arguments # lockfile: pathname of the lock file; the lock will be stored in # ZED_LOCKDIR unless the pathname contains a "/". # fd: integer for the file descriptor used by flock (OPTIONAL unless holding # concurrent locks) # # Globals # ZED_FLOCK_FD # ZED_LOCKDIR # # Return # nothing # zed_lock() { local lockfile="$1" local fd="${2:-${ZED_FLOCK_FD}}" local umask_bak local err [ -n "${lockfile}" ] || return if ! expr "${lockfile}" : '.*/' >/dev/null 2>&1; then lockfile="${ZED_LOCKDIR}/${lockfile}" fi umask_bak="$(umask)" umask 077 # Obtain a lock on the file bound to the given file descriptor. # eval "exec ${fd}> '${lockfile}'" err="$(flock --exclusive "${fd}" 2>&1)" if [ $? -ne 0 ]; then zed_log_err "failed to lock \"${lockfile}\": ${err}" fi umask "${umask_bak}" } # zed_unlock (lockfile, [fd]) # # Release the lock on [lockfile]. # # Arguments # lockfile: pathname of the lock file # fd: integer for the file descriptor used by flock (must match the file # descriptor passed to the zed_lock function call) # # Globals # ZED_FLOCK_FD # ZED_LOCKDIR # # Return # nothing # zed_unlock() { local lockfile="$1" local fd="${2:-${ZED_FLOCK_FD}}" local err [ -n "${lockfile}" ] || return if ! expr "${lockfile}" : '.*/' >/dev/null 2>&1; then lockfile="${ZED_LOCKDIR}/${lockfile}" fi # Release the lock and close the file descriptor. # err="$(flock --unlock "${fd}" 2>&1)" if [ $? -ne 0 ]; then zed_log_err "failed to unlock \"${lockfile}\": ${err}" fi eval "exec ${fd}>&-" } +# zed_notify (subject, pathname) +# +# Send a notification via all available methods. +# +# Arguments +# subject: notification subject +# pathname: pathname containing the notification message (OPTIONAL) +# +# Return +# 0: notification succeeded via at least one method +# 1: notification failed +# 2: no notification methods configured +# +zed_notify() +{ + local subject="$1" + local pathname="$2" + local num_success=0 + local num_failure=0 + + zed_notify_email "${subject}" "${pathname}"; rv=$? + [ "${rv}" -eq 0 ] && num_success=$((num_success + 1)) + [ "${rv}" -eq 1 ] && num_failure=$((num_failure + 1)) + + [ "${num_success}" -gt 0 ] && return 0 + [ "${num_failure}" -gt 0 ] && return 1 + return 2 +} + + +# zed_notify_email (subject, pathname) +# +# Send a notification via email to the address specified by ZED_EMAIL. +# +# Requires the mail executable to be installed in the standard PATH. +# +# Arguments +# subject: notification subject +# pathname: pathname containing the notification message (OPTIONAL) +# +# Globals +# ZED_EMAIL +# +# Return +# 0: notification sent +# 1: notification failed +# 2: not configured +# +zed_notify_email() +{ + local subject="$1" + local pathname="${2:-"/dev/null"}" + + [ -n "${ZED_EMAIL}" ] || return 2 + + [ -n "${subject}" ] || return 1 + if [ ! -r "${pathname}" ]; then + zed_log_err "mail cannot read \"${pathname}\"" + return 1 + fi + + zed_check_cmd "mail" || return 1 + + mail -s "${subject}" "${ZED_EMAIL}" < "${pathname}" >/dev/null 2>&1; rv=$? + if [ "${rv}" -ne 0 ]; then + zed_log_err "mail exit=${rv}" + return 1 + fi + return 0 +} + + # zed_rate_limit (tag, [interval]) # # Check whether an event of a given type [tag] has already occurred within the # last [interval] seconds. # # This function obtains a lock on the statefile using file descriptor 9. # # Arguments # tag: arbitrary string for grouping related events to rate-limit # interval: time interval in seconds (OPTIONAL) # # Globals -# ZED_EMAIL_INTERVAL_SECS +# ZED_NOTIFY_INTERVAL_SECS # ZED_RUNDIR # # Return # 0 if the event should be processed # 1 if the event should be dropped # # State File Format # time;tag # zed_rate_limit() { local tag="$1" - local interval="${2:-${ZED_EMAIL_INTERVAL_SECS}}" + local interval="${2:-${ZED_NOTIFY_INTERVAL_SECS}}" local lockfile="zed.zedlet.state.lock" local lockfile_fd=9 local statefile="${ZED_RUNDIR}/zed.zedlet.state" local time_now local time_prev local umask_bak local rv=0 [ -n "${tag}" ] || return 0 zed_lock "${lockfile}" "${lockfile_fd}" time_now="$(date +%s)" time_prev="$(egrep "^[0-9]+;${tag}\$" "${statefile}" 2>/dev/null \ | tail -1 | cut -d\; -f1)" if [ -n "${time_prev}" ] \ && [ "$((time_now - time_prev))" -lt "${interval}" ]; then rv=1 else umask_bak="$(umask)" umask 077 egrep -v "^[0-9]+;${tag}\$" "${statefile}" 2>/dev/null \ > "${statefile}.$$" echo "${time_now};${tag}" >> "${statefile}.$$" mv -f "${statefile}.$$" "${statefile}" umask "${umask_bak}" fi zed_unlock "${lockfile}" "${lockfile_fd}" return "${rv}" } diff --git a/cmd/zed/zed.d/zed.rc b/cmd/zed/zed.d/zed.rc index 4c53207d74dc..05f84c877304 100644 --- a/cmd/zed/zed.d/zed.rc +++ b/cmd/zed/zed.d/zed.rc @@ -1,60 +1,60 @@ ## # zed.rc ## ## # Absolute path to the debug output file. # #ZED_DEBUG_LOG="/tmp/zed.debug.log" ## -# Email address of the zpool administrator. +# Email address of the zpool administrator for receipt of notifications. # Email will only be sent if ZED_EMAIL is defined. # Disabled by default; uncomment to enable. # #ZED_EMAIL="root" ## -# Minimum number of seconds between emails for a similar event. +# Default directory for zed lock files. # -#ZED_EMAIL_INTERVAL_SECS=3600 +#ZED_LOCKDIR="/var/lock" ## -# Email verbosity. -# If set to 0, suppress email if the pool is healthy. -# If set to 1, send email regardless of pool health. +# Minimum number of seconds between notifications for a similar event. # -#ZED_EMAIL_VERBOSE=0 +#ZED_NOTIFY_INTERVAL_SECS=3600 ## -# Default directory for zed lock files. +# Notification verbosity. +# If set to 0, suppress notification if the pool is healthy. +# If set to 1, send notification regardless of pool health. # -#ZED_LOCKDIR="/var/lock" +#ZED_NOTIFY_VERBOSE=0 ## # Default directory for zed state files. # #ZED_RUNDIR="/var/run" ## # Replace a device with a hot spare after N checksum errors are detected. # Disabled by default; uncomment to enable. # #ZED_SPARE_ON_CHECKSUM_ERRORS=10 ## # Replace a device with a hot spare after N I/O errors are detected. # Disabled by default; uncomment to enable. # #ZED_SPARE_ON_IO_ERRORS=1 ## # The syslog priority (e.g., specified as a "facility.level" pair). # #ZED_SYSLOG_PRIORITY="daemon.notice" ## # The syslog tag for marking zed events. # #ZED_SYSLOG_TAG="zed"