1

I'm trying to learn Bash scripting and for fun I would like to write a script which will monitor the httpd.service.

The basic construct looks like this:

#!/bin/bash
SERVICE=httpd.service

if [ "systemctl show -p ActiveState $SERVICE | sed 's/ActiveState=//g'" != "active" ] && [ "systemctl show -p SubState $SERVICE | sed 's/SubState=//g'"  != "running" ]
then
        echo "$SERVICE is inactive" | mailx -r admin@server.com -s "$SERVICE not running on $HOSTNAME"  my_account@server.com
fi

it works. Whether is written in a secure and best practice way, I guess not but its my second day and I first need to get an idea behind scripting in generall.

How can I get the result of the two testconditions in a variable so that I could print the status and substatus in to the mail ? I guess I could do something like:

#!/bin/bash

SERVICE=httpd.service

STATE=$(systemctl show -p ActiveState $SERVICE | sed 's/ActiveState=//g')
SUBSTATE=$(systemctl show -p SubState $SERVICE | sed 's/SubState=//g')

if [ "$STATE" != "active" ] && [ "SUBSTATE" != "running" ]
then
        echo "$SERVICE state is $STATE and substate is $SUBSTATE"
fi

But not sure if this is a elegant way to do this ?

EDIT

Thanks for all your valuable comments! I've up voted all of them!

So, basically I ended up doing it in the following way:

#!/bin/bash

SERVICE=httpd.service
HOST=$(grep '^ServerName' /etc/httpd/conf/httpd.conf | sed 's/^.* //')
EMAIL=blablatrace@blabla.com




if [ "$(systemctl show -p ActiveState $SERVICE | sed 's/ActiveState=//g')" = "active" ]
then
        echo "$SERVICE is running" >/dev/null
else
        systemctl restart $SERVICE 2>/dev/null
        if [ "$(systemctl show -p ActiveState $SERVICE | sed 's/ActiveState=//g')" = "active" ]
        then
                echo "$SERVICE on $HOST has been started" | mailx -r "${HOST}"@blabla.com -s "$SERVICE on $HOST restarted" $EMAIL
        else
                echo "$SERVICE on $HOST is stopped and could not be started!" | mailx -r "${HOST}"@blabla.com -s "$SERVICE on $HOST has encountered a problem!" $EMAIL
        fi
fi

Could you please have a look at it? Are there any style, not POSIX compliant things used ?

2

Your first script doesn't work, you need

if [ "$(cmd)" != "active" ]

instead of

if [ "cmd" != "active" ]

The second script looks good.
Take care about negated conditions combined with &&. It might not give the result your looking for. I think you want || instead of &&.

You don't need the g option to sed substitution here, but it doesn't hurt either.


But it would be more elegant if you'd use the systemctl integrated functions:

systemctl is-enabled httpd.service >/dev/null || echo "Service not enabled"
systemctl is-active httpd.service >/dev/null || echo "Service not active"
systemctl is-failed httpd.service >/dev/null && echo "Service is failed"
  • Thank your @RoVo. Ok I made the correction as suggested. BUT my originalscript (the first one) works in its original form as well ... what is the difference between if [ "$(cmd)" != "active" ] instead if [ "cmd" != "active" ] ? Could you please explain ? Regarding || and &&. In the first test condition I would like to check if the service status is different than active, so if it is in inactive state the conditions is true that's why the && or did i get it somehow wrong ? – blabla_trace Sep 5 '18 at 9:38
  • 1
    your original runs, but it is not doing what you intend. It will never be active, because it's comparing "active" with the string "cmd" – pLumo Sep 5 '18 at 9:39
1

As @RoVo says, be careful with your logic. You probably want

if [[ ! ("$STATE" = "active" && "SUBSTATE" = "running") ]]

note the use of bash's [[ ... ]]

or more portably

case "$STATE,$SUBSTATE" in
    "active,running") echo ok ;;
                   *) echo not ok ;;
esac

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.