Skip to main content
added 149 characters in body
Source Link
dave_thompson_085
  • 4.5k
  • 1
  • 19
  • 16

The failures are that you try to select fields with e.g.

CRITICAL_LIMIT=`awk {'print $2'}`

without giving awk any input; you apparently wanted echo $line| or (in ksh bash zsh) <<<$line, and your if syntax is wrong: you need (( )) for arithmetic comparison, and something else entirely for string comparison, and elif instead of elseif. Other things are clumsier than necessary:

  • you initially exclude, only, any filesysem whose mount line includes root. I would want to monitor space usage on the root filesystem. However practically all systems today have several filesystems that aren't stored and thus have no space usage to be monitored: /proc and /sys usually, /dev or part of it often, sometimes others. If you run df without specifying a filesystem, it will do all meaningful filesystems for you. Even better, you only care about the filesystems that are in the config file, so just do those.

  • you read each line and (try to) split it clumsily with awk when read can do this for free

  • you (try to) test only if the usage is equal to a threshold; if e.g. '/dev/sda5' goes rapidly from 79% to 81% your logic won't give a warning for 80%. Usually people want alerts when usage is at or above a threshold.

  • the { and } in an awk script should go inside quotes, because braces are special characters to the shell (at least most shells) and may produce unintended and undesired results, although not in your specific cases

And you haven't tried to actually mail anything at all, but that's often system and environment dependent, so I'll leave that to you.

Applying all of those I would do:

#!/bin/ksh
CONFIG_FILE=/home/oracle/files/template
<$CONFIG_FILE while read filesys warn crit; do
  used=$( df -Ph "$filesys" | awk 'NR>1 {sub(/%/,"",$5);print $5}' )
  if (($used >= $crit)); then echo critical $used% on $filesys
  elif (($used >= $warn)); then echo warning $used% on $filesys; fi
done 

Alternatively you could leave the % in field 5 and used, and do the comparisons on the trimmed value ${used%\%} ; that's six versus half a dozen.

The failures are that you try to select fields with e.g.

CRITICAL_LIMIT=`awk {'print $2'}`

without giving awk any input; you apparently wanted echo $line| or (in ksh bash zsh) <<<$line, and your if syntax is wrong: you need (( )) for arithmetic comparison, and something else entirely for string comparison, and elif instead of elseif. Other things are clumsier than necessary:

  • you initially exclude, only, any filesysem whose mount line includes root. I would want to monitor space usage on the root filesystem. However practically all systems today have several filesystems that aren't stored and thus have no space usage to be monitored: /proc and /sys usually, /dev or part of it often, sometimes others. If you run df without specifying a filesystem, it will do all meaningful filesystems for you. Even better, you only care about the filesystems that are in the config file, so just do those.

  • you read each line and (try to) split it clumsily with awk when read can do this for free

  • you (try to) test only if the usage is equal to a threshold; if e.g. '/dev/sda5' goes rapidly from 79% to 81% your logic won't give a warning for 80%. Usually people want alerts when usage is at or above a threshold.

  • the { and } in an awk script should go inside quotes, because braces are special characters to the shell (at least most shells) and may produce unintended and undesired results, although not in your specific cases

And you haven't tried to actually mail anything at all, but that's often system and environment dependent, so I'll leave that to you.

Applying all of those I would do:

#!/bin/ksh
CONFIG_FILE=/home/oracle/files/template
<$CONFIG_FILE while read filesys warn crit; do
  used=$( df -Ph "$filesys" | awk 'NR>1 {sub(/%/,"",$5);print $5}' )
  if (($used >= $crit)); then echo critical $used% on $filesys
  elif (($used >= $warn)); then echo warning $used% on $filesys; fi
done 

The failures are that you try to select fields with e.g.

CRITICAL_LIMIT=`awk {'print $2'}`

without giving awk any input; you apparently wanted echo $line| or (in ksh bash zsh) <<<$line, and your if syntax is wrong: you need (( )) for arithmetic comparison, and something else entirely for string comparison, and elif instead of elseif. Other things are clumsier than necessary:

  • you initially exclude, only, any filesysem whose mount line includes root. I would want to monitor space usage on the root filesystem. However practically all systems today have several filesystems that aren't stored and thus have no space usage to be monitored: /proc and /sys usually, /dev or part of it often, sometimes others. If you run df without specifying a filesystem, it will do all meaningful filesystems for you. Even better, you only care about the filesystems that are in the config file, so just do those.

  • you read each line and (try to) split it clumsily with awk when read can do this for free

  • you (try to) test only if the usage is equal to a threshold; if e.g. '/dev/sda5' goes rapidly from 79% to 81% your logic won't give a warning for 80%. Usually people want alerts when usage is at or above a threshold.

  • the { and } in an awk script should go inside quotes, because braces are special characters to the shell (at least most shells) and may produce unintended and undesired results, although not in your specific cases

And you haven't tried to actually mail anything at all, but that's often system and environment dependent, so I'll leave that to you.

Applying all of those I would do:

#!/bin/ksh
CONFIG_FILE=/home/oracle/files/template
<$CONFIG_FILE while read filesys warn crit; do
  used=$( df -Ph "$filesys" | awk 'NR>1 {sub(/%/,"",$5);print $5}' )
  if (($used >= $crit)); then echo critical $used% on $filesys
  elif (($used >= $warn)); then echo warning $used% on $filesys; fi
done 

Alternatively you could leave the % in field 5 and used, and do the comparisons on the trimmed value ${used%\%} ; that's six versus half a dozen.

Source Link
dave_thompson_085
  • 4.5k
  • 1
  • 19
  • 16

The failures are that you try to select fields with e.g.

CRITICAL_LIMIT=`awk {'print $2'}`

without giving awk any input; you apparently wanted echo $line| or (in ksh bash zsh) <<<$line, and your if syntax is wrong: you need (( )) for arithmetic comparison, and something else entirely for string comparison, and elif instead of elseif. Other things are clumsier than necessary:

  • you initially exclude, only, any filesysem whose mount line includes root. I would want to monitor space usage on the root filesystem. However practically all systems today have several filesystems that aren't stored and thus have no space usage to be monitored: /proc and /sys usually, /dev or part of it often, sometimes others. If you run df without specifying a filesystem, it will do all meaningful filesystems for you. Even better, you only care about the filesystems that are in the config file, so just do those.

  • you read each line and (try to) split it clumsily with awk when read can do this for free

  • you (try to) test only if the usage is equal to a threshold; if e.g. '/dev/sda5' goes rapidly from 79% to 81% your logic won't give a warning for 80%. Usually people want alerts when usage is at or above a threshold.

  • the { and } in an awk script should go inside quotes, because braces are special characters to the shell (at least most shells) and may produce unintended and undesired results, although not in your specific cases

And you haven't tried to actually mail anything at all, but that's often system and environment dependent, so I'll leave that to you.

Applying all of those I would do:

#!/bin/ksh
CONFIG_FILE=/home/oracle/files/template
<$CONFIG_FILE while read filesys warn crit; do
  used=$( df -Ph "$filesys" | awk 'NR>1 {sub(/%/,"",$5);print $5}' )
  if (($used >= $crit)); then echo critical $used% on $filesys
  elif (($used >= $warn)); then echo warning $used% on $filesys; fi
done