mirror of
https://github.com/deajan/obackup.git
synced 2024-11-10 01:53:42 +01:00
148 lines
4.7 KiB
Plaintext
148 lines
4.7 KiB
Plaintext
|
Coding style used for my bash projects (v2.1 Oct 2015)
|
||
|
|
||
|
++++++ Header
|
||
|
|
||
|
Always use the following header
|
||
|
|
||
|
----BEGIN HEADER
|
||
|
#!/usr/bin/env bash
|
||
|
|
||
|
PROGRAM="program-name" # Long description
|
||
|
AUTHOR="(L) 20XX-20YY by Orsiris \"Ozy\" de Jong"
|
||
|
CONTACT="http://www.example.com me@example.com"
|
||
|
PROGRAM_BUILD=YYYYMMDDVV
|
||
|
|
||
|
## Optional instructions
|
||
|
----END HEADER
|
||
|
|
||
|
Using bind style versionning:
|
||
|
YYYYMMDDVV (Year, Month, Day, Revision): Example: 2015012402 = 2nd revision of 24 Jan 2015
|
||
|
|
||
|
#!/usr/bin/env bash instead of #!/bin/bash
|
||
|
|
||
|
Change old scripts with
|
||
|
for i in $(grep -r '#!/bin/bash' * |cut -f1 -d':'); do sed -i 's&#!/bin/bash&#!/usr/bin/env bash&g' $i; done
|
||
|
|
||
|
|
||
|
type instead of type -p for bash test (other shells don't know -p)
|
||
|
++++++ Indentation
|
||
|
|
||
|
Using tabs
|
||
|
Transform old shell scripts using unexpand command
|
||
|
|
||
|
++++++ Comments
|
||
|
|
||
|
Some command # comment
|
||
|
## Some comment on a new line
|
||
|
################################################# Some separation
|
||
|
|
||
|
++++++ Work comments
|
||
|
|
||
|
Whenever there is some idea to postpone, use #TODO[-version]:[dev-name:] some remark
|
||
|
A marker must be left where on the line a dev is working (when the work isn't finished). Marker is #WIP:dev-name: some remark
|
||
|
dev-name is mandatory if more than one person is coding
|
||
|
Example: #TODO-v2.1:deajan: need to do something
|
||
|
|
||
|
++++++ Variables
|
||
|
|
||
|
All local variables are lowercase, separated by _ (ex: low_wait)
|
||
|
All global variables full upercase, separated by _ (ex: EXEC_TIME)
|
||
|
All environment variables (verbose, silent, debug, etc) have prefix _ and are full upercase, separated by _ (ex: _PARANOIA_DEBUG)
|
||
|
|
||
|
++++++ Functions
|
||
|
|
||
|
Every word in a function begins with an uppercase (ex: SomeFunctionDoesThings)
|
||
|
|
||
|
Define functions this way. Use sed ':a;N;$!ba;s/\n{\n/ {\n/g' to adapt when opening bracket is on a new line.
|
||
|
|
||
|
function something {
|
||
|
|
||
|
}
|
||
|
|
||
|
If function has some arguments, use local variable names that are more readable than $1...$n. Explain via comments what those variables contain if needed.
|
||
|
|
||
|
function anotherthing {
|
||
|
local var_name="${1}"
|
||
|
local other_var_name="${2}" # This variable contains stuff
|
||
|
}
|
||
|
|
||
|
Functions should always have return status
|
||
|
function thirdthing {
|
||
|
some_command
|
||
|
return $?
|
||
|
}
|
||
|
|
||
|
++++++ Sub functions
|
||
|
|
||
|
When a function is a subroutine of another function, it is called _SomethingAsSubFunction
|
||
|
|
||
|
++++++ Function argument check
|
||
|
|
||
|
Bash does not provide any checks against missing function arguments. Also, missing quotes can lead to an inconsistent number of arguments.
|
||
|
Every function call will be checked by __CheckArguments which takes the number of arguments, $# (the real number of args given), the parent function name and the parent function's arguments.
|
||
|
__CheckArguments will trigger a critical error if number of arguments if incorrect. This will also prevent silent typo errors.
|
||
|
Ex:
|
||
|
|
||
|
function Something {
|
||
|
local some="${1}"
|
||
|
local other="${2}"
|
||
|
local args="${3}"
|
||
|
__CheckArguments 3 $# $FUNCNAME "$*"
|
||
|
|
||
|
__CheckArguments will only trigger if script is called with DEBUG=yes
|
||
|
Also, with PARANOIA_DEBUG=yes, __CheckArguments will recount all arguments given by "$*" and compare. This can mislead if arguments contain spaces.
|
||
|
|
||
|
++++++ If statements
|
||
|
|
||
|
If statements will be fully written (word "if" must be used). then is written on the same line.
|
||
|
(Use sed ':a;N;$!ba;s/]\n\t*then/]; then/g' to convert files to this format... Replace "],new line, zero or more tabs, then" by "; then")
|
||
|
if [ something ]; then
|
||
|
stuff
|
||
|
else
|
||
|
other stuff
|
||
|
fi
|
||
|
|
||
|
++++++ Logging
|
||
|
|
||
|
A logging function is available with the following levels of logging:
|
||
|
|
||
|
- DEBUG: Only log this when DEBUG flas is set in program. Any command forged for eval should be logged by this.
|
||
|
- NOTICE: Standard messages
|
||
|
- WARN: Requires attention
|
||
|
- ERROR: Program produced an error but continues execution
|
||
|
- CRITICAL: Program execution is halted
|
||
|
|
||
|
++++++ Eval
|
||
|
|
||
|
Most commands should be logged to a tmp file.
|
||
|
The basic way of doing is:
|
||
|
|
||
|
cmd='"something '$somevar'" > some_file 2>&1'
|
||
|
eval $cmd &
|
||
|
WaitForTaskCompletion $! 0 0 $FUNCNAME
|
||
|
|
||
|
Remote commands should exist as:
|
||
|
|
||
|
cmd=$SSH_CMD' "some; commands \"'$VARIABLE'\" some; other; commands" > some_file 2>&1'
|
||
|
|
||
|
++++++ File variables
|
||
|
|
||
|
All eval cmd should exit their content to a file called "$RUNDIR/osync.$FUNCNAME.$SCRIPT_PID"
|
||
|
Dots are used instead of '_' so variables can be separated with a forbidden char in variables, so they get detected.
|
||
|
|
||
|
++++++ Finding code errors
|
||
|
|
||
|
Use shellcheck.net now and then (ignore SC2086 in our case)
|
||
|
|
||
|
Use a low tech approach to find uneven number of quotes per line
|
||
|
|
||
|
tr -cd "'\n" < my_bash_file.sh | awk 'length%2==1 {print NR, $0}'
|
||
|
tr -cd "\"\n" < my_bash_file.sh | awk 'length%2==1 {print NR, $0}'
|
||
|
|
||
|
++++++ ofunctions
|
||
|
|
||
|
As obackup and osync share alot of common functions, ofunctions.sh will host all shared code.
|
||
|
Dev programs n_osync.sh and n_obackup.sh will source ofunctions.sh
|
||
|
Release programs will still include ofunctions.sh in order to enhance ease of use.
|
||
|
|