Bash Script
By
Prokopto Platform Team
sh is a specification, bash is the implementation.
(1) sh
Strictly speaking, sh (or the Shell Command Language) is a programming language described by
the POSIX standard. The key here is that sh isn’t really a programming language in itself. It is just a
specification. Specification is a detailed description of the syntax and semantics of that language.
Specification doesn’t include an implementation.
(2) bash
There are different operating systems with their own shells and kernel. Bash is the shell for the GNU
operating system. But we can also say that bash is a programming language.
sh vs bash
(1) Variables
(2) Conditionals
(3) Loops
(4) Regex
(5) Mathematical Skill
(6) Debugging Skill
(7) Understand Problem life cycle
Basics for better bash scripts
(1) Variables
#!/usr/bin/env bash
LINK_OR_DIR="/tmp/coordinator"
if [ -d "$LINK_OR_DIR" ]; then
# If Condition is satisfied
else:
# If Condition is not satisfies
fi
(2) Conditionals
(3) Loops
(4) Regex
(5) Mathematical Skill
(6) Debugging Skill
(7) Understand Problem life cycle
Basics for better bash scripts
(1) Variables
(2) Conditionals
#!/usr/bin/env bash
if [ -d "$LINK_OR_DIR" ]; then
# If Condition is satisfied
else:
# If Condition is not satisfies
fi
## With the same syntax you can use:
## -e: any kind of archive
## -f: file
## -h: symbolic link
## -r: readable file
## -w: writable file
## -x: executable file
## -s: file size greater than zero
## -d: check if it's a directory
## -L: check if it's a symbolic link
## -z: if the length of string is zero
## -n: length of string is non-zero
(3) Loops
(4) Regex
(5) Mathematical Skill
(6) Debugging Skill
(7) Problem life cycle
Basics for better bash scripts
(1) Variables
(2) Conditionals
(3) Loops
#!/usr/bin/env bash
## While loop
while [ <some test> ]
do
<commands>
done
## Until loop
until [ <some test> ]
do
<commands>
done
## For loop
for var in <list>
do
<commands>
done
(1) Regex
(2) Mathematical Skill
(3) Debugging Skill
(4) Understand Problem life cycle
Basics for better bash scripts
(1) Variables
(2) Conditionals
(3) Loops
(4) Regex
#!/usr/bin/env bash
t="abc123"
[[ "$t" == abc* ]] # true (globbing)
[[ "$t" == "abc*" ]] # false (literal matching)
[[ "$t" =~ [abc]+[123]+ ]] # true (regular expression)
[[ "$t" =~ "abc*" ]] # false (literal matching)
Note, that starting with bash version 3.2 the regular or globbing expression
must not be quoted. If your expression contains whitespace you can store it in a variable:
r="a b+"
[[ "a bbb" =~ $r ]] # true
(5) Mathematical Skill
(6) Debugging Skill
(7) Understand Problem life cycle
Basics for better bash scripts
(1) Variables
(2) Conditionals
(3) Loops
(4) Regex
(5) Mathematical Skill
Matrix algebra
Logical gates
(6) Debugging Skill
(7) Understand Problem life cycle
Basics for better bash scripts
(1) Variables
(2) Conditionals
(3) Loops
(4) Regex
(5) Mathematical Skill
(6) Debugging Skill
1. Reproduce
Before you scramble and try to fix the bug as soon as possible, make sure you can actually reproduce it first.
2. Investigate
Find the bug in the code and the cause!
3. Know Your Error Codes
This is a bit of strange one to hear, but given how fundamental are worth here.
4. Fix & Verify
Now verify that it is actually fixed and, more importantly, that your fix didn't break anything else.
(7) Understand Problem life cycle
Basics for better bash scripts
(1) Variables
(2) Conditionals
(3) Loops
(4) Regex
(5) Mathematical Skill
(6) Debugging Skill
(7) Understand Problem life cycle
Basics for better bash scripts
#!/usr/bin/env bash
##
## HEADER
# Include other bash file
source helper.sh
# Read a file and execute line by line
for server in $(cat servers.txt); do
echo "Server Info: ${server} n"
done
# Ask for confirmation
read -p "You need choice?" yn
case $yn in
[yY] | [yY][Ee][Ss] )
# YOUR YES CODE HERE
;;
[nN] | [nN][Oo] )
# YOUR NO CODE HERE
;;
* ) echo "Please answer yes or no.";;
Esac
# Create File/Directory if not Exists
[ ! -f /tmp/testfile.log ] && touch /tmp/testfile.log
[ ! -d /tmp/mydir ] && mkdir -p /tmp/mydir
# If not active node version 8 then activate using nvm
NVM=https://raw.githubusercontent.com/nvm-
sh/nvm/v0.38.0/install.sh
if [ -x "$(command -v nvm)" ]; then
sh -c "$(curl -fsSL $NVM)"
source ~/.profile
fi
# finds out where bash is on your system
Whereisbash=$(whereis bash)
# Check command executed or not
<command-here>
if [ $? -eq 0 ]; then
echo OK
else
echo FAIL
Fi
# Check profile data on execution time
start=$(date +%s)
# YOUR NO CODE HERE
end=$(date +%s)
echo "Elapsed Time: $(($end-$start)) seconds"
Example:
5 Tips for better bash scripts
(1) Always start with a shebang with header description
(2) Start debug options when developing
(3) Create descriptive variable names
(4) Use $(command) for command substitution
(5) Before you exit on error describe the problem
5 Tips for better bash scripts
(1) Always start with a shebang with header description
#!/usr/bin/env bash
##
## DESCRIPTION: [Description]
## AUTHOR: [Author]
## DATE: [XX_XX_XXXX.XX_XX_XX]
## VERSION: [Version]
## USAGE: [Usage]
##
NOTE:
# How To Start A shebang
#!/bin/sh [For sh scripting]
#!/bin/bash [For bash scripting]
#!/usr/bin/perl [For perl programming]
#!/bin/awk -f [For awk scripting]
#!/usr/bin/env bash [For more portable than #!/bin/bash]
(2) Start debug options when developing
(3) Create descriptive variable names
(4) Use $(command) for command substitution
(5) Before you exit on error describe the problem
5 Tips for better bash scripts
(1) Always start with a shebang with header description
(2) Start debug options when developing
SHORTFORM FULLFORM DESCRIPTION
set -f set -o noglob Disable file name generation using metacharacters (globbing).
set –v set -o verbose Prints shell input lines as they are read.
set –x set -o xtrace Print command traces before executing command.
set -o pipefail Return the exit status of the last command piped command
set -u set -o nounset Exit if an unsed variable is used
set –e set -o errexit let script exit if a command fails
set -n dry run shell script commands
Usage:
#!/usr/bin/env bash
set -o errexit
set -o nounset
set -o pipefail
OR
#!/usr/bin/env bash
set -xv # this line will enable debug
# --- YOUR CODE HERE --- #
set +xv # this line will disable debug
(3) Create descriptive variable names
(4) Use $(command) for command substitution
(5) Before you exit on error describe the problem
5 Tips for better bash scripts
(1) Always start with a shebang with header description
(2) Start debug options when developing
(3) Create descriptive variable names
## Strings should have the form name=value.
## Ideally variable names should only consist uppercase letters, digits, and the ‘_’ (underscore).
## Variable Names shall not contain the character ‘=’ or ‘-‘
## No spaces before or after that equal sign
## Double quotes around every parameter expansion
## Don’t start Variable Name with special characters or Numbers
Example: song="My song.mp3"
(4) Use $(command) for command substitution
(5) Before you exit on error describe the problem
5 Tips for better bash scripts
(1) Always start with a shebang with header description
(2) Start debug options when developing
(3) Create descriptive variable names
(4) Use $(command) for command substitution
#!/usr/bin/env bash
##
## DESCRIPTION: [Description]
## AUTHOR: [Author]
## DATE: [XX_XX_XXXX.XX_XX_XX]
## VERSION: [Version]
## USAGE: [Usage]
##
users=$(cat users.txt)
(5) Before you exit on error describe the problem
5 Tips for better bash scripts
(1) Always start with a shebang with header description
(2) Start debug options when developing
(3) Create descriptive variable names
(4) Use $(command) for command substitution
(5) Before you exit on error describe the problem
Bash Exit Codes
The exit code is a number between 0 and 255
• Success – A zero (0) value represents success.
• failure – A non-zero exit-code represents failure.
#!/usr/bin/env bash
listall=$(ls –la)
if [ $? -eq 0 ]; then
echo OK
else
echo FAIL
fi
NOTE: $?-- Holds the status of the last pipe close, back-quote string, or system() function.
5 Tips for better bash scripts
High level view for better bash scripts
(1) Prerequisites
(2) Program Logic
(3) Create and Moving files/directories
(4) Change Owner access
(5) Create Soft/Hard links
(6) Check installation
High level view for better bash scripts
#!/usr/bin/env bash
##
## HEADER
# PREREQUISITES
# Include other bash file
source helper.sh
# PROGRAM LOGIC
# Read a file and execute line by line
for server in $(cat servers.txt); do
echo "Server Info: ${server} n"
done
# Ask for confirmation
read -p "You need choice?" yn
case $yn in
[yY] | [yY][Ee][Ss] )
# YOUR YES CODE HERE
;;
[nN] | [nN][Oo] )
# YOUR NO CODE HERE
;;
* ) echo "Please answer yes or no.";;
esac
# CREATE FILES, DIRECTORIES
# Create File/Directory if not Exists
[ ! -f /tmp/testfile.log ] && touch /tmp/testfile.log
[ ! -d /tmp/mydir ] && mkdir -p /tmp/mydir
# If not active node version 8 then activate using nvm
NVM=https://raw.githubusercontent.com/nvm-
sh/nvm/v0.38.0/install.sh
if [ -x "$(command -v nvm)" ]; then
sh -c "$(curl -fsSL $NVM)"
source ~/.profile
fi
# finds out where bash is on your system
Whereisbash=$(whereis bash)
# CHECK INSTALLATION
# Check command executed or not
<command-here>
if [ $? -eq 0 ]; then
echo OK
else
echo FAIL
Fi
# PROFILE YOUR CODE
# Check profile data on execution time
start=$(date +%s)
# YOUR NO CODE HERE
end=$(date +%s)
echo "Elapsed Time: $(($end-$start)) seconds"
Example:
QUESTIONS/QUERIES
https://madewithlove.com/blog/software-engineering/follow-these-4-steps-to-take-your-debugging-skills-to-the-next-level/
https://kvz.io/bash-best-practices.html
https://wiki.bash-hackers.org/dict/terms/exit_status
https://tldp.org/LDP/abs/html/exitcodes.html
https://stackoverflow.com/questions/5725296/difference-between-sh-and-bash
References:

KT on Bash Script.pptx

  • 1.
  • 2.
    sh is aspecification, bash is the implementation. (1) sh Strictly speaking, sh (or the Shell Command Language) is a programming language described by the POSIX standard. The key here is that sh isn’t really a programming language in itself. It is just a specification. Specification is a detailed description of the syntax and semantics of that language. Specification doesn’t include an implementation. (2) bash There are different operating systems with their own shells and kernel. Bash is the shell for the GNU operating system. But we can also say that bash is a programming language. sh vs bash
  • 3.
    (1) Variables (2) Conditionals (3)Loops (4) Regex (5) Mathematical Skill (6) Debugging Skill (7) Understand Problem life cycle Basics for better bash scripts
  • 4.
    (1) Variables #!/usr/bin/env bash LINK_OR_DIR="/tmp/coordinator" if[ -d "$LINK_OR_DIR" ]; then # If Condition is satisfied else: # If Condition is not satisfies fi (2) Conditionals (3) Loops (4) Regex (5) Mathematical Skill (6) Debugging Skill (7) Understand Problem life cycle Basics for better bash scripts
  • 5.
    (1) Variables (2) Conditionals #!/usr/bin/envbash if [ -d "$LINK_OR_DIR" ]; then # If Condition is satisfied else: # If Condition is not satisfies fi ## With the same syntax you can use: ## -e: any kind of archive ## -f: file ## -h: symbolic link ## -r: readable file ## -w: writable file ## -x: executable file ## -s: file size greater than zero ## -d: check if it's a directory ## -L: check if it's a symbolic link ## -z: if the length of string is zero ## -n: length of string is non-zero (3) Loops (4) Regex (5) Mathematical Skill (6) Debugging Skill (7) Problem life cycle Basics for better bash scripts
  • 6.
    (1) Variables (2) Conditionals (3)Loops #!/usr/bin/env bash ## While loop while [ <some test> ] do <commands> done ## Until loop until [ <some test> ] do <commands> done ## For loop for var in <list> do <commands> done (1) Regex (2) Mathematical Skill (3) Debugging Skill (4) Understand Problem life cycle Basics for better bash scripts
  • 7.
    (1) Variables (2) Conditionals (3)Loops (4) Regex #!/usr/bin/env bash t="abc123" [[ "$t" == abc* ]] # true (globbing) [[ "$t" == "abc*" ]] # false (literal matching) [[ "$t" =~ [abc]+[123]+ ]] # true (regular expression) [[ "$t" =~ "abc*" ]] # false (literal matching) Note, that starting with bash version 3.2 the regular or globbing expression must not be quoted. If your expression contains whitespace you can store it in a variable: r="a b+" [[ "a bbb" =~ $r ]] # true (5) Mathematical Skill (6) Debugging Skill (7) Understand Problem life cycle Basics for better bash scripts
  • 8.
    (1) Variables (2) Conditionals (3)Loops (4) Regex (5) Mathematical Skill Matrix algebra Logical gates (6) Debugging Skill (7) Understand Problem life cycle Basics for better bash scripts
  • 9.
    (1) Variables (2) Conditionals (3)Loops (4) Regex (5) Mathematical Skill (6) Debugging Skill 1. Reproduce Before you scramble and try to fix the bug as soon as possible, make sure you can actually reproduce it first. 2. Investigate Find the bug in the code and the cause! 3. Know Your Error Codes This is a bit of strange one to hear, but given how fundamental are worth here. 4. Fix & Verify Now verify that it is actually fixed and, more importantly, that your fix didn't break anything else. (7) Understand Problem life cycle Basics for better bash scripts
  • 10.
    (1) Variables (2) Conditionals (3)Loops (4) Regex (5) Mathematical Skill (6) Debugging Skill (7) Understand Problem life cycle Basics for better bash scripts
  • 11.
    #!/usr/bin/env bash ## ## HEADER #Include other bash file source helper.sh # Read a file and execute line by line for server in $(cat servers.txt); do echo "Server Info: ${server} n" done # Ask for confirmation read -p "You need choice?" yn case $yn in [yY] | [yY][Ee][Ss] ) # YOUR YES CODE HERE ;; [nN] | [nN][Oo] ) # YOUR NO CODE HERE ;; * ) echo "Please answer yes or no.";; Esac # Create File/Directory if not Exists [ ! -f /tmp/testfile.log ] && touch /tmp/testfile.log [ ! -d /tmp/mydir ] && mkdir -p /tmp/mydir # If not active node version 8 then activate using nvm NVM=https://raw.githubusercontent.com/nvm- sh/nvm/v0.38.0/install.sh if [ -x "$(command -v nvm)" ]; then sh -c "$(curl -fsSL $NVM)" source ~/.profile fi # finds out where bash is on your system Whereisbash=$(whereis bash) # Check command executed or not <command-here> if [ $? -eq 0 ]; then echo OK else echo FAIL Fi # Check profile data on execution time start=$(date +%s) # YOUR NO CODE HERE end=$(date +%s) echo "Elapsed Time: $(($end-$start)) seconds" Example:
  • 12.
    5 Tips forbetter bash scripts
  • 13.
    (1) Always startwith a shebang with header description (2) Start debug options when developing (3) Create descriptive variable names (4) Use $(command) for command substitution (5) Before you exit on error describe the problem 5 Tips for better bash scripts
  • 14.
    (1) Always startwith a shebang with header description #!/usr/bin/env bash ## ## DESCRIPTION: [Description] ## AUTHOR: [Author] ## DATE: [XX_XX_XXXX.XX_XX_XX] ## VERSION: [Version] ## USAGE: [Usage] ## NOTE: # How To Start A shebang #!/bin/sh [For sh scripting] #!/bin/bash [For bash scripting] #!/usr/bin/perl [For perl programming] #!/bin/awk -f [For awk scripting] #!/usr/bin/env bash [For more portable than #!/bin/bash] (2) Start debug options when developing (3) Create descriptive variable names (4) Use $(command) for command substitution (5) Before you exit on error describe the problem 5 Tips for better bash scripts
  • 15.
    (1) Always startwith a shebang with header description (2) Start debug options when developing SHORTFORM FULLFORM DESCRIPTION set -f set -o noglob Disable file name generation using metacharacters (globbing). set –v set -o verbose Prints shell input lines as they are read. set –x set -o xtrace Print command traces before executing command. set -o pipefail Return the exit status of the last command piped command set -u set -o nounset Exit if an unsed variable is used set –e set -o errexit let script exit if a command fails set -n dry run shell script commands Usage: #!/usr/bin/env bash set -o errexit set -o nounset set -o pipefail OR #!/usr/bin/env bash set -xv # this line will enable debug # --- YOUR CODE HERE --- # set +xv # this line will disable debug (3) Create descriptive variable names (4) Use $(command) for command substitution (5) Before you exit on error describe the problem 5 Tips for better bash scripts
  • 16.
    (1) Always startwith a shebang with header description (2) Start debug options when developing (3) Create descriptive variable names ## Strings should have the form name=value. ## Ideally variable names should only consist uppercase letters, digits, and the ‘_’ (underscore). ## Variable Names shall not contain the character ‘=’ or ‘-‘ ## No spaces before or after that equal sign ## Double quotes around every parameter expansion ## Don’t start Variable Name with special characters or Numbers Example: song="My song.mp3" (4) Use $(command) for command substitution (5) Before you exit on error describe the problem 5 Tips for better bash scripts
  • 17.
    (1) Always startwith a shebang with header description (2) Start debug options when developing (3) Create descriptive variable names (4) Use $(command) for command substitution #!/usr/bin/env bash ## ## DESCRIPTION: [Description] ## AUTHOR: [Author] ## DATE: [XX_XX_XXXX.XX_XX_XX] ## VERSION: [Version] ## USAGE: [Usage] ## users=$(cat users.txt) (5) Before you exit on error describe the problem 5 Tips for better bash scripts
  • 18.
    (1) Always startwith a shebang with header description (2) Start debug options when developing (3) Create descriptive variable names (4) Use $(command) for command substitution (5) Before you exit on error describe the problem Bash Exit Codes The exit code is a number between 0 and 255 • Success – A zero (0) value represents success. • failure – A non-zero exit-code represents failure. #!/usr/bin/env bash listall=$(ls –la) if [ $? -eq 0 ]; then echo OK else echo FAIL fi NOTE: $?-- Holds the status of the last pipe close, back-quote string, or system() function. 5 Tips for better bash scripts
  • 19.
    High level viewfor better bash scripts
  • 20.
    (1) Prerequisites (2) ProgramLogic (3) Create and Moving files/directories (4) Change Owner access (5) Create Soft/Hard links (6) Check installation High level view for better bash scripts
  • 21.
    #!/usr/bin/env bash ## ## HEADER #PREREQUISITES # Include other bash file source helper.sh # PROGRAM LOGIC # Read a file and execute line by line for server in $(cat servers.txt); do echo "Server Info: ${server} n" done # Ask for confirmation read -p "You need choice?" yn case $yn in [yY] | [yY][Ee][Ss] ) # YOUR YES CODE HERE ;; [nN] | [nN][Oo] ) # YOUR NO CODE HERE ;; * ) echo "Please answer yes or no.";; esac # CREATE FILES, DIRECTORIES # Create File/Directory if not Exists [ ! -f /tmp/testfile.log ] && touch /tmp/testfile.log [ ! -d /tmp/mydir ] && mkdir -p /tmp/mydir # If not active node version 8 then activate using nvm NVM=https://raw.githubusercontent.com/nvm- sh/nvm/v0.38.0/install.sh if [ -x "$(command -v nvm)" ]; then sh -c "$(curl -fsSL $NVM)" source ~/.profile fi # finds out where bash is on your system Whereisbash=$(whereis bash) # CHECK INSTALLATION # Check command executed or not <command-here> if [ $? -eq 0 ]; then echo OK else echo FAIL Fi # PROFILE YOUR CODE # Check profile data on execution time start=$(date +%s) # YOUR NO CODE HERE end=$(date +%s) echo "Elapsed Time: $(($end-$start)) seconds" Example:
  • 22.
  • 23.