Custom shell instructions explanations

Custom shell instructions explanations#

Custom shell instructions can be set up like described in the custom shell instructions how-to.

Here is a few guidelines to follow when creating new shell instructions:

  • Don’t specify complete path to the programs you want to use. E.g. if you want to retrieve the cumulated CPU usage (over all CPU cores) of Java, then use a shell instruction like this:

    $ ps -eo %cpu,args | grep java | awk '{print $1}' | paste -sd+ - | bc
    

    And not like this:

    $ /path/to/ps -eo %cpu,args | /path/to/grep java | /path/to/awk '{print $1}' | /path/to/paste -sd+ - | /path/to/bc
    

    Unless you specify the paths of the symlinked programs that have being defined for your restricted bash environment (like described in the security how-to), e.g. like this:

    $ /home/sshmonitor-user/bin/ps -eo %cpu,args | /home/sshmonitor-user/bin/grep java | /home/sshmonitor-user/bin/awk '{print $1}' | /home/sshmonitor-user/bin/paste -sd+ - | /path/to/bc
    
  • The default maximum size of a shell instruction is 1024 characters. This size can be changed in the .substitutions file like described in the .cmd and .substitutions how-to and detailed in the .cmd, .template and .substitutions explanations thanks to the <TYPE>_<ID>_INSTRUCTION_LENGTH macro (where <TYPE> is either SCALAR or STRING, and <ID> is integer ranging between 1 to 15 for scalars, and between 1 to 5 for strings).

  • A shell instruction can be suffixed with the #DEBUG comment, in order to print the shell instruction in the IOC Shell before being send through SSH. Like described in the .cmd and .substitutions how-to and detailed in the .cmd, .template and .substitutions explanations.

  • A shell instruction can be suffixed with the #LOCAL comment, in order to execute the shell instruction on the host and not on a target. Like described in the .cmd and .substitutions how-to and detailed in the .cmd, .template and .substitutions explanations.

  • Note that a shell instruction can be suffixed with #LOCAL+DEBUG or #DEBUG+LOCAL if both functionality are needed at the same time (e.g. see STRING_2_INSTRUCTION in the .cmd and .substitutions how-to).

  • As much as possible, tests your shell instructions directly on the target, or in an environment that is similar enough to be truly representative of the target’s environment. This is quite important because the same program on two different machines can have different outputs (e.g. the version of the program may vary, the program could be aliased to a different one, etc). See the bellow side note illustrating why this is so important for BusyBox environments.


BusyBox side note#

Note that some Linux targets do not use the GNU Coreutils shell instructions, but the alternative BusyBox Coreutils shell instructions instead (this is often the case for embedded Linux targets).

BusyBox do not implement all the expected options of the Coreutils shell instructions (the most “uncommon” ones are ignored in order to save space, which can be interesting for some embedded systems).

E.g. the free shell instruction with BusyBox Coreutils:

$ free --help
    BusyBox v1.29.3 (2021-11-19 10:25:20 CET) multi-call binary.
    
    Usage: free [-b/k/m/g]
    
    Display the amount of free and used system memory

$ free
                 total       used       free     shared    buffers     cached
    Mem:       8178052    2559532    5618520       1284      37900      41468
    -/+ buffers/cache:    2480164    5697888
    Swap:            0          0          0

Vs the free shell instruction with GNU Coreutils:

$ free --help
    Usage:
     free [options]
    
    Options:
     -b, --bytes         show output in bytes
         --kilo          show output in kilobytes
         --mega          show output in megabytes
         --giga          show output in gigabytes
         --tera          show output in terabytes
         --peta          show output in petabytes
     -k, --kibi          show output in kibibytes
     -m, --mebi          show output in mebibytes
     -g, --gibi          show output in gibibytes
         --tebi          show output in tebibytes
         --pebi          show output in pebibytes
     -h, --human         show human-readable output
         --si            use powers of 1000 not 1024
     -l, --lohi          show detailed low and high memory statistics
     -t, --total         show total for RAM + swap
     -s N, --seconds N   repeat printing every N seconds
     -c N, --count N     repeat printing N times, then exit
     -w, --wide          wide output
    
         --help     display this help and exit
     -V, --version  output version information and exit
    
    For more details see free(1).

$ free
                   total        used        free      shared  buff/cache   available
    Mem:        32731448     3269368    27681968      468996     1780112    28596924
    Swap:              0           0           0

One can see that a lot of options are missing on the BusyBox version of free, and the output is different.

So, be careful when designing customs shell instructions: make sure to test them on your target before using them in your .substitutions file.

If you do not have access to a BusyBox target, you can install the busybox package (see https://repology.org/project/busybox/versions), and locally test your shell instruction. E.g. in order to retrieve available RAM, instead of running :

$ free -m | grep 'Mem:' | awk '{print $7}'

You would rather run:

$ busybox free -m | busybox grep 'Mem:' | busybox awk '{print $7}'

Warning

Different versions of BusyBox might differ regarding their output format and/or the accepted options. E.g. BusyBox v1.34.1 will accept the df -i shell instruction, but v1.29.3 won’t. This might also be the case when comparing very old GNU Coreutils shell instructions and more recent ones. So, when monitoring an old and/or uncommon target, as a rule of thumb: try to test your custom shell instruction directly on that target!

See also

See https://linuxhandbook.com/what-is-busybox/ for more details about BusyBox.