Difference between revisions of "Lustre Script Coding Style"

From Lustre Wiki
Jump to navigation Jump to search
m (→‎Bash Style: remove duplicate text)
 
Line 45: Line 45:
 
</nowiki>
 
</nowiki>
 
* Function arguments should be given local variable names for clarity like "<code>local facet=$1</code>", rather than being used as <code>$1</code> in the function
 
* Function arguments should be given local variable names for clarity like "<code>local facet=$1</code>", rather than being used as <code>$1</code> in the function
 +
* Use <code>sleep 0.1</code> instead of <code>usleep 100000</code>, since <code>usleep</code> is RHEL-specific
 +
 
=== Tests and Libraries ===
 
=== Tests and Libraries ===
 
* To avoid clustering a single <code>test-framework.sh</code> file, there should be a <code><nowiki><test-lib>.sh</nowiki></code> file for each test that contains specific functions and variables for that test.
 
* To avoid clustering a single <code>test-framework.sh</code> file, there should be a <code><nowiki><test-lib>.sh</nowiki></code> file for each test that contains specific functions and variables for that test.

Latest revision as of 13:00, 18 June 2020

Bash Style

  • Bash is a programming language. It includes functions. Shell code outside of functions is effectively code in an implicit main() function. An entire function should be fully seen on one page (~70-90 lines) and be readily comprehensible. If you have any doubts, then it is too complicated. Make it easier to understand by separating it into subroutines.
  • The total length of a line (including comment) must not exceed 80 characters. Take advantage of bash's += operator for constants or linefeed escapes \.
  • Lines can be split without the need for a linefeed escape after |, ||, & and && operators.
  • The indentation must use 8-column tabs and not spaces. For line continuation, an additional tab should be used to indent the continued line, or align after [ or ( for continued logic operations.
  • Comments are just as important in a shell script as in C code.
  • Use $(...) instead of `...` for subshell commands, since the former is easier to see the start and end of the subshell command, avoids confusion with '...' and a small font, and $(...) can be nested. Use the subshell syntax only when you have to (e.g. when you need to capture the output of a separate program). Using the construct with functions leads to stray output and/or convoluted code struggling to avoid output pollution. It is also more computationally efficient to not fork() the Bash process. Bash is slow enough already.
  • Use "here string" like function <<<$var instead of echo $var | function to avoid forking a subshell and pipe
  • Use built-in Bash Parameter Expansion for variable/string manipulation rather than forking sed/tr if possible.
  • Avoid use of "grep foo | awk '{ print $2 }'" since "awk '/foo/ { print $2 }' works just as well and avoids a separate fork + pipe
  • If a variable is intended to be used as a boolean, then it must be assigned as followed:
local mybool=false         # or true
if $mybool; then
        do_stuff
fi
 
  • for loops it is possible to avoid a subshell for $(seq 10) using the built-in iterator for fixed-length loops (unfortunately, {1..$var} does not work):
for i in {1..10}; do
      something_with $i
done

  • Use export FOOBAR=val instead of FOOBAR=val; export FOOBAR for clarity and simplicity
  • Use [[ expr ]] instead of [ expr ], especially since the [[ test understands regular expression matching with the =~ operator. The easiest way to use it is by putting the RE in a variable and expanding the RE after the operator without quotes.
  • Use $((...)) for arithmetic expressions instead of expr

Test Framework

Variables

  • Names of variables local to current script which are not exported to the environment should be declared with "local" and use lowercase letters
  • Names of global variables or variables that exported to the environment should be UPPERCASE letters

Functions

  • Each function must have a section describing what it does and explain the list of parameters
# One line description of this function's purpose
#
# More detailed description of what the function is doing if necessary
#
# usage: function_name [--option argument] {required_argument} ...
# option: meaning of "option" and its argument
# required_argument: meaning of "required_argument"
# 
# expected output and/or return value(s)

  • Function arguments should be given local variable names for clarity like "local facet=$1", rather than being used as $1 in the function
  • Use sleep 0.1 instead of usleep 100000, since usleep is RHEL-specific

Tests and Libraries

  • To avoid clustering a single test-framework.sh file, there should be a <test-lib>.sh file for each test that contains specific functions and variables for that test.
  • Any functions, variables that global to all tests should be put in test-framework.sh
  • A test file only need to source test-framework.sh and necessary <test-lib>.sh file