Em774
Em774

Reputation: 49

Bash exit in if statement in a for loop

I am trying to do a for loop in Bash and exit on an if statement but I realised it will break the code before finishing the loop.

#!/bin/bash

for node in $(ps -ef | awk <something>);
do

  var=<command>
  echo "node ${node}"

  if [[ ${var} -gt 300000 ]]; then
    echo "WARNING!";
    exit 1;

  elif [[ ${var} -gt 1000000 ]]; then
    echo "CRITICAL!";
    exit 2;

  else
    echo "OK!";
    exit 0;
  fi
done

My second option is to set a variable instead of the exit outside the loop but then I realised it will override each node status:

#!/bin/bash

for node in $(ps -ef | awk <command>);
do

  var=<command>
  echo "node ${node}"

  if [[ ${var} -gt 300000 ]]; then
    echo "WARNING!";
    status="warning"

  elif [[ ${var} -gt 1000000 ]]; then
    echo "CRITICAL!";
    status="critical"

  else
    echo "OK!";
    status="ok"
  fi
done

if [[ status == "warning" ]]; then 
  exit 1;
elif [[ status == "critical" ]]; then 
  exit 2;
elif [[ status == "ok" ]]; then 
  exit 0;
fi 

How do I exit properly on each node?

Upvotes: 0

Views: 6500

Answers (2)

Wiimm
Wiimm

Reputation: 3615

Here is an alternative. It counts the results and and creates an exit status depending on the counters. I changed the semantic, because your script never reaches the CRITICAL path. Instead the WARNING path was entered for values >1000000:

#!/bin/bash

let ok_count=0 warn_count=0 critical_count=0

for node in $(ps -ef | awk <command>);
do

  var=<command>
  echo "node ${node}"

  # >1000000 must be checked before >300000
  if [[ ${var} -gt 1000000 ]]; then
    echo "CRITICAL!";
    let critical_count++

  elif [[ ${var} -gt 300000 ]]; then
    echo "WARNING!";
    let warn_count++

  else
    echo "OK!";
    let ok_count++
  fi
done

if ((critical_count)); then 
  exit 2
elif ((warn_count)); then 
  exit 1
else
  exit 0
fi

This script can be optimized, if only the exit status is needed: CRITICAL is the highest warn level. So counting is not necessary. OK is the fallback. So counting is not necessary.

#!/bin/bash

let warn_count=0

for node in $(ps -ef | awk <command>);
do

  var=<command>
  echo "node ${node}"

  if [[ ${var} -gt 1000000 ]]; then
    echo "CRITICAL! -> abort";
    exit 2 # no more analysis needed!

  elif [[ ${var} -gt 300000 ]]; then
    echo "WARNING!";
    let warn_count++
  fi
done

exit $(( warn_count > 0 ))

Upvotes: 1

Ivan
Ivan

Reputation: 7317

Use continue operator, from man bash

...
       continue [n]
              Resume the next iteration of the enclosing for, while, until, or select loop.  If n is specified, resume at the nth enclosing loop.  n must be
              ≥ 1.  If n is greater than the number of enclosing loops, the last enclosing loop (the ``top-level'' loop) is resumed.  The return value is  0
              unless n is not greater than or equal to 1.

Or break if you need to exit from loop

...
       break [n]
              Exit  from within a for, while, until, or select loop.  If n is specified, break n levels.  n must be ≥ 1.  If n is greater than the number of
              enclosing loops, all enclosing loops are exited.  The return value is 0 unless n is not greater than or equal to 1.

Upvotes: 1

Related Questions