Last active
August 12, 2024 09:40
-
-
Save benc-uk/54b663b7e2443d5fbfeaa1b30391436b to your computer and use it in GitHub Desktop.
Bash snippets
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# Common recipes and tricks | |
# | |
# Check for missing commands & tools | |
which foo > /dev/null || { echo -e "๐ฅ Error! Command foo not installed"; exit 1; } | |
# Single variable | |
[[ -z "$SOMEVAR" ]] && { echo "๐ฅ Error! Required variable SOMEVAR is not set!"; exit 1; } | |
# List of many variables (make sure `set -u` is NOT used) | |
for varName in REQUIRED_VAR ALSO_REQUIRED SO_IS_THIS; do | |
varVal=$(eval echo "\${$varName}") | |
[[ -z $varVal ]] && { echo "๐ฅ Error! Required variable '$varName' is not set!"; varUnset=true; } | |
done | |
[[ $varUnset ]] && exit 1 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
NAME="cert" | |
DOMAIN="localhost" | |
#DOMAIN="myapp.benco.io" | |
IP="12.34.56.78" | |
DAYS="3650" | |
# Create a self-signed cert with a single command, with SNI/SAN | |
openssl req -x509 -newkey rsa:4096 -sha256 -days "$DAYS" -nodes \ | |
-keyout "$NAME".key -out "$NAME".pem -subj "/CN=$DOMAIN" \ | |
-addext "subjectAltName=DNS:$DOMAIN,IP:$IP" | |
# Convert to a PKCS12 file, you might want it in that format I dunno ยฏ\_(ใ)_/ยฏ | |
#openssl pkcs12 -export -out "$NAME".p12 -inkey "$NAME".key -in "$NAME".pem |
Using mkcert with WSL can be a little tricky as it creates a root CA for you and installs it in the relevant place for the OS to be trusted. If you run this in WSL it will result in your browser over on the Windows side still not trusting the certs you create with mkcert.
This is a workaround / solution:
- Install root CA:
mkcert -install
- Convert the root CA to PKCS12, run:
openssl pkcs12 -export -out rootCA.pfx -inkey $(mkcert -CAROOT)/rootCA-key.pem -in $(mkcert -CAROOT)/rootCA.pem
- Specify no password, just hit enter
- Run
explorer.exe .
- In Windows Explorer; double click the
rootCA.pfx
file to import the certificate- Pick the "Place all certificates in the following store" option
- Select "Trusted Root Certification Authorities"
- Run:
mkcert localhost
or any other name (e.g.mkcert foo.example.net
) to generate a certificate and use certs with whatever server/software/SDK as normal - Delete the
rootCA.pfx
file
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
host=localhost | |
port=8080 | |
maxTries=3 | |
sleep=5 | |
tries=0 | |
while ! nc -z $host $port; do | |
echo "Waiting ${sleep}s for $host:$port to accept connections" | |
sleep $sleep | |
tries=$((tries+1)) | |
if [ $tries -ge $maxTries ]; then | |
echo "FAILED: Unable to connect to the $host:$port after $maxTries tries" | |
exit 1 | |
fi | |
done | |
echo "Port $port is available, $host is online" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# Quickly create a new CSR with a new key | |
DOMAIN=${1:-"blah.example.net"} | |
FILE_BASENAME=${2:-"example_net"} | |
LOCATION="London" | |
COUNTRY="GB" | |
ORG="Damage Inc." | |
openssl req -new -newkey rsa:2048 -nodes \ | |
-out "${FILE_BASENAME}.csr" \ | |
-keyout "${FILE_BASENAME}.key" \ | |
-subj "/C=${COUNTRY}/ST=/L=${LOCATION}/O=${ORG}/CN=${DOMAIN}" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
set -euo pipefail | |
if [[ "${TRACE-0}" == "1" ]]; then set -o xtrace; fi | |
if [[ "${1-}" =~ ^-*h(elp)?$ ]]; then | |
echo -e "Usage: $(basename "$0") some-args\nBlah blah change this text" | |
exit | |
fi | |
cd "$(dirname "$0")" | |
# Rest of the script |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
declare count=0 maxTime=30 | |
[[ $# < 2 ]] && { echo "๐ฌ Pass URL and content check as args"; exit 1; } | |
while (( $count < $maxTime )); do | |
# Remove the grep if you don't need content checking | |
curl -sSL $1 | grep $2 | |
if [ $? -eq 0 ]; then | |
echo "๐ URL check passed, content match found!" | |
exit 0 | |
else | |
echo "โ URL check failed, trying again in 1 second" | |
sleep 1 | |
((count=count+1)) | |
fi | |
done | |
echo "๐ฅ Giving up after $maxTime seconds, check failed!" | |
exit 1 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
declare -i time=60 | |
declare -i delay=5 | |
declare -i count=5 | |
declare -i okCount=0 | |
declare -i elapsed=0 | |
declare isUp="false" | |
# Display usage | |
usage(){ | |
echo -e "\e[32mโญโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ" | |
echo -e "โ ๐ \e[94murl-check.sh \e[96mCheck URL endpoint for HTTP responses ๐\e[32m โ" | |
echo -e "โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ" | |
echo -e "\n\e[95mParameters:\e[37m" | |
echo -e " -u, --url \e[33mURL to check (required)\e[37m" | |
echo -e " [-t, --time] \e[33mMaximum number of seconds to poll for \e[92m(default: 60)\e[37m" | |
echo -e " [-d, --delay] \e[33mDelay in seconds between requests \e[92m(default: 5)\e[37m" | |
echo -e " [-c, --count] \e[33mHow many successes to receive before exiting \e[92m(default: 5)\e[37m" | |
echo -e " [-s, --search] \e[33mOptional content check, grep for this string in HTTP body \e[92m(default: none)\e[37m" | |
echo -e " [-h, --help] \e[33mShow this help text\e[37m" | |
} | |
if ! OPTS=$(getopt -o u:t:d:c:s:h --long url:,time:,delay:,count:,search:,help -n 'parse-options' -- "$@"); then echo "Failed parsing options." >&2 ; usage; exit 1 ; fi | |
eval set -- "$OPTS" | |
while true; do | |
case "$1" in | |
-u | --url ) url="$2"; shift; shift;; | |
-t | --time ) time="$2"; shift; shift;; | |
-d | --delay ) delay="$2"; shift; shift;; | |
-c | --count ) count="$2"; shift; shift;; | |
-s | --search ) search="$2"; shift; shift;; | |
-h | --help ) HELP=true; shift ;; | |
-- ) shift; break ;; | |
* ) break ;; | |
esac | |
done | |
if [[ ${HELP} = true ]] || [ -z "${url}" ]; then | |
usage | |
exit 0 | |
fi | |
# Check for impossible parameter combination ie. too many checks and delays in given time limit | |
if (( delay * count > time)); then | |
echo -e "\e[31m### Error! The time ($time) provided is too short given the delay ($delay) and count ($count)\e[0m" | |
exit 1 | |
fi | |
echo -e "\n\e[36m### Polling \e[33m$url\e[36m for ${time}s, to get $count OK results, with a ${delay}s delay\e[0m\n" | |
# Generate tmp filename | |
tmpfile=$(echo "$url" | md5sum) | |
# Main loop | |
while [ "$isUp" != "true" ] | |
do | |
# Break out of loop if max time has elapsed | |
if (( elapsed >= time )); then break; fi | |
timestamp=$(date "+%Y/%m/%d %H:%M:%S") | |
# Main CURL test, output to file and return http_code | |
urlstatus=$(curl -o "/tmp/$tmpfile" --silent --write-out '%{http_code}' "$url") | |
if [ "$urlstatus" -eq 000 ]; then | |
# Code 000 means DNS, network error or malformed URL | |
msg="\e[95mSite not found or other error" | |
else | |
if (( urlstatus >= 200 )) && (( urlstatus < 300 )); then | |
# Check returned content with grep if check specified | |
if [ -n "$search" ]; then | |
# Only count as a success if string grep passed | |
if grep -q "$search" "/tmp/$tmpfile"; then | |
(( okCount=okCount + 1 )) | |
msg="โ \e[32m$urlstatus ๐ Content check for '$search' passed" | |
else | |
msg="โ \e[91m$urlstatus ๐ Content check for '$search' failed" | |
fi | |
else | |
# Good status code | |
((okCount=okCount + 1)) | |
msg="โ \e[32m$urlstatus " | |
fi | |
if (( okCount >= count )); then isUp="true"; fi | |
else | |
# Bad status code | |
msg="โ \e[91m$urlstatus " | |
fi | |
fi | |
# Output message + timestamp then delay | |
echo -e "### $timestamp: $msg\e[0m" | |
# if isUp false then delay | |
if [ "$isUp" != "true" ]; then sleep "$delay"; fi | |
((elapsed=elapsed + delay)) | |
done | |
rm "/tmp/$tmpfile" > /dev/null 2>&1 | |
# Final result check | |
if [ "$isUp" == "true" ]; then | |
echo -e "\n\e[32m### Result: $url is UP! ๐คฉ\e[0m" | |
exit 0 | |
else | |
echo -e "\n\e[91m### Result: $url is DOWN! ๐ข\e[0m" | |
exit 1 | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment