0

I am a beginner with bash/shell scripting and I am trying to handle a specific output that comes from systemctl when a specific service is not found. For example, when I run systemctl status xyz the output that returns is Unit xyz could not be found. If the service is not found I want to update a variable to hold a string ServiceName="xyz service not found". If the service is found, I don't want to update the variable at all and keep it the same.

This is a part of an effort of trying to find if a specific service is running or not, and store the output from the variable in a csv file that gets shipped to s3 and then I can query the bucket via aws Athena. (I have this implemented already, just providing additional information).

so far I have tried

#!/usr/bin/env bash
serviceName=$(systemctl status xyz | head -n 1 | cut -c 3-)

if [[ $serviceName$(systemctl status xyz | grep 'could not be found') ]]; then
        serviceName="xyz not found"
else
        serviceName=$(systemctl status xyz | head -n 1 | cut -c 3-)
fi

Which returns from running bash test.sh (the name of the file containing the provided code).

Unit xyz could not be found.
Unit xyz could not be found.
Unit xyz could not be found.

I am running this with other commands, so I would prefer not to exit the entire script on failure.

Thank you in advance.

1 Answer 1

1

When you run systemctl status someservice this can return these exit status:

Value Description in LSB Use in systemd
0 "program is running or service is OK" unit is active
1 "program is dead and /var/run pid file exists" unit not failed (used by is-failed)
2 "program is dead and /var/lock lock file exists" unused
3 "program is not running" unit is not active
4 "program or service status is unknown" no such unit

So in this case we care about 4 exit status. Then you can use this script:

systemctl status xyz

if [ "$?" -eq 4 ]; then
   serviceName="xyz service not found"
fi

Btw, in your case this assignment serviceName=$(systemctl status xyz) does not work because the variable actually is empty (because when systemctl status fails with 4 this sends the output to stderr). So if you want to store both stderr too you can use:

serviceName=$(systemctl status xyz 2>&1)
6
  • Thank you for your response. I have some additional questions. I tried your solution, but the first line is my variable assignment serviceName=$(systemctl status xyz | head -n 1 | cut -c 3-| 2>&1) followed by your solution. When I execute the script the variable assignment line gets run and fails the script immediately without evaluating the if block. why is that? TYIA!
    – Sauce
    Feb 17 at 5:56
  • @Sauce I see you have | in your commannd, this: 3-| 2>&1. Nevertheless removing | would not solution your problem. You should use this: systemctl status xyz 2>&1 | head -n 1 | cut -c 3-. (The 2>&1 goes after systemctl status xyz not at the end) Feb 17 at 6:09
  • 1
    To underline what was said above, you want to use 2>&1 to merge stdout and stderr of sysctl, not of cut.
    – user10489
    Feb 17 at 9:17
  • @EdgarMagallon does the stderr get stored into the var serviceName when ran that way? I am sorry, I am just trying to get a better understanding
    – Sauce
    Feb 17 at 13:45
  • @Sauce yes, when you assign to a variable the output of some command only the stdout (file descriptor 1) gets into the var, however if some error occurs then the output will be sent to stderr (file descriptor 2). So if you want to assign both stdout and stderr you will have to use 2>&1 Feb 17 at 17:15

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .