Browse Source

added service manager and tutorials

main
deicidus 2 years ago
parent
commit
00f310906c
  1. 24
      spells/cantrips/cd
  2. 22
      spells/cantrips/fathom-height
  3. 18
      spells/cantrips/fathom-width
  4. 2
      spells/cantrips/menu
  5. 59
      spells/install-service-template
  6. 38
      spells/is-service-installed
  7. 44
      spells/menu/bitcoin/bitcoin-menu
  8. 64
      spells/menu/bitcoin/bitcoin-status
  9. 28
      spells/menu/bitcoin/bitcoin.service
  10. 78
      spells/menu/bitcoin/change-bitcoin-directory
  11. 105
      spells/menu/bitcoin/configure-bitcoin
  12. 88
      spells/menu/bitcoin/install-bitcoin
  13. 4
      spells/menu/bitcoin/is-bitcoin-installed
  14. 16
      spells/menu/bitcoin/is-bitcoin-running
  15. 42
      spells/menu/bitcoin/repair-bitcoin-permissions
  16. 70
      spells/menu/bitcoin/uninstall-bitcoin
  17. 16
      spells/path-wizard
  18. 46
      spells/remove-service
  19. 43
      spells/unbind-tome
  20. 38
      tutorials/01_navigating.sh
  21. 30
      tutorials/02_variables.sh
  22. 55
      tutorials/03_comparison.sh
  23. 36
      tutorials/04_conditionals.sh
  24. 44
      tutorials/05_loops.sh
  25. 47
      tutorials/06_functions.sh
  26. 26
      tutorials/07_pipe.sh
  27. 32
      tutorials/08_permissions.sh
  28. 41
      tutorials/09_regex.sh
  29. 34
      tutorials/10_debugging.sh
  30. 19
      tutorials/11_aliases.sh
  31. 29
      tutorials/12_eval.sh
  32. 21
      tutorials/13_bg.sh
  33. 5
      tutorials/20_advanced_terminal.sh
  34. 47
      tutorials/21_parentheses.sh
  35. 10
      tutorials/22_shebang.sh
  36. 193
      tutorials/23_shell_options.sh
  37. 18
      tutorials/24_backticks.sh
  38. 109
      tutorials/25_env.sh
  39. 19
      tutorials/26_history.sh
  40. 56
      tutorials/27_best_practices.sh
  41. 127
      tutorials/28_distribution.sh
  42. 44
      tutorials/29_ssh.sh
  43. 37
      tutorials/30_git.sh
  44. 104
      tutorials/31_usability.sh

24
spells/cantrips/cd

@ -0,0 +1,24 @@
#!/bin/sh
install_cd() {
if ! grep -q "alias cd=" ~/.bashrc; then
echo "Do you wish to memorize this spell, so that you look around rooms automatically as you use 'cd'? (yes/no)"
read -r answer
if [ "$answer" = "yes" ]; then
scriptpath="$(dirname $(readlink -f $0))"
filename="$(basename "$0")"
echo "alias cd=\". $scriptpath/$filename\"" >> ~/.bashrc
echo "Spell memorized in .bashrc, so the mud will always be active in the terminal."
else
echo "The mud will only run in this shell window."
fi
fi
}
install_cd
# Call the standard cd command
builtin cd "$@"
# Look around the room
look

22
spells/cantrips/fathom-height

@ -0,0 +1,22 @@
#!/usr/bin/env sh
# This magical spell reveals the dimensions of the terminal window, displaying the width and height as if by magic.
# Define the function to calculate the dimensions of the terminal window
fathom_dimensions() {
# Get the width of the terminal window
width=$(tput cols)
# Get the height of the terminal window
height=$(tput lines)
# Output the dimensions of the terminal window
echo "Width: $width"
echo "Height: $height"
}
# Check if the script is being called from another script
if [ "${BASH_SOURCE[0]}" = "$0" ]; then
# If not, call the function
fathom_dimensions
fi

18
spells/cantrips/fathom-width

@ -0,0 +1,18 @@
#!/usr/bin/env sh
# This magical spell reveals the dimensions of the terminal window, displaying the width and height as if by magic.
# Define the function to calculate the dimensions of the terminal window
fathom_height() {
# Get the width of the terminal window
width=$(tput rows)
# Output the dimensions of the terminal window
echo "height"
}
# Check if the script is being called from another script
if [ "${BASH_SOURCE[0]}" = "$0" ]; then
# If not, call the function
fathom_dimensions
fi

2
spells/cantrips/menu

@ -11,7 +11,7 @@
. colors
if [ ${#} -lt 2 ]; then
mud-menu
main-menu
exit 0
fi

59
spells/install-service-template

@ -0,0 +1,59 @@
#!/bin/sh
# This script serves as a magic scroll that conjures a systemd service
# from a given template and a set of variable-value pairs
if [ $# -lt 1 ]; then
echo "Usage: $0 /path/to/service/template key=value [key=value...]"
exit 1
fi
# Ensure systemd is available
if ! command -v systemctl >/dev/null 2>&1; then
echo "Systemd is not installed or not in PATH. Exiting."
exit 1
fi
service_dir=/etc/systemd/system
template_path=$1
service_file=$(basename "$template_path")
service_path="$service_dir/$service_file"
# Ask for confirmation before overwriting an existing file
if [ -f "$service_path" ]; then
if ask_yn "Service file $service_path already exists. Overwrite?" "N"; then
echo "User chose not to overwrite. Exiting."
exit 1
fi
fi
# Prepare a sed command based on the remaining arguments
shift
substitution_cmd=""
for arg in "$@"; do
substitution_cmd="${substitution_cmd}s|\\\$${arg%%=*}|${arg#*=}|g;"
done
# Perform substitutions
sudo sh -c "sed \"$substitution_cmd\" \"$template_path\" > \"$service_path\""
# Ask for missing variables
while IFS= read -r line; do
if echo "$line" | grep -q '\$'; then
var=$(echo "$line" | sed -n -e 's/^.*\$\([A-Z_]*\).*$/\1/p')
if [ -n "$var" ]; then
echo "Enter a value for $var: "
read -r value
sed -i "s|\$$var|$value|g" "$service_path"
fi
fi
done < "$service_path"
# Set permissions
sudo chmod 644 "$service_path"
# Reload systemd
systemctl daemon-reload
echo "Service installed at $service_path"
exit 0

38
spells/is-service-installed

@ -0,0 +1,38 @@
#!/bin/sh
# This script serves as a scrying spell, checking if a given systemd service is installed
if [ $# -lt 1 ]; then
echo "Usage: $0 service_name"
exit 1
fi
# Ensure systemd is available
if ! command -v systemctl >/dev/null 2>&1; then
echo "Systemd is not installed or not in PATH. Exiting."
exit 1
fi
service_dir=/etc/systemd/system
service_name=$1
# Add .service if not present in the name
case $service_name in
*.service) ;;
*) service_name="$service_name.service" ;;
esac
service_path="$service_dir/$service_name"
# Check if service file exists
if [ -f "$service_path" ]; then
if [ -t 1 ]; then # Check if output is a terminal
echo "$service_name is installed."
fi
exit 0 # Service is installed (success)
else
if [ -t 1 ]; then # Check if output is a terminal
echo "$service_name is not installed."
fi
exit 1 # Service is not installed (failure)
fi

44
spells/menu/bitcoin/bitcoin-menu

@ -0,0 +1,44 @@
#!/bin/sh
# This script is a magical tome of sorcery, commanding the elusive entity known as Bitcoin.
. colors
# Displays the menu
display_menu() {
title="${BOLD}${CYAN}Bitcoin: $(bitcoin-status)"
blockchain_info="Display Blockchain Info%bitcoin-cli getblockchaininfo"
set_config="Configure Bitcoin%configure-bitcoin"
change_directory="Change Bitcoin Directory%change-bitcoin-directory"
clear_cache="Clear Bitcoin Cache%# coming soon"
repair_permissions="Repair Permissions%repair-bitcoin-permissions # Sometimes necessary"
exit_option="Exit%kill -2 $$" # Commands are run with 'eval' by the menu script, so we can't simply say 'exit'. The keyword $$ gets this scripts PID and the -2 code is SIGINT aka Ctrl-C
if is-bitcoin-installed; then
install_bitcoin_option="Uninstall Bitcoin%uninstall-bitcoin"
if is-service-installed bitcoin; then
install_service_option="Uninstall Bitcoin Service%remove-service bitcoin"
if is-bitcoin-running; then
bitcoin_server_option="Stop Bitcoin Service%sudo systemctl stop bitcoind"
menu "$title" "$blockchain_info" "$set_config" "$change_directory" "$clear_cache" "$repair_permissions" "$bitcoin_server_option" "$install_service_option" "$install_bitcoin_option" "$exit_option"
else
bitcoin_server_option="Start Bitcoin Service%sudo systemctl start bitcoind"
menu "$title" "$set_config" "$change_directory" "$clear_cache" "$repair_permissions" "$bitcoin_server_option" "$install_service_option" "$install_bitcoin_option" "$exit_option"
fi
else
install_service_option="Install Bitcoin Service%install-service-template ./bitcoin.service \"BITCOIND=`which bitcoind`\""
menu "$title" "$set_config" "$change_directory" "$clear_cache" "$repair_permissions" "$install_service_option" "$install_bitcoin_option" "$exit_option"
fi
else
install_bitcoin_option="Install Bitcoin%install-bitcoin"
menu "$title" "$install_bitcoin_option" "$exit_option"
fi
}
# Catch Ctrl-C and exit
trap 'echo exiting; exit' INT
# Main execution loop
while true; do
display_menu
done

64
spells/menu/bitcoin/bitcoin-status

@ -0,0 +1,64 @@
#!/bin/sh
# Get Bitcoin sync status: 'syncing', 'synced', 'unknown', or 'error'
. colors
# Returns colored text based on status
color_for_status() {
case "$1" in
"installed, running, synced")
printf "${GREEN}"
;;
"not installed")
printf "${GRAY}"
;;
"installed, not running"|"installed, running, syncing"*|"installed, running, not synced")
printf "${YELLOW}"
;;
"installed, running, error"|"*")
printf "${RED}"
;;
esac
}
get_sync_status() {
sync_status=$(bitcoin-cli getblockchaininfo 2>&1 | grep 'initialblockdownload' | awk '{print $2}' | tr -d ',')
if [ "$?" -ne "0" ]; then
echo "error"
elif [ "$sync_status" = "true" ]; then
echo "syncing"
elif [ "$sync_status" = "false" ]; then
echo "synced"
else
echo "unknown"
fi
}
# Returns colored status message
get_status() {
if is-bitcoin-installed; then
if is-bitcoin-running; then
running_status="running"
sync_status=$(get_sync_status)
if [ "$sync_status" = "synced" ]; then
install_status="installed, $running_status, synced"
elif [ "$sync_status" = "syncing" ]; then
progress=$(bitcoin-cli getblockchaininfo | grep 'progress' | awk '{print int($2*100)}')
install_status="installed, $running_status, syncing $progress%"
elif [ "$sync_status" = "unknown" ]; then
install_status="installed, $running_status, not synced"
elif [ "$sync_status" = "error" ]; then
install_status="installed, $running_status, error"
fi
else
install_status="installed, not running"
fi
else
install_status="not installed"
fi
printf "$(color_for_status "$install_status")$install_status${RESET}\n"
}
get_status

28
spells/menu/bitcoin/bitcoin.service

@ -0,0 +1,28 @@
[Unit]
Description=Bitcoin daemon
After=network-online.target
Wants=network-online.target
[Service]
Type=notify
NotifyAccess=all
ExecStart=BITCOIND --daemonwait --pid=HOME/.bitcoin/bitcoind.pid
Type=forking
PIDFile=HOME/.bitcoin/bitcoind.pid
Restart=on-failure
TimeoutStartSec=infinity
TimeoutStopSec=600
KillSignal=SIGINT
LimitNOFILE=32768
User=USER
Group=USER
# Hardening
PrivateTmp=yes
PrivateDevices=yes
MemoryDenyWriteExecute=true
[Install]
WantedBy=multi-user.target

78
spells/menu/bitcoin/change-bitcoin-directory

@ -0,0 +1,78 @@
#!/bin/sh
# This spell alters the location of thy Bitcoin data chamber on your system.
# Check if a command needs to be re-invoked with sudo
retry_with_sudo() {
echo "Permission denied. Invoking the power of the super user..."
sudo "$@"
if [ $? -ne 0 ]; then
echo "Failed to execute with elevated privileges. Make certain thou hast the necessary permissions and try again."
exit 1
fi
}
# Check for the bitcoin.conf file
if [ ! -f "$HOME/.bitcoin/bitcoin.conf" ]; then
echo "Unable to locate bitcoin.conf. Canst thou provide its location?"
read bitcoin_conf
if [ ! -f "$bitcoin_conf" ]; then
echo "bitcoin.conf file not found at the provided location. The spell must end here."
exit 1
fi
else
bitcoin_conf="$HOME/.bitcoin/bitcoin.conf"
fi
# Get the current Bitcoin directory
current_directory=$(grep "datadir" "$bitcoin_conf" | cut -d'=' -f2)
if [ -z "$current_directory" ]; then
current_directory="$HOME/.bitcoin"
else
# Confirm that the directory actually exists
if [ ! -d "$current_directory" ]; then
echo "The Bitcoin data chamber specified in bitcoin.conf doth not exist. Please ensure the correctness of the 'datadir' value in bitcoin.conf."
exit 1
fi
echo "Verified the existence of the Bitcoin data chamber at: $current_directory"
fi
# Ask for the new directory
echo "Enter the new haven for thy Bitcoin data:"
read new_directory
# Create the new directory if it does not exist
if [ ! -d "$new_directory" ]; then
mkdir "$new_directory" || retry_with_sudo mkdir "$new_directory"
fi
# Ask user what to move
echo "What wouldst thou like to move to the new Bitcoin data haven?"
echo "1. The entire Bitcoin data chamber"
echo "2. Only the blockchain data"
echo "3. Move naught"
read move_choice
case "$move_choice" in
1)
echo "Moving the entire Bitcoin data chamber..."
mv "$current_directory"/* "$new_directory" || retry_with_sudo mv "$current_directory"/* "$new_directory"
;;
2)
echo "Moving only the blockchain data..."
mv "$current_directory/blocks" "$current_directory/chainstate" "$new_directory" || retry_with_sudo mv "$current_directory/blocks" "$current_directory/chainstate" "$new_directory"
;;
3)
echo "Moving naught..."
;;
*)
echo "Invalid choice, the spell ends here without moving anything."
exit 1
;;
esac
# Update the bitcoin.conf file to point to the new directory
awk -v path="$new_directory" '!/datadir/ {print} /datadir/ {$3 = path; print}' "$bitcoin_conf" | tee "$bitcoin_conf" >/dev/null || { retry_with_sudo awk -v path="$new_directory" '!/datadir/ {print} /datadir/ {$3 = path; print}' "$bitcoin_conf" | sudo tee "$bitcoin_conf" >/dev/null; }
echo "The Bitcoin data chamber now resides in: $new_directory"

105
spells/menu/bitcoin/configure-bitcoin

@ -0,0 +1,105 @@
#!/bin/sh
# This spell facilitates the setting of the configurations for thy Bitcoin system.
# Function to check if a command needs to be run with sudo
retry_with_sudo() {
echo "Permission denied. Invoking the power of the super user..."
sudo "$@"
if [ $? -ne 0 ]; then
echo "Failed to execute with elevated privileges. Make certain thou hast the necessary permissions and try again."
exit 1
fi
}
# Handle Ctrl-C
#trap "printf '\n'; exit 2" 2
# Create bitcoin directory and configuration file if they do not exist
mkdir -p "$HOME/.bitcoin"
touch "$HOME/.bitcoin/bitcoin.conf"
# Bitcoin defaults
defaults="proxy=127.0.0.1:9050
listen=1
bind=127.0.0.1
disablewallet=1
zmqpubrawblock=tcp://127.0.0.1:28332
zmqpubrawtx=tcp://127.0.0.1:28333"
bitcoin_conf="$HOME/.bitcoin/bitcoin.conf"
# If the file was just created (is empty), write defaults
if [ ! -s "$bitcoin_conf" ]; then
echo "$defaults" > "$bitcoin_conf"
else
ask_yn "Would you like to reset the bitcoin.conf file to defaults?" "n"
reset_conf=$?
if [ "$reset_conf" = 0 ]; then
echo "$defaults" > "$bitcoin_conf"
fi
fi
# Function to modify bitcoin.conf using awk
modify_bitcoin_conf() {
local key=$1
local value=$2
awk -v key="$key" -v value="$value" 'BEGIN {found=0} !/^#/ && $1==key {found=1; print key"="value; next} {print} END {if (!found) print key"="value}' "$bitcoin_conf" > "$bitcoin_conf.tmp" && mv "$bitcoin_conf.tmp" "$bitcoin_conf" || retry_with_sudo mv "$bitcoin_conf.tmp" "$bitcoin_conf"
}
# Pruning question and storage amount
ask_yn "Wouldst thou like to enable pruning? Pruning allows thee to reduce disk usage by discarding some transaction history." "y"
prune=$?
if [ "$prune" = 0 ]; then
modify_bitcoin_conf "prune" "1"
valid_number=false
while [ "$valid_number" = false ]; do
printf "What is the maximum disk space thou art willing to dedicate to Bitcoin in GB? (Type a number) [default: 500]: "
read -r max_disk
if [ -z "$max_disk" ]; then
max_disk=500
valid_number=true
elif validate_number "$max_disk"; then
valid_number=true
else
printf "Invalid input. Please enter a valid number.\n"
fi
done
# Convert GB to MB
max_mem=$((max_disk * 1024))
modify_bitcoin_conf "dbcache" "$max_mem"
else
modify_bitcoin_conf "prune" "0"
fi
# Network selection
ask_yn "Art thou operating on the main Bitcoin network?" "y"
mainnet=$?
if [ "$mainnet" = 0 ]; then
modify_bitcoin_conf "testnet" "0"
else
modify_bitcoin_conf "testnet" "1"
fi
# Blockchain storage location
default_data_dir="$HOME/.bitcoin/blocks"
modify_bitcoin_conf "datadir" "$default_data_dir"
ask_yn "Wouldst thou like to store the blockchain in the default location ($default_data_dir)?" "y"
alt_storage=$?
if [ "$alt_storage" = 1 ]; then
while true; do
printf "Please type the alternate path thou wouldst like to use for blockchain storage: "
read -r alt_path
if validate_path "$alt_path"; then
break
else
printf "That's not a valid UNIX path string. "
fi
done
modify_bitcoin_conf "datadir" "$alt_path"
fi
printf "Bitcoin configuration has been updated.\n"

88
spells/menu/bitcoin/install-bitcoin

@ -0,0 +1,88 @@
#!/bin/sh
# This spell installs bitcoin on almost any Linux platform, from source when possible, otherwise from precompiled binary.
# Set Bitcoin version
BITCOIN_VERSION=24.1
# Install Bitcoin from source
install_bitcoin_from_source() {
say "Installing Bitcoin Core from source"
if [ ! -e bitcoin-$BITCOIN_VERSION* ]; then
wget https://bitcoincore.org/bin/bitcoin-core-$BITCOIN_VERSION/bitcoin-$BITCOIN_VERSION.tar.gz
fi
. ./path_to_install_if_needed_script.sh boost
tar -xvf bitcoin-$BITCOIN_VERSION.tar.gz
sleep 1
cd bitcoin-$BITCOIN_VERSION
chmod +x autogen.sh
./autogen.sh
./configure --disable-wallet
make
if [ $? -ne 0 ]; then
return 1
fi
sudo make install
cd ..
return 0
}
# Install Bitcoin ARM precompiled binary
install_bitcoin_arm_binary() {
say "Installing Bitcoin Core ARM precompiled binary"
if [ ! -e bitcoin-$BITCOIN_VERSION* ]; then
wget https://bitcoincore.org/bin/bitcoin-core-$BITCOIN_VERSION/bitcoin-$BITCOIN_VERSION-arm-linux-gnueabihf.tar.gz
tar -xzf bitcoin-$BITCOIN_VERSION-arm-linux-gnueabihf.tar.gz
fi
sudo install -m 0755 -o root -g root -t /usr/local/bin bitcoin-$BITCOIN_VERSION/bin/*
}
# Install Bitcoin x86_64 precompiled binary
install_bitcoin_x86_64_binary() {
say "Installing Bitcoin Core x86_64 precompiled binary"
if [ ! -e bitcoin-$BITCOIN_VERSION* ]; then
wget https://bitcoincore.org/bin/bitcoin-core-$BITCOIN_VERSION/bitcoin-$BITCOIN_VERSION-x86_64-linux-gnu.tar.gz
tar -xzf bitcoin-$BITCOIN_VERSION-x86_64-linux-gnu.tar.gz
fi
sudo install -m 0755 -o root -g root -t /usr/local/bin bitcoin-$BITCOIN_VERSION/bin/*
}
# Install Bitcoin macOS precompiled binary
install_bitcoin_macos_binary() {
say "Installing Bitcoin Core macOS precompiled binary"
if [ ! -e bitcoin-$BITCOIN_VERSION* ]; then
wget https://bitcoincore.org/bin/bitcoin-core-$BITCOIN_VERSION/bitcoin-$BITCOIN_VERSION-osx-signed.dmg
hdiutil attach bitcoin-$BITCOIN_VERSION-osx-signed.dmg
cp -R /Volumes/Bitcoin-Core/Bitcoin-Qt.app /Applications/
hdiutil detach /Volumes/Bitcoin-Core
fi
}
# Detect the operating system
OS=$(uname -s)
# Install Bitcoin based on the OS
case $OS in
Darwin)
install_bitcoin_macos_binary
;;
Linux)
ARCH=$(uname -m)
case $ARCH in
x86_64)
if ! install_bitcoin_from_source; then
install_bitcoin_x86_64_binary
fi
;;
arm* | aarch64)
install_bitcoin_arm_binary
;;
*)
say "Unsupported architecture: $ARCH"
exit
esac
;;
*)
say "Unsupported operating system: $OS"
exit
esac

4
spells/menu/bitcoin/is-bitcoin-installed

@ -0,0 +1,4 @@
#!/bin/sh
# Returns 0 (true) if Bitcoin is installed, 1 (false) if not
command -v bitcoin-cli >/dev/null 2>&1

16
spells/menu/bitcoin/is-bitcoin-running

@ -0,0 +1,16 @@
#!/bin/sh
# This script serves as a magic mirror, reflecting the running status of Bitcoin
# Look for bitcoin process
if ps -e | grep -q '[b]itcoind'; then
if [ -t 1 ]; then # Check if output is a terminal
echo "Bitcoin is running."
fi
exit 0 # Bitcoin is running (success)
else
if [ -t 1 ]; then # Check if output is a terminal
echo "Bitcoin is not running."
fi
exit 1 # Bitcoin is not running (failure)
fi

42
spells/menu/bitcoin/repair-bitcoin-permissions

@ -0,0 +1,42 @@
#!/bin/sh
# This script sets the correct permissions on the Bitcoin configuration directory.
# Set the default Bitcoin configuration directory
default_dir="$HOME/.bitcoin"
# Check if the default directory exists
if [ -d "$default_dir" ]; then
bitcoin_dir="$default_dir"
else
# Prompt the user to enter the path to the Bitcoin configuration directory
read -p "Enter the path to the Bitcoin configuration directory: " bitcoin_dir
fi
# Check if the provided directory exists
if [ -d "$bitcoin_dir" ]; then
# Set the default permission mode
default_mode=710
# Get the configuration directory mode from bitcoin.conf
config_mode=$(grep -E '^ConfigurationDirectoryMode=' "$bitcoin_dir/bitcoin.conf" | cut -d '=' -f 2)
# If ConfigurationDirectoryMode is not specified, use the default mode
if [ -z "$config_mode" ]; then
config_mode=$default_mode
fi
# Get the current permission mode of the directory
current_mode=$(stat -c "%a" "$bitcoin_dir")
# Compare the current mode with the configured mode
if [ "$current_mode" != "$config_mode" ]; then
# Fix the permission by setting the correct mode
chmod "$config_mode" "$bitcoin_dir"
echo "The permission on the Bitcoin configuration directory has been set to $config_mode."
else
echo "The Bitcoin configuration directory is already configured with the correct permissions."
fi
else
echo "The provided directory does not exist."
fi

70
spells/menu/bitcoin/uninstall-bitcoin

@ -0,0 +1,70 @@
#!/bin/sh
# Function to check if a package is installed in Debian-based distributions
is_deb_package_installed() {
dpkg-query -W -f='${Status}' "$1" 2>/dev/null | grep -c "ok installed"
}
# Function to check if a package is installed in Redhat-based distributions
is_rpm_package_installed() {
rpm -q "$1" &> /dev/null
}
# Function to check if a package is installed in Arch-based distributions
is_arch_package_installed() {
pacman -Q "$1" &> /dev/null
}
# Uninstall Bitcoin from source
uninstall_bitcoin_from_source() {
say "Uninstalling Bitcoin Core installed from source"
sudo make uninstall
}
# Uninstall Bitcoin package
uninstall_bitcoin_package() {
say "Uninstalling Bitcoin Core package"
# Detect the operating system's package manager
if command -v apt &> /dev/null; then
if is_deb_package_installed bitcoin; then
sudo apt-get remove -y bitcoin
fi
elif command -v dnf &> /dev/null; then
if is_rpm_package_installed bitcoin; then
sudo dnf remove -y bitcoin
fi
elif command -v pacman &> /dev/null; then
if is_arch_package_installed bitcoin; then
sudo pacman -Rns bitcoin --noconfirm
fi
elif command -v brew &> /dev/null; then
if brew list --cask bitcoin-core; then
brew uninstall --cask bitcoin-core
fi
else
say "Unsupported package manager"
exit 1
fi
}
# Uninstall Bitcoin
uninstall_bitcoin() {
read -p "This will uninstall Bitcoin Core and might delete your wallet data. Are you sure? (Y/n) " yn
case $yn in
[Yy]* )
uninstall_bitcoin_from_source
uninstall_bitcoin_package
;;
[Nn]* )
say "Uninstallation cancelled"
;;
* )
say "Invalid input. Please answer with Y (yes) or N (no)"
uninstall_bitcoin
;;
esac
}
# Start the uninstallation
uninstall_bitcoin

16
spells/path-wizard

@ -22,10 +22,20 @@ fi
# Check if the directory path was provided
if [ -z "$directory" ]; then
# If no directory path was provided, use the current directory
directory=$(pwd)
directory=$(pwd -P)
else
# If a directory path was provided, expand the '~' character if necessary
directory="$(echo "$directory" | sed "s|^~|$HOME|")"
# If the directory path is '.', convert it to the absolute path of the current directory
if [ "$directory" = "." ]; then
directory=$(pwd -P)
else
# If the directory is a relative path, convert it to an absolute path
if [ "${directory:0:1}" != "/" ]; then
directory=$(cd "$directory" && pwd -P)
fi
fi
fi
# Check if the directory exists
@ -41,7 +51,7 @@ if [ ! -f "$HOME/.bashrc" ]; then
fi
# Check if the directory is already in the PATH variable
if grep -q "PATH=$directory" "$HOME/.bashrc"; then
if grep -q "export PATH=$directory:\$PATH$" "$HOME/.bashrc"; then
# If the directory is already in the PATH variable, check if the action is 'add'
if [ "$action" = "add" ]; then
echo "The directory is already in your PATH."
@ -49,7 +59,7 @@ if grep -q "PATH=$directory" "$HOME/.bashrc"; then
fi
# If the action is 'remove' and the directory is already in the PATH variable, remove the directory from the PATH variable using the 'sed' command
sed -i "\|$directory|d" "$HOME/.bashrc"
sed -i "\|^export PATH=$directory:\$PATH$|d" "$HOME/.bashrc"
echo "The directory has been removed from your PATH."
else
# If the directory is not in the PATH variable, check if the action is 'add'

46
spells/remove-service

@ -0,0 +1,46 @@
#!/bin/sh
# This script serves as an "undo" scroll for the service installation script,
# removing a systemd service that was previously created
if [ $# -lt 1 ]; then
echo "Usage: $0 service_name"
exit 1
fi
# Ensure systemd is available
if ! command -v systemctl >/dev/null 2>&1; then
echo "Systemd is not installed or not in PATH. Exiting."
exit 1
fi
service_dir=/etc/systemd/system
service_name=$1
# Add .service if not present in the name
case $service_name in
*.service) ;;
*) service_name="$service_name.service" ;;
esac
service_path="$service_dir/$service_name"
# Check if service file exists
if [ ! -f "$service_path" ]; then
echo "Service $service_name does not exist."
exit 1
fi
# Stop and disable service if it's running
if systemctl is-active --quiet "$service_name"; then
systemctl stop "$service_name"
fi
# Remove the service file
sudo rm -f "$service_path"
# Reload systemd
systemctl daemon-reload
echo "Service $service_name removed."
exit 0

43
spells/unbind-tome

@ -0,0 +1,43 @@
#!/bin/bash
# A magical spell for slicing and dicing texts and lines. Reads a text file line by line and creates a new folder with the same name as the text file, with one file for each line in the text file inside that folder. Masks any characters that are not valid for use in Unix filenames.
#!/bin/bash
###############################################################################
#
# SCRIPT: slice_text_file.sh
#
# DESCRIPTION: A magical spell for slicing and dicing texts and lines.
# Reads a text file line by line and creates a new folder with the same name
# as the text file, with one file for each line in the text file inside that
# folder. Masks any characters that are not valid for use in Unix filenames.
#
# USAGE: slice_text_file.sh path/to/text_file.txt
#
###############################################################################
# Check that a file path was provided as an argument
if [ "$#" -ne 1 ]; then
echo "Error: Please provide a file path as an argument."
exit 1
fi
# Create a folder with the same name as the text file
folder_name=$(basename "$1" | sed 's/\.[^.]*$//')
i=1
while [ -d "$folder_name" ]; do
# If the folder already exists, append a number to the folder name
folder_name="$folder_name$i"
i=$((i+1))
done
mkdir "$folder_name"
# Read the text file line by line and create a file for each line
while read -r line; do
# Mask any characters that are not valid for use in Unix filenames
# Todo: file names are all prepended with the folder name (no slash), please fix so it's just the filename
file_name=$(echo "$line" | tr -dc '[:alnum:] .,;_-' | tr ' ' '_')
# Create the file
touch "$folder_name/$file_name"
done < "$1"

38
tutorials/01_navigating.sh

@ -0,0 +1,38 @@
#!/bin/sh
# To make this script executable, use the command: chmod +x 01_navigating.sh
# To run the script, use the command: ./01_navigating.sh
echo "This spell that will teach you the basics of navigating the filesystem in POSIX-compliant Bash."
echo "To study the code of the examples, please use the command: cat 01_navigating.sh"
echo "Casting 'pwd' command..."
echo "The 'pwd' command stands for 'print working directory' and it prints the current working directory."
pwd
echo "Casting 'ls' command..."
echo "The 'ls' command stands for 'list' and it lists the files and directories in the current working directory."
ls
echo "Casting 'cd' command with '/' argument..."
echo "The 'cd' command stands for 'change directory' and it changes the current working directory."
echo "This will take us to the root directory."
cd /
pwd
echo "Casting 'cd' command with '~' argument..."
echo "This will take us to the home directory."
cd ~
pwd
echo "Casting 'mkdir' command..."
echo "The 'mkdir' command stands for 'make directory' and it creates a new directory."
echo "We are using the '-p' option which creates any necessary parent directories."
mkdir -p ~/wizardry/charms
ls ~/wizardry
echo "Casting 'rmdir' command..."
echo "The 'rmdir' command stands for 'remove directory' and it removes an empty directory."
rmdir ~/wizardry/charms
ls ~/wizardry
rmdir ~/wizardry
echo "Spell cast successfully."

30
tutorials/02_variables.sh

@ -0,0 +1,30 @@
#!/bin/sh
# To make this script executable, use the command: chmod +x 02_variables.sh
# To run the script, use the command: ./02_variables.sh
echo "This script is a spell that will teach you the basics of variables and parameter expansion in Bash."
echo "To study the code of the examples, please use the command: cat 02_variables_parameter_expansion.sh"
# Declaring a variable
ingredient="Dragon's blood"
echo "Gathering ingredients for the potion, $ingredient found."
# Accessing the value of a variable
echo "The ingredient used is: $ingredient"
# Re-assigning a variable
ingredient="Unicorn hair"
echo "Gathering ingredients for the potion, $ingredient found."
# Special variable: $#
echo "Number of ingredients passed to the script: $#"
# Special variable: $@
echo "All ingredients passed to the script: $@"
# Special variable: $?
echo "Effect of the last ingredient added: $?"
# Parameter expansion
echo "The first ingredient passed to the script is: ${1}" #todo: split this into another script, maybe between 01 and 02?
echo "Spell cast successfully."

55
tutorials/03_comparison.sh

@ -0,0 +1,55 @@
#!/bin/sh
To make this script executable, use the command: chmod +x 14_boolean_comparison.sh
To run the script, use the command: ./14_boolean_comparison.sh
echo "This spell will teach you the basics of boolean values and basic string comparison in POSIX-compliant Bash"
echo "To study the code of the examples, please use the command: cat 14_boolean_comparison.sh"
Basic string comparison
string1="magic"
string2="wizardry"
echo "Are 'magic' and 'wizardry' the same? (Should be false)"
[ "$string1" = "$string2" ]
echo $?
echo "Are 'magic' and 'magic' the same? (Should be true)"
[ "$string1" = "$string1" ]
echo $?
echo "Is 'magic' not 'wizardry'? (Should be true)"
[ "$string1" != "$string2" ]
echo $?
echo "Is 'magic' greater than 'wizardry'? (Should be false)"
[ "$string1" > "$string2" ]
echo $?
echo "Is 'wizardry' greater than 'magic'? (Should be true)"
[ "$string2" > "$string1" ]
echo $?
echo "Spell cast successfully"
# To make this script executable, use the command: chmod +x 23_boolean_values.sh
# To run the script, use the command: ./23_boolean_values.sh
echo "This spell will teach you the basics of boolean values and string comparison in POSIX-compliant Bash."
echo "To study the code of the examples, please use the command: cat 23_boolean_values.sh"
# Basic boolean values
echo $((1 == 1)) # 0
echo $((1 != 1)) # 1
echo $((1 > 2)) # 1
echo $((1 < 2)) # 0
# Basic string comparison
string1="Hello"
string2="World"
echo $((string1 == string2)) # 0
echo $((string1 != string2)) # 1
echo $((string1 > string2)) # 1
echo $((string1 < string2)) # 0
echo "Spell cast successfully"

36
tutorials/04_conditionals.sh

@ -0,0 +1,36 @@
#!/bin/sh
# To make this script executable, use the command: chmod +x 03_conditionals.sh
# To run the script, use the command: ./03_conditionals.sh
echo "This spell will teach you the basics of conditional statements in POSIX-compliant Bash."
echo "To study the code of the examples, please use the command: cat 03_conditionals.sh"
# Using if statement
echo "Checking if the ingredient is Dragon's blood"
ingredient="Dragon's blood"
if [ "$ingredient" = "Dragon's blood" ]; then
echo "The ingredient is Dragon's blood, adding it to the potion"
else
echo "The ingredient is not Dragon's blood, adding something else to the potion"
fi
# Using if-else statement
echo "Checking if the ingredient is Dragon's blood or Unicorn hair"
ingredient="Unicorn hair"
if [ "$ingredient" = "Dragon's blood" ]; then
echo "The ingredient is Dragon's blood, adding it to the potion"
elif [ "$ingredient" = "Unicorn hair" ]; then
echo "The ingredient is Unicorn hair, adding it to the potion"
else
echo "The ingredient is not Dragon's blood nor Unicorn hair, adding something else to the potion"
fi
# Using test command
echo "Checking if the number of ingredients is greater than 5"
ingredients_count=6
if test $ingredients_count -gt 5; then
echo "The number of ingredients is greater than 5"
else
echo "The number of ingredients is not greater than 5"
fi
echo "Spell cast successfully."

44
tutorials/05_loops.sh

@ -0,0 +1,44 @@
#!/bin/sh
# To make this script executable, use the command: chmod +x 04_loops.sh
# To run the script, use the command: ./04_loops.sh
echo "To study the code of the examples, please use the command: cat 04_loops.sh"
echo "This spell will teach you the basics of loops in POSIX-compliant Bash"
# Todo: give an example of using a for loop with both a number and an array (which is more like for-each)
# A for loop continues looping for as many iterations as the number of things in "in"
echo "Iterating through ingredients"
ingredients=("Dragon's blood" "Unicorn hair" "Phoenix feather")
for ingredient in "${ingredients[@]}"; do
echo " Adding $ingredient to the potion"
done
# A while loop continues as long as its test condition evaluates to true
echo "Iterating through numbers"
count=1
while test $count -le 5; do
echo " Adding number $count to the potion"
count=$((count + 1))
done
# The 'break' keyword exits out of a loop
echo "Making a second potion, only adding ingredients up through Unicorn hair"
for ingredient in "${ingredients[@]}"; do
echo " Adding $ingredient to the potion"
if [ "$ingredient" = "Unicorn hair" ]; then
echo " Found Unicorn hair, this potion is finished."
break
fi
done
# The 'continue' keyword skips ahead to the next loop iteration
echo "Making a third potion, skipping adding the Unicorn hair this time"
for ingredient in "${ingredients[@]}"; do
if [ "$ingredient" = "Unicorn hair" ]; then
echo " Found Unicorn hair, skipping adding this ingredient."
continue
fi
echo " Adding $ingredient to the potion"
done
echo "Spell cast successfully"

47
tutorials/06_functions.sh

@ -0,0 +1,47 @@
#!/bin/sh
# To make this script executable, use the command: chmod +x 05_functions.sh
# To run the script, use the command: ./05_functions.sh
echo "This spell will teach you the basics of functions in POSIX-compliant Bash"
echo "To study the code of the examples, please use the command: cat 05_functions.sh"
# Defining a function
create_potion() {
echo "Creating potion with $1 and $2"
}
# Calling a function
create_potion "Dragon's blood" "Unicorn hair"
# Defining a function with return value
calculate_price() {
echo $((10 + 20))
}
# Calling a function with return value
price=$(calculate_price)
echo "Price of the potion is $price golds"
echo "Functions can also be loaded in your .bashrc file to make them available in all terminals."
echo "For example, you can add the following line in your .bashrc file to load the 'hello' function: 'hello() { echo \"Hello, \$1\" }'"
echo "Creating a function that changes the working directory"
go_to_spell_folder() {
cd ~/spells
pwd
}
# Return statement
echo "The 'return' statement cause the function to return immediately. The return value can be captured in a variable."
my_function() {
echo "Inside the function"
return 5
echo "This line will not be executed"
}
echo "Before calling the function"
result=$(my_function)
echo "The function returned $result"
echo "After calling the function"
echo "Spell cast successfully"

26
tutorials/07_pipe.sh

@ -0,0 +1,26 @@
#!/bin/sh
# To make this script executable, use the command: chmod +x 06_pipe.sh
# To run the script, use the command: ./06_pipe.sh
echo "This spell will teach you the basics of I/O redirection and pipelines in POSIX-compliant Bash"
echo "To study the code of the examples, please use the command: cat 06_pipe.sh"
# Redirecting standard output to a file
echo "The '>' operator redirects the output of the command to the left of it and writes it to the file on the right. If the file already exists, its contents will be overwritten."
echo "Dragon's blood" > ingredient.txt
# Appending standard output to a file
echo "The '>>' operator works similar to '>', but it appends the output to the file instead of overwriting its contents."
echo "Appending to current_date.txt" >> current_date.txt
echo "Unicorn hair" >> ingredient.txt
# Redirecting standard input from a file
echo "The '<' operator redirects the contents of the file on the right as the input for the command on the left."
echo "Content of current_date.txt:"
sort < ingredient.txt
# Using pipelines
echo "The '|' operator takes the output of the command on the left and uses it as the input for the command on the right."
echo "All files in the current directory:"
ls -l | grep "^-"
echo "Spell cast successfully."

32
tutorials/08_permissions.sh

@ -0,0 +1,32 @@
#!/bin/sh
# To make this script executable, use the command: chmod +x 07_permissions.sh
# To run the script, use the command: ./07_permissions.sh
echo "This spell will teach you the basics of permissions in POSIX-compliant Bash"
echo "To study the code of the examples, please use the command: cat 07_permissions.sh"
# Execution flags
echo "The chmod command changes the permissions of a file. The permissions can be represented in two ways: octal or symbolic. "
echo "In octal representation, permissions are represented by a three-digit number, with each digit representing permissions for owner, group and others respectively. In this representation, 7 means read, write and execute permissions, 5 means read and execute permissions, and 0 means no permissions."
echo "In symbolic representation, permissions are represented by a combination of letters 'ugoa' (user, group, others, all) and '+-' (add or remove) and 'rwx' (read, write, execute) permissions. For example, 'ug+x' means add execute permission for user and group."
echo "chmod +x script.sh adds the execution flag to a script"
touch my_script.sh
chmod +x my_script.sh
ls -l my_script.sh
echo "The file my_script.sh now has the execution flag set"
echo "chmod 755 script.sh adds the execution flag and read and execute permissions for owner, group and others"
touch my_script2.sh
chmod 755 my_script2.sh
ls -l my_script2.sh
echo "The file my_script2.sh now has the execution flag and read and execute permissions for owner, group and others"
echo "chmod 700 script.sh adds the execution flag and read, write and execute permissions for owner only"
touch my_script3.sh
chmod 700 my_script3.sh
ls -l my_script3.sh
echo "The file my_script3.sh now has the execution flag and read, write and execute permissions for owner only"
echo "You can also use chown to change the ownership of a file."
echo "chown user:group script.sh changes the owner and group of the script.sh file"
echo "Spell cast successfully"

41
tutorials/09_regex.sh

@ -0,0 +1,41 @@
#!/bin/sh
# To make this script executable, use the command: chmod +x 08_regex.sh
# To run the script, use the command: ./08_regex.sh
echo "This spell will teach you the basics of regular expressions and pattern matching in POSIX-compliant Bash"
echo "To study the code of the examples, please use the command: cat 08_regex.sh"
# Basic regular expressions (special characters)
echo "Regular expressions are a way to search for patterns in text. Common special characters include:"
echo "^ - beginning of a line"
echo "$ - end of a line"
echo "* - any number of characters"
echo "? - any single character"
echo "[] - any character in the brackets"
echo "() - group characters together"
echo "| - or"
echo "\\ - escape special characters"
# grep (search in text)
echo "The grep command searches for a pattern in a file or input."
echo "grep '^root:' /etc/passwd - searches for the pattern '^root:' in the file /etc/passwd"
echo "Example: grep 'bash' /etc/passwd - searches for the pattern 'bash' in the file /etc/passwd"
grep 'bash' /etc/passwd
# sed (replace in text)
echo "The sed command is a stream editor that can perform basic text transformations on an input stream (a file or input from a pipeline)."
echo "sed 's/root/admin/' /etc/passwd - replaces the first occurence of 'root' with 'admin' in the file /etc/passwd"
echo "Example: sed 's/bash/zsh/' /etc/passwd - replaces the first occurence of 'bash' with 'zsh' in the file /etc/passwd"
echo "backup" | sed 's/backup/backup_file/'
# awk (advanced text processing)
echo "The awk command is a text processing tool that can perform more complex text transformations."
echo "awk -F: '{ print $1 }' /etc/passwd - prints the first field of each line of the file /etc/passwd, where the field separator is ':'"
awk '{ print $1 }' /etc/passwd
echo "root:x:0:0:root:/root:/bin/bash" | awk -F: '{print $1}'
# find and xargs (run command for all found files)
echo "The find command is used to search for files in a directory hierarchy. xargs is used to build and execute command lines from standard input."
echo "find / -name '*.txt' | xargs grep 'example' - searches for all .txt files in the root directory and its subdirectories, and runs 'grep 'example'' on each file found"
find /etc -name "*.conf" -exec grep "root" {} \;
echo "Spell cast successfully"

34
tutorials/10_debugging.sh

@ -0,0 +1,34 @@
#!/bin/sh
# To make this script executable, use the command: chmod +x 09_debugging.sh
# To run the script, use the command: ./09_debugging.sh
echo "This spell will teach you the basics of script debugging and error handling in POSIX-compliant Bash"
echo "To study the code of the examples, please use the command: cat 09_debugging.sh"
# echo and set -x (debugging)
echo "The echo command is used to print messages to the terminal. The set -x command enables the display of commands and their arguments as they are executed."
echo "Example: set -x; echo 'Debugging message'; set +x"
set -x; echo 'Debugging message'; set +x
# trap and signal handling (error handling)
echo "The trap command is used to catch signals sent to the script. Signals are used to communicate with processes, and are typically sent when a program needs to terminate or interrupt another program."
echo "Example: trap 'echo Signal received, exiting...; exit 0' INT; sleep 10; echo 'This line will not be executed'"
trap 'echo Signal received, exiting...; exit 0' INT; sleep 10; echo 'This line will not be executed'
# exit status and return values (error handling)
echo "Every command in Bash returns an exit status, which is the value that the command returns to the parent process. The value can be checked using the $? variable. A value of 0 indicates success, and any other value indicates failure."
echo "Example: echo $? (this should be 0)"
echo $?
# Using the exit status in a conditional statement
command
if [ $? -eq 0 ]; then
echo "Command executed successfully"
else
echo "Command failed with exit status $?"
fi
# Setting the exit status of the script
echo "You can also set the exit value of a script manually with the 'exit' command. 0 means success, every other value is an error. This script will exit with an error code of 42."
exit 42
echo "Spell cast successfully"

19
tutorials/11_aliases.sh

@ -0,0 +1,19 @@
#!/bin/sh
# To make this script executable, use the command: chmod +x 10_aliases_functions.sh
# To run the script, use the command: ./10_aliases_functions.sh
echo "This spell will teach you the basics of Aliases and Functions in POSIX-compliant Bash"
echo "To study the code of the examples, please use the command: cat 10_aliases_functions.sh"
# Aliases
echo "Creating an alias for a command"
alias ll='ls -al'
ll
echo "Aliases are used to create short, easy-to-remember commands for frequently used commands or sequences of commands."
echo "For example, we just created an alias 'll' for 'ls -al' command"
echo "Creating an alias of an alias"
alias la='ll -a'
la
echo "Spell cast successfully"

29
tutorials/12_eval.sh

@ -0,0 +1,29 @@
#!/bin/sh
echo "This spell will teach you the basics of the eval and exec functions in POSIX-compliant Bash"
echo "To study the code of the examples, please use the command: cat 11_eval.sh"
# eval function
# The eval function takes a string as an argument and treats it as if it were a command.
# It allows the user to dynamically generate and execute commands.
# Example 1: Using variables in a command
ingredient="Dragon's blood"
eval "echo Gathering ingredients for the potion: $ingredient"
# Example 2: Using command substitution
eval "echo Today is $(date)"
# Example 3: Using multiple commands
eval "echo Starting spell; sleep 2; echo Spell complete"
# exec function
# The exec function also takes a command as its argument, but it replaces the current shell process with the new command.
# This means that the new command will not run in a subshell and any changes made by the new command will affect the current shell.
# Example 1: Using exec to run a new shell
exec /bin/sh
# Example 2: Using exec to run a command
exec echo "This command is being run by exec"
echo "Spell cast successfully"

21
tutorials/13_bg.sh

@ -0,0 +1,21 @@
#!/bin/sh
# This script is a spell that will teach you about the bg and fg commands in POSIX-compliant Bash
# To study the code of the examples, please use the command: cat 12_bg.sh
echo "This spell will teach you about the bg and fg commands in POSIX-compliant Bash"
echo "To study the code of the examples, please use the command: cat 12_bg.sh"
# Running a command in the background
sleep 5 &
echo "Background task started. You can continue with other spells while waiting for it to finish."
# Listing background tasks
jobs
# Moving a background task to the foreground
fg %1
echo "Background task is now in the foreground."
# Sending a background task to the background
bg %1
echo "Foreground task is now in the background."

5
tutorials/20_advanced_terminal.sh

@ -0,0 +1,5 @@
# To move the cursor to the beginning/end of the line, use the key combination: Ctrl+A/Ctrl+E
# To delete the word before the cursor, use the key combination: Alt+Backspace
# To delete the word after the cursor, use the key combination: Alt+D

47
tutorials/21_parentheses.sh

@ -0,0 +1,47 @@
#!/bin/sh
# To make this script executable, use the command: chmod +x 21_parentheses.sh
# To run the script, use the command: ./11_parentheses.sh
echo "This spell will teach you the basics of differentiating between similar parenthetical syntax in POSIX-compliant Bash"
echo "To study the code of the examples, please use the command: cat 21_parentheses.sh"
# Using $() command substitution
echo "Using command substitution with $()"
current_date=$(date)
echo "Today's date is: $current_date"
# Using $(()) arithmetic expansion
echo "Using arithmetic expansion with $(())"
num1=5
num2=3
result=$((num1 + num2))
echo "5 + 3 = $result"
# Using string list
echo "Using string list with \"\""
ingredients="Dragon's blood Unicorn hair Phoenix feather"
echo "Ingredients: $ingredients"
# Using array
echo "Using array with ()"
ingredients=("Dragon's blood" "Unicorn hair" "Phoenix feather")
echo "Ingredients: ${ingredients[@]}"
# Using [] test command
echo "Using test command with []"
string="Dragon's blood"
if [ "$string" = "Dragon's blood" ]; then
echo "The string is Dragon's blood"
else
echo "The string is not Dragon's blood"
fi
# Using [[]] test command
echo "Using test command with [[]]"
string="Dragon's blood"
if [[ "$string" = "Dragon's blood" ]]; then
echo "The string is Dragon's blood"
else
echo "The string is not Dragon's blood"
fi
echo "Spell cast successfully."

10
tutorials/22_shebang.sh

@ -0,0 +1,10 @@
#!/bin/sh
# To make this script executable, use the command: chmod +x 22_shebang.sh
# To run the script, use the command: ./22_shebang.sh
echo "This spell will teach you the basics of script execution headers in POSIX-compliant Bash"
echo "To study the code of the examples, please use the command: cat 22_shebang.sh"
# Shebang
echo "#!/bin/sh is the shebang, it specifies the interpreter to use for running the script"
echo "#!/usr/bin/env python is an alternative shebang to use for Python scripts"
echo "#!/usr/bin/env ruby is an alternative shebang to use for Ruby scripts"

193
tutorials/23_shell_options.sh

@ -0,0 +1,193 @@
# Set command
echo "The set command is used to set or unset various shell options, as well as positional parameters."
# Setting a shell option
echo "Here we are setting the -x option, which enables the display of commands and their arguments as they are executed."
set -x
echo "This line will be displayed in the terminal, as the -x option is set."
# Unsetting a shell option
echo "Now we will unset the -x option, so command execution will no longer be displayed in the terminal."
set +x
echo "This line will not be displayed in the terminal, as the -x option is unset."
# Setting positional parameters
echo "We can also use set to set the positional parameters."
set -- "one" "two" "three"
echo "Positional parameter 1: $1"
echo "Positional parameter 2: $2"
echo "Positional parameter 3: $3"
echo "The set command allows for greater control over shell options and positional parameters."
echo "This spell will teach you about the 'set' command and different shell options in POSIX-compliant Bash"
echo "To study the code of the examples, please use the command: cat 07_variables.sh"
# Setting shell options
echo "Setting the 'errexit' option, which exits the script if any command returns a non-zero exit status"
set -e
# Using set -e to exit the script if a command fails
echo "Creating a file with touch command, which will not return a non-zero exit status"
touch example.txt
echo "Creating a file with a non-existent command, which will return a non-zero exit status and cause the script to exit"
nonexistentCommand
echo "This line will not be executed because the script exits on the previous command"
# Unsetting shell options
echo "Unsetting the 'errexit' option"
set +e
# Using set +e to continue the script even if a command fails
echo "Creating a file with a non-existent command, which will return a non-zero exit status but the script will continue"
nonexistentCommand
echo "This line will be executed because the script does not exit on the previous command"
echo "The spell has been cast successfully"
#!/bin/sh
# This script is a spell that will teach you about various shell options in POSIX-compliant Bash
# To study the code of the examples, please use the command: cat 12_shell_options.sh
# Setting the -u option
echo "Setting the -u option: unset variables will cause an error"
set -u
# Demonstrating the effect of the -u option
echo "Value of unset variable: $unset_variable"
# Setting the -e option
echo "Setting the -e option: commands that return non-zero exit status will cause an error"
set -e
# Demonstrating the effect of the -e option
echo "This command will fail: false"
# Setting the -f option
echo "Setting the -f option: file name generation using wildcard characters will be disabled"
set -f
# Demonstrating the effect of the -f option
echo "List of files: *"
echo "Casting the spell is finished, check the code of the spell by using 'cat 12_shell_options.sh' command"
# This script is a spell that will teach you about the n, v, and o options in POSIX-compliant Bash.
# To study the code of the examples, please use the command: cat 12_shell_options_2.sh
echo "This spell will teach you about the n, v, and o options in POSIX-compliant Bash"
echo "Using the -n option to prevent execution of the commands"
set -n
echo "This line won't be executed"
set +n
echo "Using the -v option to print commands before execution"
set -v
echo "This line will be printed before execution"
set +v
echo "Using the -o option to set an option"
set -o nounset
echo "This line will trigger an error if the variable is not set"
set +o nounset
echo "Casting the spell is finished, check the code of the spell by using 'cat 12_shell_options_2.sh' command"
# This script is a spell that will teach you about some additional shell options in POSIX-compliant Bash.
# To study the code of the examples, please use the command: cat script_name.sh
# -u option: Treat unset variables as an error and exit
# This will cause the script to exit if an unset variable is used
set -u
echo "Using unset variable: $unset_variable" # This will cause the script to exit with an error
# -C option: Prevent file overwriting with >
# This will cause the script to exit if the file already exists
set -C
echo "Hello World" > existing_file.txt # This will cause the script to exit with an error
# -B option: Enable brace expansion
echo {a,b,c} # This will print "a b c"
echo {1..3} # This will print "1 2 3"
# -e option: Exit immediately if a command exits with a non-zero status
set -e
ls does_not_exist.txt # This will cause the script to exit with an error
echo "Casting the spell is finished, check the code of the spell by using 'cat script_name.sh' command"
# This script is a spell that will teach you about some advanced shell options in POSIX-compliant Bash
# -m: monitor mode
# This option will automatically exit the shell when all jobs have completed
set -m
sleep 10 &
wait
echo "All jobs have completed and the shell has exited"
# -r: restricted mode
# This option will restrict the shell's abilities, making it more secure by disabling certain dangerous commands
set -r
echo "This line will be executed"
cp /etc/passwd /tmp/passwd # this command will be disabled and the script will exit with an error
echo "This line won't be executed"
# -s: silent mode
# This option will make the shell more silent by not printing commands before they are executed
set -s
echo "This line will be executed"<