0

I need to use an if statement that is true only if "is loaded" AND "is running" occur in a service status command output:

$groupservice status
service 1 is loaded
service 2 is running 

As already mentioned I've tried to use this:

$service status | awk '/is loaded/ && /is running/'

but I dont' get any output. The only way to run it is in this way:

if [[ $(service status | grep "is loaded") ]]  && [[ $(service status | grep "is running") ]]

but I'd prefer to use a shorter expression. Where am I wrong? thank you

intore
  • 399
  • 2
    The problem with your awk attempt is that awk processes the input line-wise, so your program would only work if is loaded and is running appeared on the same line. Also, you say "As already mentioned" - can you add a link where you mentioned this? – AdminBee Jul 05 '21 at 10:04
  • groupservice status|sed '/is loaded/!d;N;/is running/!d'? – Philippos Jul 05 '21 at 10:10
  • I found it here https://unix.stackexchange.com/questions/55359/how-to-run-grep-with-multiple-and-patterns but here also is "already mentioned" – intore Jul 05 '21 at 10:10
  • @Philippos, thank you it's running – intore Jul 05 '21 at 10:18
  • not, none work for me – intore Jul 05 '21 at 11:03
  • Wait, so you don't actually need AND, you don't want the patterns to be on the same line, you want two separate lines, right? – terdon Jul 05 '21 at 11:16
  • yes, the command output consists of many lines with "is running" or "is not running "or "is loaded" or "is not loaded. I need the if returns true if there are "is loaded" AND "is running". – intore Jul 05 '21 at 13:19

2 Answers2

4

You can do it in awk by counting the matches:

$ service status | 
    awk '/is loaded/{l++} 
         /is running/{r++} 
        (l && r){
            print "found"; 
            exit 0
        }
        END{
          if  (!(l && r)){
            print "not found"; 
            exit 1
            }
        }'

The only way I can think of to do this with grep would be to grep the file twice. Something like this:

service status | 
    grep -qF 'is loaded' && foo.sh | 
        grep -qF 'is running' && 
            echo Found || 
                echo "not found"

Of course, that has a race condition in that if the output of service changes between the two invocations, you can get incorrect results. To get around that, you could use a tmp file:

service status > /tmp/file
grep -qF 'is loaded'  /tmp/file &&
    grep -qF 'is running' /tmp/file &&
        echo Found || 
            echo "not found"
terdon
  • 242,166
  • 1
    Never use a variable named l as it looks far too much like the number 1 (indistinguishable in some fonts) and so obfuscates your code. – Ed Morton Jul 05 '21 at 15:55
0

Assuming that, like in your posted sample input, there are no blank lines in your service status output then using any awk:

if service status | awk -v RS= '/is loaded/ && /is running/{f=1} END{exit !f}'; then
    echo "Eureka!"
fi
Eureka!

Obviously if all you need to do is print something then you don't need the shell if statement or to provide an exit status from awk:

service status | awk -v RS= '/is loaded/ && /is running/{print "Eureka!"}'
Eureka!

If there are blank lines and you have GNU awk then just change RS= to RS='^$'.

Ed Morton
  • 31,617
  • what does it mean {f=1} and {exit !f} ? – intore Jul 06 '21 at 10:19
  • It's exactly what it looks like - f=1 is setting a variable named f to the number 1 and then exit !f will exit with status 0 (the shell success exit status) if f was set, or status 1 (a shell failure exit status) otherwise. So the script will exit with success if is loaded and is running are both present, failure otherwise, exactly like grep does when it finds the regexp you're looking for. Add a print f; before the exit and/or a echo "$?" after the call to awk to see what it's set to for files that do/don't contain both strings if you like. – Ed Morton Jul 06 '21 at 14:58