bash script get result from test into variable

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
2
down vote

favorite












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 ?










share|improve this question



















  • 2




    @RoVo, you want if [ "$(cmd)" ..., with the quotes.
    – ilkkachu
    Sep 5 at 9:26






  • 1




    systemctl show --value -p ActiveState to avoid having to use sed.
    – Stéphane Chazelas
    Sep 5 at 20:40










  • @StéphaneChazelas thank you! yes but if you are on systemd version 240 and higher :) github.com/systemd/systemd/blob/master/NEWS I'm on 219.
    – blablatrace
    Sep 6 at 7:10















up vote
2
down vote

favorite












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 ?










share|improve this question



















  • 2




    @RoVo, you want if [ "$(cmd)" ..., with the quotes.
    – ilkkachu
    Sep 5 at 9:26






  • 1




    systemctl show --value -p ActiveState to avoid having to use sed.
    – Stéphane Chazelas
    Sep 5 at 20:40










  • @StéphaneChazelas thank you! yes but if you are on systemd version 240 and higher :) github.com/systemd/systemd/blob/master/NEWS I'm on 219.
    – blablatrace
    Sep 6 at 7:10













up vote
2
down vote

favorite









up vote
2
down vote

favorite











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 ?










share|improve this question















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 ?







shell-script variable test






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Sep 15 at 16:06









Rui F Ribeiro

36.8k1273117




36.8k1273117










asked Sep 5 at 9:16









blablatrace

566




566







  • 2




    @RoVo, you want if [ "$(cmd)" ..., with the quotes.
    – ilkkachu
    Sep 5 at 9:26






  • 1




    systemctl show --value -p ActiveState to avoid having to use sed.
    – Stéphane Chazelas
    Sep 5 at 20:40










  • @StéphaneChazelas thank you! yes but if you are on systemd version 240 and higher :) github.com/systemd/systemd/blob/master/NEWS I'm on 219.
    – blablatrace
    Sep 6 at 7:10













  • 2




    @RoVo, you want if [ "$(cmd)" ..., with the quotes.
    – ilkkachu
    Sep 5 at 9:26






  • 1




    systemctl show --value -p ActiveState to avoid having to use sed.
    – Stéphane Chazelas
    Sep 5 at 20:40










  • @StéphaneChazelas thank you! yes but if you are on systemd version 240 and higher :) github.com/systemd/systemd/blob/master/NEWS I'm on 219.
    – blablatrace
    Sep 6 at 7:10








2




2




@RoVo, you want if [ "$(cmd)" ..., with the quotes.
– ilkkachu
Sep 5 at 9:26




@RoVo, you want if [ "$(cmd)" ..., with the quotes.
– ilkkachu
Sep 5 at 9:26




1




1




systemctl show --value -p ActiveState to avoid having to use sed.
– Stéphane Chazelas
Sep 5 at 20:40




systemctl show --value -p ActiveState to avoid having to use sed.
– Stéphane Chazelas
Sep 5 at 20:40












@StéphaneChazelas thank you! yes but if you are on systemd version 240 and higher :) github.com/systemd/systemd/blob/master/NEWS I'm on 219.
– blablatrace
Sep 6 at 7:10





@StéphaneChazelas thank you! yes but if you are on systemd version 240 and higher :) github.com/systemd/systemd/blob/master/NEWS I'm on 219.
– blablatrace
Sep 6 at 7:10











2 Answers
2






active

oldest

votes

















up vote
3
down vote













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"





share|improve this answer






















  • 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 ?
    – blablatrace
    Sep 5 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"
    – RoVo
    Sep 5 at 9:39

















up vote
2
down vote













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





share|improve this answer






















    Your Answer







    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "106"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    convertImagesToLinks: false,
    noModals: false,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













     

    draft saved


    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f466970%2fbash-script-get-result-from-test-into-variable%23new-answer', 'question_page');

    );

    Post as a guest






























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    3
    down vote













    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"





    share|improve this answer






















    • 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 ?
      – blablatrace
      Sep 5 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"
      – RoVo
      Sep 5 at 9:39














    up vote
    3
    down vote













    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"





    share|improve this answer






















    • 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 ?
      – blablatrace
      Sep 5 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"
      – RoVo
      Sep 5 at 9:39












    up vote
    3
    down vote










    up vote
    3
    down vote









    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"





    share|improve this answer














    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"






    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Sep 5 at 9:38

























    answered Sep 5 at 9:28









    RoVo

    1,715213




    1,715213











    • 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 ?
      – blablatrace
      Sep 5 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"
      – RoVo
      Sep 5 at 9:39
















    • 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 ?
      – blablatrace
      Sep 5 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"
      – RoVo
      Sep 5 at 9:39















    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 ?
    – blablatrace
    Sep 5 at 9:38




    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 ?
    – blablatrace
    Sep 5 at 9:38




    1




    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"
    – RoVo
    Sep 5 at 9:39




    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"
    – RoVo
    Sep 5 at 9:39












    up vote
    2
    down vote













    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





    share|improve this answer


























      up vote
      2
      down vote













      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





      share|improve this answer
























        up vote
        2
        down vote










        up vote
        2
        down vote









        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





        share|improve this answer














        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






        share|improve this answer














        share|improve this answer



        share|improve this answer








        answered Sep 5 at 20:18


























        community wiki





        glenn jackman




























             

            draft saved


            draft discarded















































             


            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f466970%2fbash-script-get-result-from-test-into-variable%23new-answer', 'question_page');

            );

            Post as a guest













































































            Popular posts from this blog

            Peggy Mitchell

            Palaiologos

            The Forum (Inglewood, California)