mirror of
https://github.com/ViViDboarder/shoestrap.git
synced 2024-11-21 21:26:31 +00:00
453 lines
9.7 KiB
Bash
453 lines
9.7 KiB
Bash
#!/bin/bash
|
|
|
|
##############################################################################
|
|
# DO NOT MODIFY THIS FILE. Instead, modify 'helpers/custom'.
|
|
##############################################################################
|
|
|
|
COOKBOOK_NAME="$(basename "$0")"
|
|
if [ -z "$SHOESTRAP_BASE" ]; then
|
|
DIR="$( cd "$( dirname "$0" )" && pwd )"
|
|
else
|
|
DIR="$SHOESTRAP_BASE"
|
|
fi
|
|
|
|
CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/shoestrap"
|
|
|
|
#
|
|
# Run a given recipe.
|
|
#
|
|
# Arguments can be passed to the 'recipe' function. They will be accessible by
|
|
# the recipe as $2, $3, $4, etc.
|
|
#
|
|
recipe () {
|
|
CURRENT_RECIPE_NAME=$1
|
|
DEFAULT_ASSETS_PATH="$DIR/assets/default/$CURRENT_RECIPE_NAME"
|
|
COOKBOOK_ASSETS_PATH="$DIR/assets/$COOKBOOK_NAME/$CURRENT_RECIPE_NAME"
|
|
local default_recipe="$DIR/recipes/default/$CURRENT_RECIPE_NAME"
|
|
local cookbook_recipe="$DIR/recipes/$COOKBOOK_NAME/$CURRENT_RECIPE_NAME"
|
|
|
|
if [ -f "$cookbook_recipe" ]; then
|
|
log "Running recipe '$cookbook_recipe'..." 1
|
|
separator
|
|
# shellcheck source=/dev/null
|
|
. "$cookbook_recipe"
|
|
elif [ -f "$default_recipe" ]; then
|
|
log "Running recipe '$default_recipe'..." 1
|
|
separator
|
|
# shellcheck source=/dev/null
|
|
. "$default_recipe"
|
|
else
|
|
error "Could not find recipe for '$CURRENT_RECIPE_NAME'. Fail!"
|
|
fi
|
|
|
|
cd "$DIR" || error "Failed to find recipe"
|
|
}
|
|
|
|
#
|
|
# Prints the 'finished' banner.
|
|
#
|
|
finished () {
|
|
spacer 1
|
|
separator "="
|
|
echo " FINISHED: '$COOKBOOK_NAME'"
|
|
separator "="
|
|
spacer 1
|
|
}
|
|
|
|
#
|
|
# Writes a log line to the screen
|
|
#
|
|
# If specified, the first parameter is the number of empty lines to print
|
|
# before the log message.
|
|
#
|
|
# If specified, the second parameter is the number of empty lines to print
|
|
# before the log message.
|
|
#
|
|
log () {
|
|
if [[ $2 -gt 0 ]]; then
|
|
spacer "$2"
|
|
fi
|
|
|
|
echo " * $1"
|
|
|
|
if [[ $3 -gt 0 ]]; then
|
|
spacer "$3"
|
|
fi
|
|
}
|
|
|
|
#
|
|
# Writes an error log line to the screen and exit with an error code.
|
|
#
|
|
error () {
|
|
spacer 2
|
|
echo " -> $1"
|
|
spacer 2
|
|
exit 1
|
|
}
|
|
|
|
#
|
|
# Write one or many empty lines to the screen.
|
|
#
|
|
spacer () {
|
|
if [ -n "$1" ]; then
|
|
local spaces=$1
|
|
else
|
|
local spaces=1
|
|
fi
|
|
|
|
for (( i=0; i<spaces; i++ )) do
|
|
echo ""
|
|
done
|
|
}
|
|
|
|
#
|
|
# noop
|
|
#
|
|
noop () {
|
|
return 0
|
|
}
|
|
|
|
#
|
|
# Write a separator to the screen.
|
|
#
|
|
# You can optionally specify the separator character. Default is '-'.
|
|
#
|
|
separator () {
|
|
if [ -n "$1" ]; then
|
|
local char=$1
|
|
else
|
|
local char='-'
|
|
fi
|
|
|
|
local width=""
|
|
width=$(tput cols)
|
|
|
|
for (( i=0; i < width-2; i++ )) do
|
|
local output="$output$char"
|
|
done
|
|
echo "$output"
|
|
}
|
|
|
|
#
|
|
# Update packages in package manager.
|
|
#
|
|
sudo_package_update () {
|
|
log "Updating package manager..." 0 1
|
|
detect_package_manager
|
|
|
|
if [ "$PACKAGE_MANAGER" == 'apt-get' ]; then
|
|
sudo apt-get update -y
|
|
elif [ "$PACKAGE_MANAGER" == 'yum' ]; then
|
|
sudo yum check-update -y
|
|
elif [ "$PACKAGE_MANAGER" == 'port' ]; then
|
|
sudo port selfupdate
|
|
elif [ "$PACKAGE_MANAGER" == 'brew' ]; then
|
|
brew update
|
|
elif [ "$PACKAGE_MANAGER" == 'apk' ]; then
|
|
true
|
|
else
|
|
error "Unknown package manager: $PACKAGE_MANAGER"
|
|
fi
|
|
|
|
# shellcheck disable=2181
|
|
if [ $? -ne 0 ]; then
|
|
error "An error occured while updating packages. Fail!"
|
|
else
|
|
spacer 2
|
|
fi
|
|
}
|
|
|
|
#
|
|
# Install a package or packages through package manager
|
|
#
|
|
sudo_package () {
|
|
log "Installing packages '$*'..."
|
|
detect_package_manager
|
|
|
|
if [ "$PACKAGE_MANAGER" == 'apt-get' ]; then
|
|
# shellcheck disable=2086,2048
|
|
sudo env DEBIAN_FRONTEND=noninteractive apt-get install -y $*
|
|
elif [ "$PACKAGE_MANAGER" == 'yum' ]; then
|
|
# shellcheck disable=2086,2048
|
|
sudo yum install -y $*
|
|
elif [ "$PACKAGE_MANAGER" == 'port' ]; then
|
|
# Unintuitive, but this skips all promps which should assume Y
|
|
# shellcheck disable=2086,2048
|
|
sudo port -N install $*
|
|
elif [ "$PACKAGE_MANAGER" == 'brew' ]; then
|
|
# shellcheck disable=2086,2048
|
|
brew install $*
|
|
elif [ "$PACKAGE_MANAGER" == 'apk' ]; then
|
|
# shellcheck disable=2086,2048
|
|
apk add $*
|
|
else
|
|
error "Unknown package manager: $PACKAGE_MANAGER"
|
|
fi
|
|
|
|
# shellcheck disable=2181
|
|
if [ $? -ne 0 ]; then
|
|
error "An error occured while installing packages. Fail!"
|
|
else
|
|
spacer 2
|
|
fi
|
|
}
|
|
|
|
#
|
|
# Determine if a package is installed or not.
|
|
#
|
|
# If package is installed, function will return 0. If not, it will return 1.
|
|
#
|
|
test_package_installed () {
|
|
detect_package_manager
|
|
|
|
# When many packages are specified, skip test.
|
|
if [ $# -gt 1 ]; then
|
|
return 1
|
|
fi
|
|
|
|
if [ "$PACKAGE_MANAGER" == 'apt-get' ]; then
|
|
dpkg-query -l "$1" | grep -q ^.i
|
|
return $?
|
|
fi
|
|
|
|
# Don't know how to detect if a package is installed with other package managers.
|
|
return 1
|
|
}
|
|
|
|
#
|
|
# Determine which package manager is in use on the system.
|
|
#
|
|
detect_package_manager () {
|
|
if [ "$PACKAGE_MANAGER" != "" ]; then
|
|
return 0
|
|
fi
|
|
|
|
if command_exist apt-get; then
|
|
PACKAGE_MANAGER='apt-get'
|
|
elif command_exist yum; then
|
|
PACKAGE_MANAGER='yum'
|
|
elif command_exist port; then
|
|
PACKAGE_MANAGER='port'
|
|
elif command_exist brew; then
|
|
PACKAGE_MANAGER='brew'
|
|
elif command_exist 'apk'; then
|
|
PACKAGE_MANAGER='apk'
|
|
else
|
|
error "Could not find a package manager. Fail!"
|
|
fi
|
|
|
|
log "Detected package manager: $PACKAGE_MANAGER"
|
|
return 0
|
|
}
|
|
|
|
#
|
|
# Determines if a command exist on the system.
|
|
#
|
|
command_exist () {
|
|
command -v "$1" > /dev/null 2>&1;
|
|
}
|
|
|
|
#
|
|
# Copy a file from the assets folder to the specified location.
|
|
#
|
|
copy () {
|
|
local cookbook_assets_source="$COOKBOOK_ASSETS_PATH/$1"
|
|
local default_assets_source="$DEFAULT_ASSETS_PATH/$1"
|
|
local target="$2"
|
|
|
|
if [ -f "$cookbook_assets_source" ]; then
|
|
log "Copying $cookbook_assets_source to $target..."
|
|
cp "$cookbook_assets_source" "$target"
|
|
elif [ -f "$default_assets_source" ]; then
|
|
log "Copying $default_assets_source to $target..."
|
|
cp "$default_assets_source" "$target"
|
|
else
|
|
error "Could not find '$1' to copy. Fail!"
|
|
fi
|
|
}
|
|
|
|
#
|
|
# Link a file from the assets folder to the specified location.
|
|
#
|
|
link () {
|
|
local src="$1"
|
|
local cookbook_assets_source="$COOKBOOK_ASSETS_PATH/$1"
|
|
local default_assets_source="$DEFAULT_ASSETS_PATH/$1"
|
|
local target="$2"
|
|
|
|
if [ -f "$src" ]; then
|
|
src="$src"
|
|
elif [ -d "$src" ]; then
|
|
src="$src"
|
|
elif [ -f "$cookbook_assets_source" ]; then
|
|
src="$cookbook_assets_source"
|
|
elif [ -f "$default_assets_source" ]; then
|
|
src="$default_assets_source"
|
|
elif [ -d "$cookbook_assets_source" ]; then
|
|
src="$cookbook_assets_source"
|
|
elif [ -d "$default_assets_source" ]; then
|
|
src="$default_assets_source"
|
|
else
|
|
error "Could not find '$1' to link Fail!"
|
|
fi
|
|
|
|
ln -s "$src" "$target"
|
|
}
|
|
|
|
#
|
|
# Attempt to link a file if it doesn't already exist
|
|
#
|
|
try_link () {
|
|
local src="$1"
|
|
local cookbook_assets_source="$COOKBOOK_ASSETS_PATH/$1"
|
|
local default_assets_source="$DEFAULT_ASSETS_PATH/$1"
|
|
local target="$2"
|
|
|
|
if [ -f "$src" ]; then
|
|
src="$src"
|
|
elif [ -d "$src" ]; then
|
|
src="$src"
|
|
elif [ -f "$cookbook_assets_source" ]; then
|
|
src="$cookbook_assets_source"
|
|
elif [ -f "$default_assets_source" ]; then
|
|
src="$default_assets_source"
|
|
elif [ -d "$cookbook_assets_source" ]; then
|
|
src="$cookbook_assets_source"
|
|
elif [ -d "$default_assets_source" ]; then
|
|
src="$default_assets_source"
|
|
else
|
|
error "Could not find '$1' to link Fail!"
|
|
fi
|
|
|
|
if [ -L "$2" ] && [ "$(readlink "$2")" == "$src" ] ; then
|
|
log "Link already exists: $2"
|
|
else
|
|
log "Creating link: $2 -> $src"
|
|
link "$1" "$2"
|
|
fi
|
|
}
|
|
|
|
#
|
|
# Add a user to the system.
|
|
#
|
|
add_user () {
|
|
local user=$1
|
|
local pass=$2
|
|
local args=$3
|
|
|
|
if id "$user" > /dev/null 2>&1 ; then
|
|
log "User $user already exists. Skipped creation."
|
|
else
|
|
log "Adding user $user..."
|
|
[ "$pass" == "" ] && pass=generate_password
|
|
|
|
if [[ "$args" != *nohome* ]]; then
|
|
/usr/sbin/useradd --password "$(openssl passwd -crypt "$pass")" --create-home "$user" --shell /bin/bash
|
|
else
|
|
/usr/sbin/useradd --password "$(openssl passwd -crypt "$pass")" "$user" --shell /bin/bash
|
|
fi
|
|
fi
|
|
}
|
|
|
|
#
|
|
# Generate a random password.
|
|
#
|
|
generate_password() {
|
|
local l=$1
|
|
[ "$l" == "" ] && l=8
|
|
tr -dc A-Za-z0-9_ < /dev/urandom | head -c ${l} | xargs
|
|
}
|
|
|
|
#
|
|
# Run a command as another user
|
|
#
|
|
run_as () {
|
|
local user=$1
|
|
local cmd=$2
|
|
log "Running command as '$user'..."
|
|
log "$cmd"
|
|
# sudo -u $user -H -s /bin/bash -c "$cmd"
|
|
# sudo -u $user -s /bin/bash -i "$cmd"
|
|
su -c "$cmd" -s /bin/bash "$user"
|
|
}
|
|
|
|
#
|
|
# Add line to a file if line is not already present
|
|
#
|
|
add_line () {
|
|
local line="$1"
|
|
local file="$2"
|
|
grep "$line" "$file" > /dev/null 2>&1
|
|
|
|
# shellcheck disable=2181
|
|
if [ $? -ne 0 ]; then
|
|
log "Adding '$line' to '$file'..."
|
|
echo "$line" >> "$file"
|
|
else
|
|
log "'$line' already in '$file'. Skipping."
|
|
fi
|
|
}
|
|
|
|
#
|
|
# Write a warning if user is not root.
|
|
#
|
|
warn_if_not_root () {
|
|
[ "$(id -u)" = "0" ] ||
|
|
{ echo "WARNING: You are NOT running this script as 'root'. You might want to consider that..."; }
|
|
}
|
|
|
|
#
|
|
# Stops the execution of the script if user is not root.
|
|
#
|
|
fail_if_not_root () {
|
|
[ "$(id -u)" = "0" ] || { echo "You must run this as 'root'. Exiting."; exit 1; }
|
|
}
|
|
|
|
#
|
|
# Checks if a certain element has already been installed.
|
|
#
|
|
is_installed () {
|
|
local args=$*
|
|
local name=${args//[ \/:@]/-}
|
|
|
|
if [[ -f "$CONFIG_DIR/installed/$name" ]]; then
|
|
log "'$name' is already installed."
|
|
return 0
|
|
else
|
|
log "'$name' is not installed."
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
#
|
|
# Sets an element as installed.
|
|
#
|
|
set_installed () {
|
|
local args=$*
|
|
local name=${args//[ \/:@]/-}
|
|
|
|
mkdir -p "$CONFIG_DIR/installed"
|
|
touch "$CONFIG_DIR/installed/$name"
|
|
}
|
|
|
|
#
|
|
# Promts a user for a Yn confirmation
|
|
#
|
|
|
|
prompt_yn () {
|
|
read -p "$1 [y/n] " -n 1 -r
|
|
echo # move to a new line
|
|
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
|
return 0
|
|
fi
|
|
|
|
return 1
|
|
}
|
|
|
|
#
|
|
# Prompt any key
|
|
#
|
|
prompt_any () {
|
|
read -p "Press any key key to continue..." -n1 -s -r
|
|
}
|