Path: blob/main/sys/contrib/openzfs/cmd/zed/zed.d/zed-functions.sh
48529 views
#!/bin/sh1# shellcheck disable=SC2154,SC30432# zed-functions.sh3#4# ZED helper functions for use in ZEDLETs567# Variable Defaults8#9: "${ZED_LOCKDIR:="/var/lock"}"10: "${ZED_NOTIFY_INTERVAL_SECS:=3600}"11: "${ZED_NOTIFY_VERBOSE:=0}"12: "${ZED_RUNDIR:="/var/run"}"13: "${ZED_SYSLOG_PRIORITY:="daemon.notice"}"14: "${ZED_SYSLOG_TAG:="zed"}"1516ZED_FLOCK_FD=8171819# zed_check_cmd (cmd, ...)20#21# For each argument given, search PATH for the executable command [cmd].22# Log a message if [cmd] is not found.23#24# Arguments25# cmd: name of executable command for which to search26#27# Return28# 0 if all commands are found in PATH and are executable29# n for a count of the command executables that are not found30#31zed_check_cmd()32{33local cmd34local rv=03536for cmd; do37if ! command -v "${cmd}" >/dev/null 2>&1; then38zed_log_err "\"${cmd}\" not installed"39rv=$((rv + 1))40fi41done42return "${rv}"43}444546# zed_log_msg (msg, ...)47#48# Write all argument strings to the system log.49#50# Globals51# ZED_SYSLOG_PRIORITY52# ZED_SYSLOG_TAG53#54# Return55# nothing56#57zed_log_msg()58{59logger -p "${ZED_SYSLOG_PRIORITY}" -t "${ZED_SYSLOG_TAG}" -- "$@"60}616263# zed_log_err (msg, ...)64#65# Write an error message to the system log. This message will contain the66# script name, EID, and all argument strings.67#68# Globals69# ZED_SYSLOG_PRIORITY70# ZED_SYSLOG_TAG71# ZEVENT_EID72#73# Return74# nothing75#76zed_log_err()77{78zed_log_msg "error: ${0##*/}:""${ZEVENT_EID:+" eid=${ZEVENT_EID}:"}" "$@"79}808182# zed_lock (lockfile, [fd])83#84# Obtain an exclusive (write) lock on [lockfile]. If the lock cannot be85# immediately acquired, wait until it becomes available.86#87# Every zed_lock() must be paired with a corresponding zed_unlock().88#89# By default, flock-style locks associate the lockfile with file descriptor 8.90# The bash manpage warns that file descriptors >9 should be used with care as91# they may conflict with file descriptors used internally by the shell. File92# descriptor 9 is reserved for zed_rate_limit(). If concurrent locks are held93# within the same process, they must use different file descriptors (preferably94# decrementing from 8); otherwise, obtaining a new lock with a given file95# descriptor will release the previous lock associated with that descriptor.96#97# Arguments98# lockfile: pathname of the lock file; the lock will be stored in99# ZED_LOCKDIR unless the pathname contains a "/".100# fd: integer for the file descriptor used by flock (OPTIONAL unless holding101# concurrent locks)102#103# Globals104# ZED_FLOCK_FD105# ZED_LOCKDIR106#107# Return108# nothing109#110zed_lock()111{112local lockfile="$1"113local fd="${2:-${ZED_FLOCK_FD}}"114local umask_bak115local err116117[ -n "${lockfile}" ] || return118if ! expr "${lockfile}" : '.*/' >/dev/null 2>&1; then119lockfile="${ZED_LOCKDIR}/${lockfile}"120fi121122umask_bak="$(umask)"123umask 077124125# Obtain a lock on the file bound to the given file descriptor.126#127eval "exec ${fd}>> '${lockfile}'"128if ! err="$(flock --exclusive "${fd}" 2>&1)"; then129zed_log_err "failed to lock \"${lockfile}\": ${err}"130fi131132umask "${umask_bak}"133}134135136# zed_unlock (lockfile, [fd])137#138# Release the lock on [lockfile].139#140# Arguments141# lockfile: pathname of the lock file142# fd: integer for the file descriptor used by flock (must match the file143# descriptor passed to the zed_lock function call)144#145# Globals146# ZED_FLOCK_FD147# ZED_LOCKDIR148#149# Return150# nothing151#152zed_unlock()153{154local lockfile="$1"155local fd="${2:-${ZED_FLOCK_FD}}"156local err157158[ -n "${lockfile}" ] || return159if ! expr "${lockfile}" : '.*/' >/dev/null 2>&1; then160lockfile="${ZED_LOCKDIR}/${lockfile}"161fi162163# Release the lock and close the file descriptor.164if ! err="$(flock --unlock "${fd}" 2>&1)"; then165zed_log_err "failed to unlock \"${lockfile}\": ${err}"166fi167eval "exec ${fd}>&-"168}169170171# zed_notify (subject, pathname)172#173# Send a notification via all available methods.174#175# Arguments176# subject: notification subject177# pathname: pathname containing the notification message (OPTIONAL)178#179# Return180# 0: notification succeeded via at least one method181# 1: notification failed182# 2: no notification methods configured183#184zed_notify()185{186local subject="$1"187local pathname="$2"188local num_success=0189local num_failure=0190191zed_notify_email "${subject}" "${pathname}"; rv=$?192[ "${rv}" -eq 0 ] && num_success=$((num_success + 1))193[ "${rv}" -eq 1 ] && num_failure=$((num_failure + 1))194195zed_notify_pushbullet "${subject}" "${pathname}"; rv=$?196[ "${rv}" -eq 0 ] && num_success=$((num_success + 1))197[ "${rv}" -eq 1 ] && num_failure=$((num_failure + 1))198199zed_notify_slack_webhook "${subject}" "${pathname}"; rv=$?200[ "${rv}" -eq 0 ] && num_success=$((num_success + 1))201[ "${rv}" -eq 1 ] && num_failure=$((num_failure + 1))202203zed_notify_pushover "${subject}" "${pathname}"; rv=$?204[ "${rv}" -eq 0 ] && num_success=$((num_success + 1))205[ "${rv}" -eq 1 ] && num_failure=$((num_failure + 1))206207zed_notify_ntfy "${subject}" "${pathname}"; rv=$?208[ "${rv}" -eq 0 ] && num_success=$((num_success + 1))209[ "${rv}" -eq 1 ] && num_failure=$((num_failure + 1))210211zed_notify_gotify "${subject}" "${pathname}"; rv=$?212[ "${rv}" -eq 0 ] && num_success=$((num_success + 1))213[ "${rv}" -eq 1 ] && num_failure=$((num_failure + 1))214215[ "${num_success}" -gt 0 ] && return 0216[ "${num_failure}" -gt 0 ] && return 1217return 2218}219220221# zed_notify_email (subject, pathname)222#223# Send a notification via email to the address specified by ZED_EMAIL_ADDR.224#225# Requires the mail executable to be installed in the standard PATH, or226# ZED_EMAIL_PROG to be defined with the pathname of an executable capable of227# reading a message body from stdin.228#229# Command-line options to the mail executable can be specified in230# ZED_EMAIL_OPTS. This undergoes the following keyword substitutions:231# - @ADDRESS@ is replaced with the space-delimited recipient email address(es)232# - @SUBJECT@ is replaced with the notification subject233# If @SUBJECT@ was omited here, a "Subject: ..." header will be added to notification234#235#236# Arguments237# subject: notification subject238# pathname: pathname containing the notification message (OPTIONAL)239#240# Globals241# ZED_EMAIL_PROG242# ZED_EMAIL_OPTS243# ZED_EMAIL_ADDR244#245# Return246# 0: notification sent247# 1: notification failed248# 2: not configured249#250zed_notify_email()251{252local subject="${1:-"ZED notification"}"253local pathname="${2:-"/dev/null"}"254255: "${ZED_EMAIL_PROG:="mail"}"256: "${ZED_EMAIL_OPTS:="-s '@SUBJECT@' @ADDRESS@"}"257258# For backward compatibility with ZED_EMAIL.259if [ -n "${ZED_EMAIL}" ] && [ -z "${ZED_EMAIL_ADDR}" ]; then260ZED_EMAIL_ADDR="${ZED_EMAIL}"261fi262[ -n "${ZED_EMAIL_ADDR}" ] || return 2263264zed_check_cmd "${ZED_EMAIL_PROG}" || return 1265266[ -n "${subject}" ] || return 1267if [ ! -r "${pathname}" ]; then268zed_log_err \269"${ZED_EMAIL_PROG##*/} cannot read \"${pathname}\""270return 1271fi272273# construct cmdline options274ZED_EMAIL_OPTS_PARSED="$(echo "${ZED_EMAIL_OPTS}" \275| sed -e "s/@ADDRESS@/${ZED_EMAIL_ADDR}/g" \276-e "s/@SUBJECT@/${subject}/g")"277278# pipe message to email prog279# shellcheck disable=SC2086,SC2248280{281# no subject passed as option?282if [ "${ZED_EMAIL_OPTS%@SUBJECT@*}" = "${ZED_EMAIL_OPTS}" ] ; then283# inject subject header284printf "Subject: %s\n" "${subject}"285# The following empty line is needed to separate the header from the286# body of the message. Otherwise programs like sendmail will skip287# everything up to the first empty line (or wont send an email at288# all) and will still exit with exit code 0289printf "\n"290fi291# output message292cat "${pathname}"293} |294eval ${ZED_EMAIL_PROG} ${ZED_EMAIL_OPTS_PARSED} >/dev/null 2>&1295rv=$?296if [ "${rv}" -ne 0 ]; then297zed_log_err "${ZED_EMAIL_PROG##*/} exit=${rv}"298return 1299fi300return 0301}302303304# zed_notify_pushbullet (subject, pathname)305#306# Send a notification via Pushbullet <https://www.pushbullet.com/>.307# The access token (ZED_PUSHBULLET_ACCESS_TOKEN) identifies this client to the308# Pushbullet server. The optional channel tag (ZED_PUSHBULLET_CHANNEL_TAG) is309# for pushing to notification feeds that can be subscribed to; if a channel is310# not defined, push notifications will instead be sent to all devices311# associated with the account specified by the access token.312#313# Requires awk, curl, and sed executables to be installed in the standard PATH.314#315# References316# https://docs.pushbullet.com/317# https://www.pushbullet.com/security318#319# Arguments320# subject: notification subject321# pathname: pathname containing the notification message (OPTIONAL)322#323# Globals324# ZED_PUSHBULLET_ACCESS_TOKEN325# ZED_PUSHBULLET_CHANNEL_TAG326#327# Return328# 0: notification sent329# 1: notification failed330# 2: not configured331#332zed_notify_pushbullet()333{334local subject="$1"335local pathname="${2:-"/dev/null"}"336local msg_body337local msg_tag338local msg_json339local msg_out340local msg_err341local url="https://api.pushbullet.com/v2/pushes"342343[ -n "${ZED_PUSHBULLET_ACCESS_TOKEN}" ] || return 2344345[ -n "${subject}" ] || return 1346if [ ! -r "${pathname}" ]; then347zed_log_err "pushbullet cannot read \"${pathname}\""348return 1349fi350351zed_check_cmd "awk" "curl" "sed" || return 1352353# Escape the following characters in the message body for JSON:354# newline, backslash, double quote, horizontal tab, vertical tab,355# and carriage return.356#357msg_body="$(awk '{ ORS="\\n" } { gsub(/\\/, "\\\\"); gsub(/"/, "\\\"");358gsub(/\t/, "\\t"); gsub(/\f/, "\\f"); gsub(/\r/, "\\r"); print }' \359"${pathname}")"360361# Push to a channel if one is configured.362#363[ -n "${ZED_PUSHBULLET_CHANNEL_TAG}" ] && msg_tag="$(printf \364'"channel_tag": "%s", ' "${ZED_PUSHBULLET_CHANNEL_TAG}")"365366# Construct the JSON message for pushing a note.367#368msg_json="$(printf '{%s"type": "note", "title": "%s", "body": "%s"}' \369"${msg_tag}" "${subject}" "${msg_body}")"370371# Send the POST request and check for errors.372#373msg_out="$(curl -u "${ZED_PUSHBULLET_ACCESS_TOKEN}:" -X POST "${url}" \374--header "Content-Type: application/json" --data-binary "${msg_json}" \3752>/dev/null)"; rv=$?376if [ "${rv}" -ne 0 ]; then377zed_log_err "curl exit=${rv}"378return 1379fi380msg_err="$(echo "${msg_out}" \381| sed -n -e 's/.*"error" *:.*"message" *: *"\([^"]*\)".*/\1/p')"382if [ -n "${msg_err}" ]; then383zed_log_err "pushbullet \"${msg_err}"\"384return 1385fi386return 0387}388389390# zed_notify_slack_webhook (subject, pathname)391#392# Notification via Slack Webhook <https://api.slack.com/incoming-webhooks>.393# The Webhook URL (ZED_SLACK_WEBHOOK_URL) identifies this client to the394# Slack channel.395#396# Requires awk, curl, and sed executables to be installed in the standard PATH.397#398# References399# https://api.slack.com/incoming-webhooks400#401# Arguments402# subject: notification subject403# pathname: pathname containing the notification message (OPTIONAL)404#405# Globals406# ZED_SLACK_WEBHOOK_URL407#408# Return409# 0: notification sent410# 1: notification failed411# 2: not configured412#413zed_notify_slack_webhook()414{415[ -n "${ZED_SLACK_WEBHOOK_URL}" ] || return 2416417local subject="$1"418local pathname="${2:-"/dev/null"}"419local msg_body420local msg_tag421local msg_json422local msg_out423local msg_err424local url="${ZED_SLACK_WEBHOOK_URL}"425426[ -n "${subject}" ] || return 1427if [ ! -r "${pathname}" ]; then428zed_log_err "slack webhook cannot read \"${pathname}\""429return 1430fi431432zed_check_cmd "awk" "curl" "sed" || return 1433434# Escape the following characters in the message body for JSON:435# newline, backslash, double quote, horizontal tab, vertical tab,436# and carriage return.437#438msg_body="$(awk '{ ORS="\\n" } { gsub(/\\/, "\\\\"); gsub(/"/, "\\\"");439gsub(/\t/, "\\t"); gsub(/\f/, "\\f"); gsub(/\r/, "\\r"); print }' \440"${pathname}")"441442# Construct the JSON message for posting.443# shellcheck disable=SC2016444#445msg_json="$(printf '{"text": "*%s*\\n```%s```"}' "${subject}" "${msg_body}" )"446447# Send the POST request and check for errors.448#449msg_out="$(curl -X POST "${url}" \450--header "Content-Type: application/json" --data-binary "${msg_json}" \4512>/dev/null)"; rv=$?452if [ "${rv}" -ne 0 ]; then453zed_log_err "curl exit=${rv}"454return 1455fi456msg_err="$(echo "${msg_out}" \457| sed -n -e 's/.*"error" *:.*"message" *: *"\([^"]*\)".*/\1/p')"458if [ -n "${msg_err}" ]; then459zed_log_err "slack webhook \"${msg_err}"\"460return 1461fi462return 0463}464465# zed_notify_pushover (subject, pathname)466#467# Send a notification via Pushover <https://pushover.net/>.468# The access token (ZED_PUSHOVER_TOKEN) identifies this client to the469# Pushover server. The user token (ZED_PUSHOVER_USER) defines the user or470# group to which the notification will be sent.471#472# Requires curl and sed executables to be installed in the standard PATH.473#474# References475# https://pushover.net/api476#477# Arguments478# subject: notification subject479# pathname: pathname containing the notification message (OPTIONAL)480#481# Globals482# ZED_PUSHOVER_TOKEN483# ZED_PUSHOVER_USER484#485# Return486# 0: notification sent487# 1: notification failed488# 2: not configured489#490zed_notify_pushover()491{492local subject="$1"493local pathname="${2:-"/dev/null"}"494local msg_body495local msg_out496local msg_err497local url="https://api.pushover.net/1/messages.json"498499[ -n "${ZED_PUSHOVER_TOKEN}" ] && [ -n "${ZED_PUSHOVER_USER}" ] || return 2500501if [ ! -r "${pathname}" ]; then502zed_log_err "pushover cannot read \"${pathname}\""503return 1504fi505506zed_check_cmd "curl" "sed" || return 1507508# Read the message body in.509#510msg_body="$(cat "${pathname}")"511512if [ -z "${msg_body}" ]513then514msg_body=$subject515subject=""516fi517518# Send the POST request and check for errors.519#520msg_out="$( \521curl \522--form-string "token=${ZED_PUSHOVER_TOKEN}" \523--form-string "user=${ZED_PUSHOVER_USER}" \524--form-string "message=${msg_body}" \525--form-string "title=${subject}" \526"${url}" \5272>/dev/null \528)"; rv=$?529if [ "${rv}" -ne 0 ]; then530zed_log_err "curl exit=${rv}"531return 1532fi533msg_err="$(echo "${msg_out}" \534| sed -n -e 's/.*"errors" *:.*\[\(.*\)\].*/\1/p')"535if [ -n "${msg_err}" ]; then536zed_log_err "pushover \"${msg_err}"\"537return 1538fi539return 0540}541542543# zed_notify_ntfy (subject, pathname)544#545# Send a notification via Ntfy.sh <https://ntfy.sh/>.546# The ntfy topic (ZED_NTFY_TOPIC) identifies the topic that the notification547# will be sent to Ntfy.sh server. The ntfy url (ZED_NTFY_URL) defines the548# self-hosted or provided hosted ntfy service location. The ntfy access token549# <https://docs.ntfy.sh/publish/#access-tokens> (ZED_NTFY_ACCESS_TOKEN) reprsents an550# access token that could be used if a topic is read/write protected. If a551# topic can be written to publicaly, a ZED_NTFY_ACCESS_TOKEN is not required.552#553# Requires curl and sed executables to be installed in the standard PATH.554#555# References556# https://docs.ntfy.sh557#558# Arguments559# subject: notification subject560# pathname: pathname containing the notification message (OPTIONAL)561#562# Globals563# ZED_NTFY_TOPIC564# ZED_NTFY_ACCESS_TOKEN (OPTIONAL)565# ZED_NTFY_URL566#567# Return568# 0: notification sent569# 1: notification failed570# 2: not configured571#572zed_notify_ntfy()573{574local subject="$1"575local pathname="${2:-"/dev/null"}"576local msg_body577local msg_out578local msg_err579580[ -n "${ZED_NTFY_TOPIC}" ] || return 2581local url="${ZED_NTFY_URL:-"https://ntfy.sh"}/${ZED_NTFY_TOPIC}"582583if [ ! -r "${pathname}" ]; then584zed_log_err "ntfy cannot read \"${pathname}\""585return 1586fi587588zed_check_cmd "curl" "sed" || return 1589590# Read the message body in.591#592msg_body="$(cat "${pathname}")"593594if [ -z "${msg_body}" ]595then596msg_body=$subject597subject=""598fi599600# Send the POST request and check for errors.601#602if [ -n "${ZED_NTFY_ACCESS_TOKEN}" ]; then603msg_out="$( \604curl \605-u ":${ZED_NTFY_ACCESS_TOKEN}" \606-H "Title: ${subject}" \607-d "${msg_body}" \608-H "Priority: high" \609"${url}" \6102>/dev/null \611)"; rv=$?612else613msg_out="$( \614curl \615-H "Title: ${subject}" \616-d "${msg_body}" \617-H "Priority: high" \618"${url}" \6192>/dev/null \620)"; rv=$?621fi622if [ "${rv}" -ne 0 ]; then623zed_log_err "curl exit=${rv}"624return 1625fi626msg_err="$(echo "${msg_out}" \627| sed -n -e 's/.*"errors" *:.*\[\(.*\)\].*/\1/p')"628if [ -n "${msg_err}" ]; then629zed_log_err "ntfy \"${msg_err}"\"630return 1631fi632return 0633}634635636# zed_notify_gotify (subject, pathname)637#638# Send a notification via Gotify <https://gotify.net/>.639# The Gotify URL (ZED_GOTIFY_URL) defines a self-hosted Gotify location.640# The Gotify application token (ZED_GOTIFY_APPTOKEN) defines a641# Gotify application token which is associated with a message.642# The optional Gotify priority value (ZED_GOTIFY_PRIORITY) overrides the643# default or configured priority at the Gotify server for the application.644#645# Requires curl and sed executables to be installed in the standard PATH.646#647# References648# https://gotify.net/docs/index649#650# Arguments651# subject: notification subject652# pathname: pathname containing the notification message (OPTIONAL)653#654# Globals655# ZED_GOTIFY_URL656# ZED_GOTIFY_APPTOKEN657# ZED_GOTIFY_PRIORITY658#659# Return660# 0: notification sent661# 1: notification failed662# 2: not configured663#664zed_notify_gotify()665{666local subject="$1"667local pathname="${2:-"/dev/null"}"668local msg_body669local msg_out670local msg_err671672[ -n "${ZED_GOTIFY_URL}" ] && [ -n "${ZED_GOTIFY_APPTOKEN}" ] || return 2673local url="${ZED_GOTIFY_URL}/message?token=${ZED_GOTIFY_APPTOKEN}"674675if [ ! -r "${pathname}" ]; then676zed_log_err "gotify cannot read \"${pathname}\""677return 1678fi679680zed_check_cmd "curl" "sed" || return 1681682# Read the message body in.683#684msg_body="$(cat "${pathname}")"685686if [ -z "${msg_body}" ]687then688msg_body=$subject689subject=""690fi691692# Send the POST request and check for errors.693#694if [ -n "${ZED_GOTIFY_PRIORITY}" ]; then695msg_out="$( \696curl \697--form-string "title=${subject}" \698--form-string "message=${msg_body}" \699--form-string "priority=${ZED_GOTIFY_PRIORITY}" \700"${url}" \7012>/dev/null \702)"; rv=$?703else704msg_out="$( \705curl \706--form-string "title=${subject}" \707--form-string "message=${msg_body}" \708"${url}" \7092>/dev/null \710)"; rv=$?711fi712713if [ "${rv}" -ne 0 ]; then714zed_log_err "curl exit=${rv}"715return 1716fi717msg_err="$(echo "${msg_out}" \718| sed -n -e 's/.*"errors" *:.*\[\(.*\)\].*/\1/p')"719if [ -n "${msg_err}" ]; then720zed_log_err "gotify \"${msg_err}"\"721return 1722fi723return 0724}725726727728# zed_rate_limit (tag, [interval])729#730# Check whether an event of a given type [tag] has already occurred within the731# last [interval] seconds.732#733# This function obtains a lock on the statefile using file descriptor 9.734#735# Arguments736# tag: arbitrary string for grouping related events to rate-limit737# interval: time interval in seconds (OPTIONAL)738#739# Globals740# ZED_NOTIFY_INTERVAL_SECS741# ZED_RUNDIR742#743# Return744# 0 if the event should be processed745# 1 if the event should be dropped746#747# State File Format748# time;tag749#750zed_rate_limit()751{752local tag="$1"753local interval="${2:-${ZED_NOTIFY_INTERVAL_SECS}}"754local lockfile="zed.zedlet.state.lock"755local lockfile_fd=9756local statefile="${ZED_RUNDIR}/zed.zedlet.state"757local time_now758local time_prev759local umask_bak760local rv=0761762[ -n "${tag}" ] || return 0763764zed_lock "${lockfile}" "${lockfile_fd}"765time_now="$(date +%s)"766time_prev="$(grep -E "^[0-9]+;${tag}\$" "${statefile}" 2>/dev/null \767| tail -1 | cut -d\; -f1)"768769if [ -n "${time_prev}" ] \770&& [ "$((time_now - time_prev))" -lt "${interval}" ]; then771rv=1772else773umask_bak="$(umask)"774umask 077775grep -E -v "^[0-9]+;${tag}\$" "${statefile}" 2>/dev/null \776> "${statefile}.$$"777echo "${time_now};${tag}" >> "${statefile}.$$"778mv -f "${statefile}.$$" "${statefile}"779umask "${umask_bak}"780fi781782zed_unlock "${lockfile}" "${lockfile_fd}"783return "${rv}"784}785786787# zed_guid_to_pool (guid)788#789# Convert a pool GUID into its pool name (like "tank")790# Arguments791# guid: pool GUID (decimal or hex)792#793# Return794# Pool name795#796zed_guid_to_pool()797{798if [ -z "$1" ] ; then799return800fi801802guid="$(printf "%u" "$1")"803$ZPOOL get -H -ovalue,name guid | awk '$1 == '"$guid"' {print $2; exit}'804}805806# zed_exit_if_ignoring_this_event807#808# Exit the script if we should ignore this event, as determined by809# $ZED_SYSLOG_SUBCLASS_INCLUDE and $ZED_SYSLOG_SUBCLASS_EXCLUDE in zed.rc.810# This function assumes you've imported the normal zed variables.811zed_exit_if_ignoring_this_event()812{813if [ -n "${ZED_SYSLOG_SUBCLASS_INCLUDE}" ]; then814eval "case ${ZEVENT_SUBCLASS} in815${ZED_SYSLOG_SUBCLASS_INCLUDE});;816*) exit 0;;817esac"818elif [ -n "${ZED_SYSLOG_SUBCLASS_EXCLUDE}" ]; then819eval "case ${ZEVENT_SUBCLASS} in820${ZED_SYSLOG_SUBCLASS_EXCLUDE}) exit 0;;821*);;822esac"823fi824}825826827