Skip to content

bash script

mohamadreza bigdeli edited this page Feb 12, 2023 · 19 revisions

Why we as devops engineers should learn programming language?

we should learn programming language(bash script, python, golang) in order to write automation scripts(trigger pipeline, backup, restore, renew certificate,...), add some features to applications, midleware apps, controller, provider, operator,...

  • an accounting application (main app)--> developers

  • some policies should execute on production environment (sentinel, opa, tf2, compliance) --> platform engineering team

    • Sentinel is a multi-cloud infrastructure as code (IaC) tool developed by Hashicorp. It helps organizations define and enforce policies for their cloud infrastructure.
    • OPA (Open Policy Agent): OPA is an open-source, general-purpose policy engine that can be used to enforce policies across multiple platforms and technologies. It can be used to implement fine-grained access control, data validation, and other policy-related tasks.
    • TF2 (Terraform v2): Terraform is an infrastructure as code (IaC) tool that allows you to provision, manage, and version control infrastructure resources. Terraform v2 is the latest version of Terraform, which includes several major improvements and new features compared to the previous version.
    • Compliance: Compliance refers to the act of adhering to a set of regulations, standards, or policies. In the context of technology, compliance often refers to ensuring that an organization's systems and processes meet legal and regulatory requirements, such as data privacy laws or security standards.
  • add some features on prometheus application (add user/pass on dashboard) --> Devops team (devops engineer)

  • write a terraform provider and integrate it with our cloud / write a controller in order to send a notification when an application is deployed on our kubernetes cluster --> Devops Team (devops stack developer/ stack integration developer)

  • write some midleware application to integrate main app with serverless environment(AWS, GCP,...) / write a midleware in order to connect a serverless DB with our main app --> Cloud developer


Bash script:

  • extension is not important in unix, but The ".sh" extension is used to indicate that the file is a shell script and to associate it with the correct interpreter for execution.
  • required permissions to execute a script: r-x
  • How does unix base OS recognize a file is executable:
    • compiled app: with file headers that shows this is a linked binary with a special format.
    • script (interpreter) app: with #!/path/to/interpreter
  • identifier: An identifier is a name used to identify a unique element in a computer program, such as a variable, function, class, or module. An identifier is a sequence of characters that adhere to the syntax rules of the programming language, such as being alphanumeric, starting with a letter, and not containing any spaces or special characters.هرچیزی که در زبان برنامه نویسی بهش اسم بدیم و صداش بزنیم
  • ex1:

mkdir bash_dir && cd bash_dir && touch test.sh && chmod +x test.sh

#!/bin/bash
echo "hello devops"

mkdir python_dir && cd python_dir && touch test.py && chmod +x test.py

#!/usr/bin/python3
print("hello devops")

bash variables principles

1. Naming conventions: Variable names can contain **letters** (capital or lower), **numbers**, and **underscores**, **but must start with a letter or an underscore**. It's case sensetive. It's a good practice to use descriptive, all-capital names for environment variables and all-lowercase names for other variables.
2. Assigning values: You can assign values to variables using the "=" operator, like this: variable_name=value. No spaces are allowed around the "=" operator.
3. Referencing values: To reference the value of a variable, you must precede the variable name with a "$" symbol, like this: $variable_name.
4. Quoting: When assigning values to variables, you can use single or double quotes to define the value. Single quotes (' ') preserve the literal value of all characters within the quotes, while double quotes (" ") allow for the interpretation of variables within the quotes.
5. Scope: Variables in Bash have either a local or global scope. Local variables are only available within the current shell or script, while global variables are available throughout the system.
6. Export: To make a variable available to child processes, you must export it using the "export" command, like this: export variable_name.

Environment variables, local variables, global variables, and shell variables are all ways to store values in different scopes of a program.

  • Environment variables: Variables that are set in the environment and can be accessed by any child process. They are usually set system-wide and persist even after a user logs out. (/etc/environment , ~/.bash_profile)
  • Global variables: Variables that are defined outside of any function or block and can be accessed from anywhere in the program. They persist until the program terminates.
  • To define a global variable, simply declare it outside of any function or block of code:
foo=10
  • Local variables: Variables that are defined within a function or a block of code and are only accessible within that function or block. They are often used to temporarily store values.
  • To define a local variable, use the local keyword before declaring it within a function:
function my_func {
  local bar=20
}
  • Shell variables: Variables that are used in shell scripts and are specific to the shell in which they are defined. They are used to store values and are often used to pass values between commands in a shell script.
  • It's important to note that the value of a local variable is not accessible outside of its scope, and changes made to a local variable do not affect the value of a global variable with the same name.

.

  • ex2: define variable (for string value --> use "")
#!/bin/bash
CLASS="Hello Devops" #CLASS="Hello Devops" ~= CLASS=Hello\ Devops
echo $CLASS
  • ex3: change value of a variable
#!/bin/bash
CLASS=Hello
echo $CLASS
CLASS=Devops
echo $CLASS
  • ex4: define readonly variable
#!/bin/bash
CLASS=Hello
readonly CLASS
echo $CLASS
CLASS=Devops
echo $CLASS

output:

 Hello
./test.sh: line 5: CLASS: readonly variable
 Hello

set -e

  • In Bash, the "set -e" command is used to make the script exit immediately if a command returns a non-zero exit status. In other words, if a command in the script fails, the script will stop executing any further commands and exit immediately. This is useful for scripts that should not continue if a critical step fails, for example, a script that performs some setup tasks before executing another script. The "set -e" command can be useful for ensuring that your script is robust and stops execution as soon as a problem is encountered, rather than continuing to execute subsequent commands that may depend on the success of previous commands.

  • ex5: exit immediately if a command returns a non-zero exit status

#!/bin/bash
set -e
CLASS=Hello
readonly CLASS
echo $CLASS
CLASS=Devops
echo $CLASS

output:

Hello
./test.sh: line 6: CLASS: readonly variable

unset

  • the "unset" command is used to remove a previously defined variable. The syntax: unset variable_name
  • ex6:
#!/bin/bash
set -e
CLASS=Hello
echo $CLASS
unset CLASS
echo $CLASS

output:

Hello

bash script special variables:

Here is a list of all the special variables in Bash scripts:

$#: number of arguments passed to the script
"$@": all the arguments passed to the script as separate words (in loop you can see it. iterate number = argumans number)
"$*": all the arguments passed to the script as one string (iterate one time)
$?: exit status of the last executed command
$0: name of the script itself
$1, $2, ...: positional parameters, representing the values of the script's arguments
$!: process ID of the last executed background command
$_: the last argument of the previous command
$$: represents the process ID of the script itself.
$IFS: the Internal Field Separator, used to split words from input into arrays or variables
$PS1: the primary command prompt string
$PS2: the secondary command prompt string, used when entering multi-line commands
$RANDOM: a random integer between 0 and 32767
$LINENO: the current line number in the script

ex:

#!/bin/bash
for i in "$*"; do
  echo $i
done

for i in "$@"; do
  echo $i
done

These variables have specific uses and can be utilized to control the flow, manipulate arguments, and provide information about the script and its environment.

  • ex7: cause we are in our shell, both process id are equal and our local variable is accesible to "sh"
#!/bin/bash
CLASS="Devops"
echo $CLASS
echo $$
sh -c "echo $CLASS && echo $$"

output:

Devops
1633
Devops
1633

ex8: cause we call a python script in shell (different process), The process IDs are distinct. and our local variable is not accesible in python code.

touch test.sh && touch test.py

  • test.sh
#!/bin/bash
CLASS="Devops"
echo "CLASS=$CLASS in shell"
echo "test.sh_PID=$$"
python3 test.py
  • test.py
#!/usr/bin/python3
from os import environ, getpid
print(f'CLASS={environ.get("CLASS", "NONE")} in python')
print(f'test.py_PID={getpid()}')

output:

CLASS=Devops in shell
test.sh_PID=1673
CLASS=NONE in python
test.py_PID=1674
  • ex9: how child process could access the local variable? we should export it
  • test.sh
#!/bin/bash
export CLASS="Devops"
echo "CLASS=$CLASS in shell"
echo "test.sh_PID=$$"
python3 test.py
  • test.py
#!/usr/bin/python3
from os import environ, getpid
print(f'CLASS={environ.get("CLASS", "NONE")} in python')
print(f'test.py_PID={getpid()}')

output:

CLASS=Devops in shell
test.sh_PID=1681
CLASS=Devops in python
test.py_PID=1682