0

I've been attempting to implement an alert script for Zabbix. Zabbix attempts to run the script in Shell for some reason, whilst the script is written in Bash.

#!/bin/bash

# Slack incoming web-hook URL and user name
url='https://hooks.slack.com/services/this/is/my/webhook/'             # example: https://hooks.slack.com/services/QW3R7Y/D34DC0D3/BCADFGabcDEF123
username='Zabbix Notification System'

## Values received by this script:
# To = $1 (Slack channel or user to send the message to, specified in the Zabbix web interface; "@username" or "#channel")
# Subject = $2 (usually either PROBLEM or RECOVERY/OK)
# Message = $3 (whatever message the Zabbix action sends, preferably something like "Zabbix server is unreachable for 5 minutes - Zabbix server (127.0.0.1)")

# Get the Slack channel or user ($1) and Zabbix subject ($2 - hopefully either PROBLEM or RECOVERY/OK)
to="$1"
subject="$2"

# Change message emoji depending on the subject - smile (RECOVERY/OK), frowning (PROBLEM), or ghost (for everything else)
recoversub='^RECOVER(Y|ED)?$'
if [[ "$subject" =~ ${recoversub} ]]; then
        emoji=':smile:'
elif [ "$subject" == 'OK' ]; then
        emoji=':smile:'
elif [ "$subject" == 'PROBLEM' ]; then
        emoji=':frowning:'
else
        emoji=':ghost:'
fi

# The message that we want to send to Slack is the "subject" value ($2 / $subject - that we got earlier)
#  followed by the message that Zabbix actually sent us ($3)
message="${subject}: $3"

# Build our JSON payload and send it as a POST request to the Slack incoming web-hook URL
payload="payload={\"channel\": \"${to//\"/\\\"}\", \"username\": \"${username//\"/\\\"}\", \"text\": \"${message//\"/\\\"}\", \"icon_emoji\": \"${emoji}\"}"
curl -m 5 --data-urlencode "${payload}" $url -A "https://hooks.slack.com/services/this/is/my/web/hook"
~

When I run the script locally using 'bash slack.sh' it sends an empty notification, which I recieve in Slack. When I run the script locally using 'sh slack.sh' I get the following error.

slack.sh: 19: slack.sh: [[: not found
slack.sh: 21: [: unexpected operator
slack.sh: 23: [: unexpected operator
slack.sh: 34: slack.sh: Bad substitution

Thanks for the assistance.

6
  • If Zabbix expects a POSIX shell script, then you have to write a POSIX shell script, and [[ isn't defined by POSIX. Whether or not you can configure Zabbix to use a different shell is another question. (If Zabbix just expects an executable, then @bishop has the answer.) Commented Mar 19, 2018 at 13:43
  • (@bishop deleted his comment, which suggested using #!/bin/bash instead of # !/bin/bash.) Commented Mar 19, 2018 at 13:44
  • According to the Zabbix website; "Regular expression support in Zabbix has been switched from POSIX extended regular expressions to Perl Compatible Regular Expressions (PCRE) for enhanced regular expressions and consistency with the frontend." I've already considered (and tried) removing the '[[' and replacing it by a single '[', but that was to no avail. Commented Mar 19, 2018 at 13:51
  • 2
    I don't think regular expression support in Zabbix is relevant; this is a shell script, and either you are using bash, in which case =~ expects a POSIX regular expression, or the script is executed by /bin/sh (a POSIX-compliant shell) and doesn't support regular expression matching at all. Commented Mar 19, 2018 at 13:55
  • 1
    But note that it is incredibly trivial to do regex matching in the shell: if echo "$string_to_match" | grep "$pattern" > /dev/null; then ... works very well. Commented Mar 19, 2018 at 14:45

4 Answers 4

2

You can force your script to run with bash by adding

#! /bin/bash

if [ -z "$BASH" ]
then
    exec /bin/bash "$0" "$@"
fi
...
Sign up to request clarification or add additional context in comments.

Comments

2

Your shebang is wrong.

# !/bin/bash

Remove that first space.

4 Comments

Thanks for noticing. But that wasn't the solution.
Really the original shebang syntax required the space.
@GiacomoCatenazzi I don't think that's correct. The original allowed a space after the !, but #! always had to be the first two bytes of the file.
@chepner: you are right, my eyes saw the space after the !.
0

Failing to convince Zabbix to use bash to execute the script, you'll have to forgo regular expression matching (the expr command, bizarrely, does not support any form of alternation, which means its regular expressions can only recognize a subset of regular languages):

# if RECOVER(Y|ED)$ were a valid POSIX basic regular expression,
# you could use
#
#   if expr "$subject" : "$recoverysub"; then
#
# but it is not, so you need...
if [ "$subject" = RECOVERY ] || [ "$subject" = RECOVERED ]; then

3 Comments

Or case "${subject}" in .. esac
Sure, but I don't think that's a vast improvement over the if statement in this case. RECOVER(Y|ED) isn't a valid pattern, either, so you'd still have to use RECOVERY|RECOVERED.
You also have the cases OK, PROBLEM and default.
0

you seems to use instead when calling the script.

Use

bash script.sh

or

chmod +x script.sh
/full/path/to/script.sh

Note :

So now, you know the problem. One solution is to change the script to POSIX shell or search how to force zabbix to handle bash scripts

2 Comments

I'm using 'sh' because that's what Zabbix is trying to use. When I use 'bash script.sh' it works. But I can't find a way for Zabbix to use bash too.
That link appears to be a pseudo-sh library meant to be used by a bash script, rather than a bash script executed by Zabbix. (I say "pseudo" because it appears to be written in a subset of bash that bash still recognizes when invoked as sh. An example is using the function keyword to define a function.)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.