🧙 Shell Tips for Linux Wizards
saving your time: some tips for linux shell
Index #
LOOPING: command x script #
command #
for i in {1..5}; do echo $i; done
count=1; while [ $count -le 5 ]; do echo $count; ((count++)); done
script #
#!/bin/bash
echo "Counting to 5 with a for loop:"
for i in {1..5}; do
echo $i
done
echo "Counting to 5 with a while loop:"
count=1
while [ $count -le 5 ]; do
echo $count
((count++))
done
Signals #
Some scenarios that make sense to deal with signals..
- Cleaning Temporary Files
- Graceful Interruption of Services
- Avoiding Database Corruption
- Releasing Network or Hardware Resources
- Maintaining Consistent Variable State-
SIGINT #
This script creates a temporary file and displays a goodbye message when it receives a SIGINT signal (e.g., when the user presses Ctrl+C).
#!/bin/bash
# Function that will be called when the script receives the SIGINT signal
function exitMsg {
echo "you sent a signal to end, byby !!"
# command here
exit
}
# Sets up the trap to call the cleanup function when the script receives SIGINT
trap exitMsg SIGINT
sleep 5
echo "Creating a temporary file..."
touch /tmp/apolzek || exit 1 # Creates a temporary file or exits with an error
SIGTERM #
This script starts a web server that runs indefinitely and shuts down gracefully when it receives a SIGTERM signal. kill <PID>
#!/bin/bash
# Function called upon receiving SIGTERM
function terminateMsg {
echo "Received SIGTERM, shutting down the server gracefully..."
# Here you can add commands to close connections or save the state
exit
}
# Sets up the trap for SIGTERM
trap terminateMsg SIGTERM
echo "Starting web server..."
while true; do
echo "Server is running... (PID: $$)"
sleep 2 # Simulates the server's running time
done
SIGHUB #
This script starts a daemon that runs indefinitely and reloads its configuration when it receives a SIGHUP signal. kill -HUP <PID>
#!/bin/bash
# Function called upon receiving SIGHUP
function reloadMsg {
echo "Received SIGHUP, reloading configuration..."
# Here you can add commands to reload the configurations
# Example: source /etc/mydaemon/config.conf
}
# Sets up the trap for SIGHUP
trap reloadMsg SIGHUP
echo "Starting my daemon..."
while true; do
echo "Daemon is running... (PID: $$)"
sleep 5 # Simulates the daemon's running time
done
Background processes #
#!/bin/bash
echo "Starting background processes..."
# Process 1
sleep 3 & # This simulates a long-running task
pid1=$! # Get the process ID of process 1
# Process 2
sleep 9 & # This simulates a shorter task
pid2=$! # Get the process ID of process 2
# Wait for process 1 to finish and notify
wait $pid1
echo "Process 1 has completed."
# Wait for process 2 to finish and notify
wait $pid2
echo "Process 2 has completed."
echo "All processes have finished."
Debugging #
#!/bin/bash
set -x # Enable debugging mode
echo "Starting the script..."
echo "Doing something..."
sleep 1
echo "Ending the script."
set +x # Disable debugging mode
echo "now debugging mode is disable"
echo "did you understand ?"
using pipefail..
#!/bin/bash
set -xeuo pipefail
# Uninitialized variable (throws an error with `set -u`)
echo "Attempting to access an uninitialized variable..."
echo "Variable value: $UNINITIALIZED_VAR"
# This command will never be executed due to the previous error
echo "End of script."
String Manipulation and Substitution #
#!/bin/bash
# Defining an original string
original="Linux is amazing!"
# Converting to uppercase
uppercase=${original^^}
echo "Uppercase: $uppercase"
# Output: Uppercase: LINUX IS AMAZING!
## another way
echo "Linux is amazing!" | tr '[:lower:]' '[:upper:]'
echo "Linux is amazing!" | awk '{ print toupper($0) }'
# Converting to lowercase
lowercase=${original,,}
echo "Lowercase: $lowercase"
# Output: Lowercase: linux is amazing!
# Replacing part of the string
modified=${original//amazing/extravagant}
echo "Substitution: $modified"
# Output: Substitution: Linux is extravagant!
# Extracting a substring
substring=${original:7:9} # Extracts "is amazing"
echo "Substring: $substring"
# Output: Substring: is amazing
# Checking the length of the string
length=${#original}
echo "Length of the string: $length characters"
# Output: Length of the string: 20 characters
Shell Associative Arrays #
#!/bin/bash
# Declare an associative array
declare -A user_info
# Assign key-value pairs
user_info[name]="Alice"
user_info[email]="alice@example.com"
user_info[role]="Admin"
# Access elements by key
echo "User Name: ${user_info[name]}"
echo "User Email: ${user_info[email]}"
echo "User Role: ${user_info[role]}"
# Looping over keys and values
for key in "${!user_info[@]}"; do
echo "$key: ${user_info[$key]}"
done
YAML files #
Install yq
sudo pacman -S yq
Create yaml example
apiVersion: v1
kind: ComplexConfig
metadata:
name: example-config
labels:
environment: production
version: "1.0"
spec:
services:
- name: service1
type: LoadBalancer
ports:
- name: http
port: 80
targetPort: 8080
- name: https
port: 443
targetPort: 8443
hosts:
- host: "service1.example.com"
ip: "192.168.1.10"
regions:
- us-east-1
- eu-west-1
- name: service2
type: ClusterIP
ports:
- name: grpc
port: 50051
targetPort: 50051
hosts:
- host: "service2.example.com"
ip: "192.168.1.20"
regions:
- ap-south-1
- eu-central-1
config:
retries: 3
timeout: 5000
logging:
level: debug
format: json
outputs:
- type: file
path: "/var/log/app.log"
- type: stdout
filtering data
yq '.metadata.name' config.yaml
yq '.spec.services[].name' config.yaml
yq '.spec.services[1].type' config.yaml
yq '.spec.services[] | select(.name == "service1") | .ports[] | {port, targetPort}' config.yaml
yq '.spec.services[].hosts[] | {host, ip}' config.yaml
yq '.spec.services[] | select(.name == "service2") | .hosts[].regions' config.yaml
yq '.spec.logging.level' config.yaml
yq -r '.metadata.name' config.yaml
yq -r '.spec.services[].name' config.yaml
yq -r '.spec.services[1].type' config.yaml
yq -r '.spec.services[] | select(.name == "service1") | .ports[] | "\(.port) \(.targetPort)"' config.yaml
yq -r '.spec.services[].hosts[] | "\(.host) \(.ip)"' config.yaml
yq -r '.spec.services[] | select(.name == "service2") | .hosts[].regions[]' config.yaml
yq -r '.spec.logging.level' config.yaml
Check input #
#!/bin/bash
# Check if the argument is a directory.
if [[ ! -d "$1" ]]; then
echo "Error: $1 is not a directory."
exit 1
fi
validating file path..
#!/bin/bash
# Check if the user provided a file path as an argument
if [[ -z "$1" ]]; then
echo "No file path provided. Please enter the file path:"
read -r file_path
else
file_path="$1"
fi
# Check if the file exists
if [[ -f "$file_path" ]]; then
echo "File exists, proceeding with backup."
else
echo "File does not exist. Please check the path and try again."
exit 1
fi