Stuck with a command? Try explainshell.com
The following posts deal with single Shell commands:
awk
- First awk Command Dumpfind
- Find mingle-manglegetopts
- Example Usage of Getopt in a Shell Scriptless
- Read Logs with Lesslsof
- Who listens on port 8080?mail
- You've Got Logssed
- Basic sed magictar
/ssh
- How to transfer a resource folder of a Java application to a remote server with a unix one linerzip
/unzip
- How to update a single file of a zip
Pro Tip: Coloured
grep
output:kubectl get namespace | grep --color=always 'namespace\|planets'
First Things, First! The Shebang: #!
Shebang - the character sequence consisting of the characters number sign and exclamation mark (
#!
) at the beginning of a script. It is also called sha-bang, hashbang, pound-bang, or hash-pling.
Why is #!/usr/bin/env bash superior to #!/bin/bash?
Neither bash
nor env
need to be in the given location.
So both seem to have the same flaw.
It’s up to you!
Check the Linux Standard Base (LBS)
lsb_release -d Description: Ubuntu 20.04.1 LTS
Using Conditional Expressions within Shell Scripts
This section shows some nice use-cases for conditional Expressions. To dive deeper into this topic please consult the official documentation of Bash Conditional Expressions.
Create a directory if not present
[ -d /opt/planets/bin ] || mkdir -p /opt/planets/bin
Test if environment variable exists - shell script: how to check if an environment variable exists, and get its value?
if [[ -z "${DEPLOY_ENV}" ]]; then
MY_SCRIPT_VARIABLE="Some default value because DEPLOY_ENV is undefined"
else
MY_SCRIPT_VARIABLE="${DEPLOY_ENV}"
fi
A simple check if a String variable isn't of size zero
if [ -n "${STOP_AND_REMOVE_CONTAINER}" ]
then
docker stop planets-server || true
docker rm planets-server || true
else
echo "Skipping stop and remove of container."
fi
Browsing through existing code I found this nice snippet: Add trailing slash, if missing:
if [ "${DEST:LEN}" != "/" ]
then
DEST=$DEST"/"
fi
Grab data from JSON
files
This snippet shows how to handle JSON
files with ./jq
` like a pro:
JOB_ID=$(echo $JSON_DOCUMENT | jq -r '.build.jobs[0].jobId')
Note: You can download jq (a lightweight and flexible command-line JSON processor) here
Or via homebrew brew install jq
on a Mac.
Use a default value in variable assignment
NETWORK_INTERFACE=${NETWORK_INTERFACE_ARG:-"en0"}
Read sensitive data from a file into a variable
token=$(<token.txt)
echo "$token”
Replace all variables in a template with envrionment variables
eval "cat <<EOF
$(<planets-bot-deployment-template.yaml)
EOF
" > planets-bot-deployment.yaml
Read the version/any value of a (Java) properties file
export VERSION=$(grep version ../gradle.properties | cut -d'=' -f2)
Check if a variable is already set
if [ -z "$JAVA_HOME" ]; then
echo "No JAVA_HOME set. Using default location for Java 8."
export JAVA_HOME=$(/usr/libexec/java_home -v 1.8)
fi
Setting an environment temporarily for one command line
LOCAL_BUILD=true echo ${LOCAL_BUILD}
Unzip all files in a directory
find . -name '*.zip' -exec unzip {} \;
Create lot's of bogus data with dd
dd if=/dev/urandom bs=1024 count=$((50*1024)) > sample.bin
Check for OSX environment and IP address
if [ $(uname) == "Darwin" ]
then
echo "OSX detected."
NETWORK_INTERFACE=${NETWORK_INTERFACE_ARG:-"en0"}
DOCKER_HOST_IP=$(ipconfig getifaddr ${NETWORK_INTERFACE})
else
echo "Defaulting to Linux."
fi
Print a small usage info using a Shell function
usage() {
cat <<-END
Usage: $0 [-h] [-b backup]
-h help
-b {backup} to use
END
}
…
if [[ -z "${BACKUP}" ]]; then
usage
exit 1
fi
…
The trickiest part was to get the formatting right: Multi-line string with extra space (preserved indentation).
Substring matching
if [[ ${DOCKER_HOST_IP} == 192.168.* ]]
then
echo "local development environment detected."
fi
Create multiple directories with one command
Lately I found this nice snippet in a mongoDB online course to create three subdirectories for a cluster setup:
mkdir -p /data/db/m040/repl/{1,2,3}
The classical for loop
With strings, strings with dash and sub shell commands:
#!/bin/bash
for word in one two "with-dash" "subshell:" $(hostname -f); do
echo $word
done
A while loop over files
#!/bin/zsh
while IFS= read -r -d '' dashboard
do
echo "Processing ${dashboard}…"
if yq -e eval '.metadata.namespace != "monitoring"' "${dashboard}" > /dev/null 2>&1; [ "$?" -eq 0 ]; then
echo "Wrong namespace set in ${dashboard}, please assign the dashboard to namespace 'monitoring'"
exit 1
fi
kubectl apply -f ${dashboard}
done < <(find "grafana/k8s" -name "*dashboard.yaml" -print0)
May the Shell be with you!