5. Options and arguments

The configuration file holds the usual values of the script. In this step, command line options allow to override them for a single execution, i.e: to check one mount point with a lower threshold.

The code

#!/usr/bin/env python3
"""
--------------------------------------------------------------------------------
  @author         : Luiggi Vercotti
  @date           : 2026-10-08
  @version        : 0.5.0
  @description    : Monitor filesystem usage

--------------------------------------------------------------------------------
  Update:
  0.1.0  2026-10-08 - Luiggi Vercotti - cre: Script creation
  0.2.0  2026-10-08 - Luiggi Vercotti - evo: Several mount points, log levels
  0.3.0  2026-10-08 - Luiggi Vercotti - evo: Monitoring exit status
  0.4.0  2026-10-08 - Luiggi Vercotti - evo: Configuration file
  0.5.0  2026-10-08 - Luiggi Vercotti - evo: Command line options

--------------------------------------------------------------------------------
  List of mandatory configuration parameters:
    @conf:filesystems|mount_points|str|false
    @conf:thresholds|warning|int|false
    @conf:thresholds|critical|int|false

--------------------------------------------------------------------------------
  List of execution options and argument parameters:
    @args:mount-point|str|Mount points to check (default: from configuration)|+||exclude||false|false
    @args:exclude|str|Mount points to skip|+||||false|false
    @args:warning|int|Warning threshold in percent (default: from configuration)|1||||false|false
    @args:critical|int|Critical threshold in percent (default: from configuration)|1||||false|false

--------------------------------------------------------------------------------
  Functioning:
  ---------------
    Checks the usage of each mount point against a warning and a critical
    threshold and exits with a monitoring compatible exit status:
      0: OK, 1: WARNING, 2: CRITICAL

    Configuration:
      - filesystems::mount_points: Comma separated list of mount points
      - thresholds::warning: Warning threshold in percent
      - thresholds::critical: Critical threshold in percent
"""
# ------------------------------------------------------------------------------
#  Initialization of the environment
# ------------------------------------------------------------------------------
import sys
import shutil
import scrippy_core
from scrippy_core import logger

OK, WARNING, CRITICAL = 0, 1, 2
STATUS = {OK: "OK", WARNING: "WARNING", CRITICAL: "CRITICAL"}

# ------------------------------------------------------------------------------
#  Definition of functions and classes
# ------------------------------------------------------------------------------
def get_mount_points(config, args):
  if args.mount_point:
    return args.mount_point
  mount_points = [mp.strip() for mp in config.get("filesystems", "mount_points").split(",")]
  return [mp for mp in mount_points if mp not in (args.exclude or [])]

def get_thresholds(config, args):
  warning = args.warning if args.warning is not None else config.get("thresholds", "warning", "int")
  critical = args.critical if args.critical is not None else config.get("thresholds", "critical", "int")
  return warning, critical

def get_usage(mount_point):
  logger.debug(f"[+] Checking {mount_point}")
  usage = shutil.disk_usage(mount_point)
  return round(usage.used * 100 / usage.total, 1)

def check(mount_points, warning, critical):
  worst = OK
  for mount_point in mount_points:
    usage = get_usage(mount_point)
    if usage >= critical:
      logger.error(f" '-> {mount_point}: {usage}% [CRITICAL]")
      status = CRITICAL
    elif usage >= warning:
      logger.warning(f" '-> {mount_point}: {usage}% [WARNING]")
      status = WARNING
    else:
      logger.info(f" '-> {mount_point}: {usage}% [OK]")
      status = OK
    worst = max(worst, status)
  return worst

# ------------------------------------------------------------------------------
#  Main processing
# ------------------------------------------------------------------------------
def main():
  with scrippy_core.ScriptContext(retention=100) as _context:
    config = _context.config
    args = _context.args
    warning, critical = get_thresholds(config, args)
    logger.log_section("disk_watch", f"Thresholds: warning={warning}% critical={critical}%")
    status = check(get_mount_points(config, args), warning, critical)
    logger.info(f"[+] Status: {STATUS[status]}")
    if status != OK:
      sys.exit(status)

# ------------------------------------------------------------------------------
#  Entry point
# ------------------------------------------------------------------------------
if __name__ == '__main__':
  main()

What changed:

  • The header declares four options with @args lines.
  • get_mount_points() uses the --mount-point option when used, otherwise the configuration minus the --exclude mount points.
  • get_thresholds() uses the --warning and --critical options when used, otherwise the configuration.

Using the options

The options are added to the help:

./disk_watch.py --help
usage: disk_watch.py [-h] [--version] [--source-code]
                     [--hist [NB_EXECUTION (default:10)]]
                     [--log [SESSION (default: last)]] [--debug] [--no-stdout]
                     [--no-log-file]
                     [--mount-point MOUNT_POINT [MOUNT_POINT ...]]
                     [--exclude EXCLUDE [EXCLUDE ...]] [--warning WARNING]
                     [--critical CRITICAL]

Author: Luiggi Vercotti
Date: 2026-10-08
Version: 0.5.0
Description: Monitor filesystem usage

options:
  [...]
  --mount-point MOUNT_POINT [MOUNT_POINT ...]
                        Mount points to check (default: from configuration)
  --exclude EXCLUDE [EXCLUDE ...]
                        Mount points to skip
  --warning WARNING     Warning threshold in percent (default: from configuration)
  --critical CRITICAL   Critical threshold in percent (default: from configuration)
./disk_watch.py --exclude /var /home --warning 30
[...]
[20261008 19:11:53] [INFO    ] [disk_watch] Thresholds: warning=30% critical=90%
[20261008 19:11:53] [WARNING ]  '-> /: 34.9% [WARNING]
[20261008 19:11:53] [INFO    ] [+] Status: WARNING
[...]

The options are checked before entering the execution context: A wrong usage stops the script with the exit status 2, before running any of your code:

./disk_watch.py --warning high
disk_watch.py: error: argument --warning: invalid int value: 'high'
./disk_watch.py --mount-point / --exclude /var
disk_watch.py: error: Params --mount-point conflicts with --exclude. Please remove --mount-point or --exclude

Reading the options

The options are available through _context.args, a standard argparse.Namespace. The value of the --mount-point option is args.mount_point: Dashes are replaced by underscores.

Option Not used --warning 30 --mount-point / /home
args.warning None 30 None
args.mount_point None None ['/', '/home']

An option that is not used and has no default value is None. This is how get_thresholds() knows whether the configuration must be used.

Declaring an option

An option is declared with an @args line made of 9 fields:

@args:<name>|<type>|<help>|<number of arguments>|<default value>|<conflicts>|<implies>|<required>|<secret>
Field Content Mandatory
name The option name, without the leading dashes. Letters, digits, - and _ Yes
type str, int, float, bool or choice Yes
help The help message of the option Yes
number of arguments 1, any integer greater than 1, + (one or more) or ? (zero or one). Ignored for bool options Yes, except for bool
default value The value used when the option is not used. For choice options, the list of accepted values No
conflicts Comma separated list of options that can not be used with this option No
implies Comma separated list of options that must be used with this option No
required true if the option must be used, false otherwise Yes
secret true if the value must be redacted from the logs and the history (see Secrets), false otherwise Yes

Empty optional fields are left empty, but the 9 fields are always present. An invalid declaration is reported at startup with the reason:

[CRITICAL] [ScrippyCoreError]: Invalid @args declaration(s):
  - @args:warning|integer|Warning threshold|1||||false|false: unknown type 'integer' (expected: str, int, float, choice, bool)

The disk_watch.py options

@args:mount-point|str|Mount points to check (default: from configuration)|+||exclude||false|false
@args:exclude|str|Mount points to skip|+||||false|false
@args:warning|int|Warning threshold in percent (default: from configuration)|1||||false|false
@args:critical|int|Critical threshold in percent (default: from configuration)|1||||false|false
  • --mount-point and --exclude accept one or more values (+) and are returned as lists.
  • --mount-point conflicts with --exclude: Excluding mount points only makes sense when they come from the configuration file.
  • --warning and --critical accept exactly one integer.
  • No option is required, no option has a default value: When an option is not used, the configuration applies.

Types

Type Value
str A string
int An integer
float A floating point number
bool A flag that takes no argument (see below)
choice A string among a list of accepted values (see below)

With a number of arguments greater than 1, or +, the value is a list. With a fixed number of arguments greater than 1, the default value contains as many comma separated values:

@args:date|int|Day, month and year|3|1,1,2026|||false|false

bool options

A bool option is a flag: It takes no argument and its number of arguments is ignored. Its default value is false when not set: The option is True when used, False otherwise.

@args:verbose|bool|Display details||false|||false|false

A bool option whose default value is true is False when used.

Note: A bool option can not be secret.

choice options

For a choice option, the default value field holds the comma separated list of accepted values. A choice option that is not used is None:

@args:format|choice|Report format|1|text,csv|||false|false
disk_watch.py: error: argument --format: invalid choice: 'pdf' (choose from text, csv)

disk_watch.py will use bool and choice options in the Workspace and environment step.

Conflicts and implications

  • conflicts: The listed options can not be used together with this option.
  • implies: When this option is used, the listed options must be used too.
@args:format|choice|Report format|1|text,csv||report|false|false
disk_watch.py: error: Params --format implies --report. Please add --report

Both fields can reference the declared options and the debug, no-stdout and no-log-file automatic options.

Reserved options

The help, version, source-code, hist, log, debug, no-stdout and no-log-file options are automatically added to every script: Declaring one of them is an error. They are described in the options reference.

What's next

disk_watch.py will soon send alerts to a monitoring API, which requires an API token. In the next step, you will make sure this token never appears in the logs nor in the history.