Marcin Jahn | Dev Notebook
  • Home
  • Programming
  • Technologies
  • Projects
  • About
  • Home
  • Programming
  • Technologies
  • Projects
  • About
  • An icon of the Networking section Networking
    • HTTP Protocol
    • OSI Model
    • TCP Procol
    • UDP Protocol
    • WebSocket
    • HSTS
    • DNS
    • Server Name Indication
    • gRPC
  • An icon of the Security section Security
    • OAuth2
      • Sender Constraint
    • Cryptography
      • Cryptography Basics
    • TPM
      • Overiew
      • TPM Entities
      • TPM Operations
  • An icon of the Linux section Linux
    • Gist of Linux Tooling
    • Unknown
    • SELinux
    • Containers
    • Bash Scripting
    • Linux From Scratch
    • Networking
  • An icon of the Kubernetes section Kubernetes
    • Meaning and Purpose
    • Cluster
    • Dev Environment
    • Kubernetes API
    • Objects
    • Pods
    • Scaling
    • Events
    • Storage
    • Configuration
    • Organizing Objects
    • Services
    • Ingress
    • Helm
  • An icon of the Observability section Observability
    • Tracing
  • An icon of the Databases section Databases
    • ACID
    • Glossary
    • Index
    • B-Tree and B+Tree
    • Partitioning and Sharding
    • Concurrency
    • Database Tips
  • An icon of the SQL Server section SQL Server
    • Overview
    • T-SQL
  • An icon of the MongoDB section MongoDB
    • NoSQL Overview
    • MongoDB Overview
    • CRUD
    • Free Text Search
  • An icon of the Elasticsearch section Elasticsearch
    • Overview
  • An icon of the Git section Git
    • Git
  • An icon of the Ansible section Ansible
    • Ansible
  • An icon of the Azure section Azure
    • Table Storage
    • Microsoft Identity
  • An icon of the Google Cloud section Google Cloud
    • Overview
  • An icon of the Blockchain section Blockchain
    • Overview
    • Smart Contracts
    • Solidity
    • Dapps
  • Home Assistant
    • Home Assistant Tips
  • An icon of the Networking section Networking
    • HTTP Protocol
    • OSI Model
    • TCP Procol
    • UDP Protocol
    • WebSocket
    • HSTS
    • DNS
    • Server Name Indication
    • gRPC
  • An icon of the Security section Security
    • OAuth2
      • Sender Constraint
    • Cryptography
      • Cryptography Basics
    • TPM
      • Overiew
      • TPM Entities
      • TPM Operations
  • An icon of the Linux section Linux
    • Gist of Linux Tooling
    • Unknown
    • SELinux
    • Containers
    • Bash Scripting
    • Linux From Scratch
    • Networking
  • An icon of the Kubernetes section Kubernetes
    • Meaning and Purpose
    • Cluster
    • Dev Environment
    • Kubernetes API
    • Objects
    • Pods
    • Scaling
    • Events
    • Storage
    • Configuration
    • Organizing Objects
    • Services
    • Ingress
    • Helm
  • An icon of the Observability section Observability
    • Tracing
  • An icon of the Databases section Databases
    • ACID
    • Glossary
    • Index
    • B-Tree and B+Tree
    • Partitioning and Sharding
    • Concurrency
    • Database Tips
  • An icon of the SQL Server section SQL Server
    • Overview
    • T-SQL
  • An icon of the MongoDB section MongoDB
    • NoSQL Overview
    • MongoDB Overview
    • CRUD
    • Free Text Search
  • An icon of the Elasticsearch section Elasticsearch
    • Overview
  • An icon of the Git section Git
    • Git
  • An icon of the Ansible section Ansible
    • Ansible
  • An icon of the Azure section Azure
    • Table Storage
    • Microsoft Identity
  • An icon of the Google Cloud section Google Cloud
    • Overview
  • An icon of the Blockchain section Blockchain
    • Overview
    • Smart Contracts
    • Solidity
    • Dapps
  • Home Assistant
    • Home Assistant Tips

Bash Scripting

Executable permission

chmod u+x script.sh

Shabang

#!/bin/bash

Shabang makes sure that the script is executed using the right shell, no matter which shell the user uses to execute the script file.

We can add some arguments to the shell:

#!/bin/bash -v - will print each script line before executing it. It’s useful for debugging when script suddenly stops at some point and hangs. Also shows comments.

#!/bin/bash -x - like above, but it will also show variables values. Doesn’t show comments.

Errors

It’s a good idea to include the following line in the beginning of the script. It will stop execution in case of errors:

Terminal window
set -euo pipefail

It’s a shorthand of:

Terminal window
set -o errexit # abort on nonzero exitstatus
set -o nounset # abort on unbound variable
set -o pipefail # don't hide errors within pipes

Variables

Naming

Only use letters, numbers, and underscores. First character cannot be a number.

It’s recommended not to use upper-case names, becasue all default variables are upper-case.

Initialization

name=Marcin

Variable names ae case-sensitive. There can’t be spaces around the =. If the value has spaces, it needs to be in "".

Usage

echo $name

Shell will replace the $variable with its value before executing the command. If the variable does not exist, an empty string will be used.

Variable can contain a command and can be executed (can be dangerous!):

Terminal window
myVar="rm file1"
$myVar

The above removes file1.

Subprocesses

Variables are available only in the process where they were defined. To change that, export can be used:

Terminal window
export someVar=5

Now, if I run some script from this shell, the myVar variable will be recongnized there.

Script Arguments

When invoking a script, user might pass some arguments. These are available via special variables: $1, $2, and so on.

It is a good idea to create new variables at the beginning of the script with the argments, so that it is easier to understand what they contain.

Terminal window
name=$1
directory=$2

Double Quotes

If our variables may contain spaces, it is a good idea to usethe varibale with "". That way, commands will “understand” that the space is not for a separate command, but rather a part of filename.

Example:

Terminal window
container="$1"
dir="$2"
mkdir -p "$dir"
grep "$container" shipments.csv > "$dir/$container.csv"
echo "Wrote report $dir/$container.csv"

Multiple variables can be put in one pair of "", as can be seen above Before execution of a given line, the variables are substituted with actual values. If dir or container had spaces in it, it is OK, becasue there are "" around the values.

There is a utility shellcheck (command-line and shellcheck.net) that shows issues in script files, i.e. missing "".

ZSH does not require "", because it does not split words from variables as separate commands. It kind of automatically interprets variables as if they were in "".

ALWAYS USE ""!

Single quotes are used to escape the $.

End of Options

When passing arguments to scripts, someone could use -. Often, that would be a problem, it could be interpreted as some command option. Example:

Terminal window
mkdir $1

Running this script with ./script.sh -p will not create a directory -p. It will be taken as an option of mkdir.

There is a special “end of options” string: --. Example:

Terminal window
mkdir -- $1

Whatever is in $1, it will be interpreted as an argument, and not an option.

Not all commands understand -- (i.e., echo). That’s why it is a good idea to use printf instead when the printed value is not granted to be safe:

Terminal window
printf "%s\n" $variable
#OR
printf "My name is %s and this is the current dir %s\n" "$USER" "$(pwd)"

Explicit Names

It might happen that we need to construct a string containing the variable, like this:

Terminal window
echo "$v1_$v2"

Only $v2 will be printed, becasue the shell will look for variable v1_! Mitigation:

Terminal window
echo ${v1}_${v2}

In this case _ was a problem, because _ is a valid character in a variable name. The issue would not be there if there was A ., /, or any other character that is not valid in a variable name.

Declare

declare allows for more advances variables creation. It allows to set a type of varable (default is always string), and others.

Exit Codes

UNIX programs can return values in range 0-255. 0 is success, any other code is an error. There may be many kinds of errors, so different values can be returned.

exit 0 - success exit 1 - error

Conditionals

If-Then-Else

These check the return value (exit code) of a testcode and act based on it (either then or else).

Multiline:

Terminal window
if testcode; then
# Some script
else
# Some else script
fi

One-line:

Terminal window
if testcode; then somecode; else someelsecode; fi

else is optional.

Conditional Expressions

[[ $var ]] - check if var has any value

[[ $var = "ok" ]] - check if var equals “ok” (SPACES AROUND =!)

[[ -e file1 ]] - check if a file file1 exists

[[ -d dir1 ]] - check if a directory dir1 exists

[[ ! testcode ]] - NOT (i.e., [[ ! -e file1 ]] is TRUE when file1 doesn’t exist)

[[ testcode1 && testcode2 ]] - AND

[[ testcode1 || testcode2 ]] - OR

Spaces after [[, and spaces before ]] are necessary!

Functions

Definition:

Terminal window
function create_app() {
var1=1 # Global variable
local var2=2 # Scoped variable
echo "Parameter $1" # The way to return data
}

Invocation:

Terminal window
create_app "argument"
←  Containers
Linux From Scratch  →
© 2023 Marcin Jahn | Dev Notebook | All Rights Reserved. | Built with Astro.