# Shared functions

## Init

All scripts start with sourcing a shared bash file

```shell
. $( dirname $0 )/inc_pluginfunctions
```

In that script are several functions starting with prefix **ph.** (=plugin helper)

## Available functions

This is a list in alphabetic order

### ph.abort

Shows error message and exit with status unknown.

Syntax:

```text
ph.abort [TEXT]
```

Parameters:

1. TEXT {string} The text message to show

Example:

```shell
if ! data=$( sudo /bin/ceph df 2>&1 )
then
    echo "$data"
    ph.abort "UNKNOWN: ceph is not available or no sudo permissions to execute ceph commands."
fi
```

### ph.execIfReady

Execute a command and repeat max. MAXTRIES times if it fails.

Syntax:

```text
ph.execIfReady [FUNCTION] [ [WAITTIME] [MAXTRIES] ]
```

Parameters:

1. FUNCTION {string} - command line to execute
2. WAITTIME {integer} - optional: sleeptime in sec before repeating again; default: 5
3. MAXTRIES {integer} - optional: max number of tries; default: 3

Example:

```shell
ph.execIfReady "timedatectl show >$tmpfile; grep '^NTPSynchronized' $tmpfile >/dev/null"

cat $tmpfile | grep "^NTPSynchronized" >/dev/null
if [ $? -ne 0 ]; then
  ph.setStatus "unknown"
  ph.status "timesync: timedatectl has no line NTP synchronized"
  cat $tmpfile
else
  cat $tmpfile | grep "^NTPSynchronized=yes" >/dev/null
  if [ $? -eq 0 ]; then
    ph.status "timesync: a timesync service is active on this ${myos} host"
  else
    ph.setStatus "critical"
    ph.status "timesync: there is no active timesync - you need to activate ntpd or timesyncd on this ${myos} host"
  fi
fi
# /timedatectl
```

### ph.exit

Use at the end to send performance data and exit plugin with set statuscode.

This is the last line of your check script.

Syntax:

```text
ph.exit
```

(no parameters)

### ph.getFileAge

get age of a given file in sec

The file must be reachable by the monitoring user.

Syntax:

```text
ph.getFileAge [FILE]
```

Parameters:

1. FILE {string} - filename

### ph.getOS

get operating system as lowercase - centos/ debian/ ubuntu ...

Syntax:

```text
ph.getOS
```

(no parameters)

Example:

```shell
$ bash -c ". inc_pluginfunctions; ph.getOS"
manjaro
```

In a script:

```shell
distro=$( ph.getOS )

case $distro in

  "centos"|"almalinux")
    # ... do something
    ;;

  "debian"|"ubuntu")
    # ... do something
    ;;

  *)
    ph.abort "UNKNOWN: distro [$distro] was detected but is not supported (yet)."
    ;; 
esac
```

### ph.getOSMajor

get OS Major version as integer, i.e. 7 on a CentOS7

Syntax:

```text
ph.getOSMajor
```

(no parameters)

### ph.getValueWithParam

Return default value or its override from command line.

Syntax:

```text
ph.getFileAge VALUE PARAMNAME "$@"
```

Parameters:

1. VALUE {integer} - the default value if the parameter (2nd param) was not set in the command line
2. PARAMNAME {char} - a single letter for the parameter to search
3. PARAM LIST {string} - list of all parameters to check; use "$@" set all current params from command line

Example:

```shell
# set default / override from command line params
typeset -i iWarnLimit=$(     ph.getValueWithParam 75 w "$@")
typeset -i iCriticalLimit=$( ph.getValueWithParam 90 c "$@")
```

This will set variable iWarnLimit based on CLI parameter -w [value] ... if it does not exist it gets the default 75.

### ph.hasParamoption

check if a letter was used as command line option and return as 0 (=true) or 1 (=false)

Syntax:

```text
ph.hasParamoption PARAMNAME "$@"
```

Parameters:

1. PARAMNAME{char} - a single letter for the parameter to search
2. PARAM LIST{string} - list of all parameters to check; use "$@" set all current params from command line

Example:

Show a help if command line param ``-h`` was given - or no parameter.

```bash
ph.hasParamoption "h" "$@" ; bOptHelp=$?

if [ $bOptHelp -eq 0 -o $# -lt 1 ]; then
    _usage
    exit 0
fi
```


### ph.perfadd

Add performance data. Their output will be written with ```ph.exit```. So you are free to add perfomance data anywhere within your check script.

Syntax:

```txt
ph.perfadd LABEL VALUE [ WARNLEVEL CRITICAL [ MIN MAX ] ]
```

Parameters:

1. LABEL {string} - a label for the performance value; it must be unique for your script; The given value will be cleaned to lowercase; other chars than a-z, 0-9, minus will be deleted.
2. VALUE {integer|float} - your value; default (if missing): 0
3. WARNLEVEL {integer} - optional: warning level; not handled by graphite; default: empty string
4. CRITICAL {integer} - optional: critical level; not handled by graphite; default: empty string
5. MIN {integer} - optional: minimum value of graph; default: empty string
6. MAX {integer} - optional: maximum value of graph;; default: empty string

Example:

Add values with label and value only:

```shell
data2=$( echo "$netdata" | sort | uniq -c )

iEst=$(    echo "$data2" | grep ESTABLISHED | awk '{ print $1 }' )
iListen=$( echo "$data2" | grep LISTEN      | awk '{ print $1 }' )
iWait=$(   echo "$data2" | grep TIME_WAIT   | awk '{ print $1 }' )

ph.perfadd "established" "$iEst"
ph.perfadd "listen"      "$iListen"
ph.perfadd "time-wait"   "$iWait"

ph.exit
```

Add values and define limits for the graph: I will draw it from 0 to a fixed maximum value like for a given physical maximum or 100 for percent values.

Remark that here are empty values for warning and critical to skip them.

```shell
ph.perfadd "memory-total"    "${ramTotal}MB"    "" "" 0 ${ramTotal}
ph.perfadd "memory-used"     "${ramUsed}MB"     "" "" 0 ${ramTotal}
ph.perfadd "memory-avail"    "${ramAvail}MB"    "" "" 0 ${ramTotal}

ph.exit
```

### ph.perfdeltaspeed

For increasing system counters: get changerate per second or per minute since last check.

Syntax:

```text
ph.perfdeltaspeed VARNAME VALUE [ UNIT [isfloat] ]
```

Parameters:

1. VARNAME {string} - an identifier for the value. It is needed to store the last given value and read it on next request.
2. VALUE {integer} - your counter value
3. UNIT {string} - optional: set a unit value can be
   * "s" or "sec" - for seconds (default)
   * "m" or "min" - for minutes
4. isfloat {string} - optional: flag to return a float value; set a non empty string for true.

Example:

```txt
# speed in byte per sec based on last stored value and its age
iSpeedRead=` ph.perfdeltaspeed "netio-${myinterface}-rx" $iRead`
```

### ph.perfshow

dump performance data (if u are not using ph.exit)

Syntax:

```text
ph.perfshow
```

(no parameters)

### ph.require

check if a binary PROG exists in search path (=are installed) - if not then execution stops with showing a warning message and status unknown (using ph.abort).

Syntax:

```text
ph.require [PROG [...PROG_N]]
```

Parameters:

1. PROG - name of program to find in path

Example:

`ph.require bc lsblk`

Hint:
Do not place the requirement check before processing -h to show a help. The help should be visible in any case.

### ph.setStatus

Set a return status of your check with a keyword. This is easier to handle and to read than fiddling with Nagios exitcodes. You can override it as often you want during the script. Based on the last setting the ``ph.exit`` function will set the exitcode.

Syntax:

```text
ph.setStatus [STATUS]
```

Parameters:

1. STATUS {string} - a keyword for the return status.
    * ok
    * warning
    * critical
    * unknown

You get an error message when using another keyword.
The default value - if you do not set it anywhere - is "ok".

Example:

```shell
if [ $iMyValue -lt $iWarnLimit ]; then
    ph.setStatus "ok"
else
    if [ $iMyValue -ge $iCriticalLimit ]; then
        ph.setStatus "critical"
    else
        ph.setStatus "warning"
    fi
fi
ph.status "Return value was $iMyValue"
ph.exit
```

### ph.setStatusByLimit

Set statuscode by verifying integer only(!) value with critical and warning limit.

Syntax:

```text
ph.setStatusByLimit VALUE WARNLIMIT CRITLIMIT
```

Parameters:

1. VALUE {integer} - your discovered value
2. WARNLIMIT {integer} - warning limit
3. CRITLIMIT {integer} - critical limit

This function works in both directions:

* critcal value is HIGHER than warning value; eg. for cpu usage warn on 80% and critical on 90%
* critcal value is LOWER than warning value; eg. for free disk space warn on 10% space left and critical on 3%

Example:

If no warning or critical value is set they are 0 - and a check will return OK on any value. But if they were set then it reacts on these limits.

```shell
if [ $iWarnLimit -gt 0 -a $iCriticalLimit -gt 0 ]; then 
    ph.setStatusByLimit $iTotal $iWarnLimit $iCriticalLimit
fi 
```

### ph.showtimer

Show a time in seconds and milliseconds since start (since source of inc_pluginfunctions.sh).
You can use it to show an execution time.

Syntax:

```text
ph.showtimer
```

It has no parameters.

```shell
2.410 sec
```

### ph.status

Show the current status (set by ``ph.setStatus``) as Text.

Syntax:

```text
ph.status [TEXT]
```

Parameters:

1. TEXT {string} - optional (but recommended) message to display

Without a given text only the status will be shown without linebreak.

Example:

```shell
if [ $iWarnLimit -gt 0 -a $iCriticalLimit -gt 0 ]; then 
    ph.setStatusByLimit $iTotal $iWarnLimit $iCriticalLimit
fi 
ph.status "NETSTAT - count of connections: $iTotal"
```

This shows OK (or WARNING or CRITICAL) as prefix + ": " + "NETSTAT - count of connections: $iTotal".

``OK: NETSTAT - count of connections: 123``

### ph.toUnit

Transform values eg. to Megabyte or back.

The calculation is done by bc. A given Input value will be multiplicated with the source unit and then divided by target unit.
It has its limits.

Syntax:

```text
ph.toUnit VALUE [UNIT] [DIGITS]
```

Parameters:

1. VALUE {integer|float|string} - your input value as integer or float. Behind your value optionally can be a letter for a unit.
2. UNIT {string} - target unit
3. DIGITS {integer} - optional: for return value set a number of digits behind ".";  default: no digits (=integer)

Valid units are:

* "K" - Kilo 2^10
* "M" - Mega 2^20
* "G" - Giga 2^30
* "T" - Tera 2^40
* "P" - Peta 2^50

Examples:

```shell
# -- Convert "kilo" into number:
ph.toUnit 2K
2048

# -- Convert "kilo" as float value into number:
ph.toUnit 2.33K
2385

# -- Get megabytes from a value in bytes:
ph.toUnit 314351346 M
29979

# -- Convert an integer source value with Kilo prefix into megabyte and 
#    return as float with 4 digits:
ph.toUnit 200.5K M 4
0.1958
```