280 lines
7.8 KiB
Bash
Executable File
280 lines
7.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# ------------------------------------------------------------------------------
|
|
# Init.sh: initialise a computer and conform it
|
|
# Copyright (c) 2019-2021 Geoffray Levasseur <fatalerrors@geoffray-levasseur.org>
|
|
# ------------------------------------------------------------------------------
|
|
# This file is distributed under 3-clause BSD license.
|
|
# The complete license agreement can be obtained at:
|
|
# https://opensource.org/licenses/BSD-3-Clause
|
|
# ------------------------------------------------------------------------------
|
|
# Global variables:
|
|
# * INSTALL_MODE: if "dev" is declared here, packages will be installed one by
|
|
# one instead of sending the whole package list to the package manager
|
|
# * LOGFILE: Define manually output log file name. Can be superseeded through
|
|
# command line parameter. ATTENTION: That variable cannot be set in
|
|
# configuration file as it is treated before loading those, so it must be
|
|
# defined before calling that script.
|
|
# ------------------------------------------------------------------------------
|
|
|
|
|
|
# trace ERR through pipes
|
|
set -o pipefail
|
|
|
|
# trace ERR through 'time command' and other functions
|
|
set -o errtrace
|
|
|
|
# set -e : exit the script if any statement returns a non-true return value
|
|
# This is overloaded by aaa_error.sh lib (but usefull for initialisation)
|
|
set -o errexit
|
|
|
|
# set +u: allow undeclared variables because our configuration files don't need
|
|
# to be complete (even if it's bad practice)
|
|
set +o nounset
|
|
|
|
# We want english messages, all the time (can be redefined in configuration)
|
|
export LC_ALL=C
|
|
export LANG=C
|
|
|
|
# Version of init
|
|
export VERSION="0.99.20"
|
|
|
|
# Store script's path (realpath -s resolve symlinks if init.sh is a symlink)
|
|
export MYPATH=$(dirname "$(realpath -s "$0")")
|
|
|
|
# Get hostname
|
|
export HOSTNAME=$(hostname)
|
|
|
|
# Load libraries
|
|
for lib in $MYPATH/lib/*.sh; do
|
|
. "$lib"
|
|
done
|
|
unset lib
|
|
|
|
# =============================
|
|
# ==== Basic sanity checks ====
|
|
# =============================
|
|
|
|
# We only test prnt which is not optimal, we should do deeper tests
|
|
function_exists prnt || (
|
|
echo "*** FATAL ERROR!"
|
|
echo "*** Some vital functions comming from libraries are missing."
|
|
exit 3
|
|
)
|
|
|
|
# ======================
|
|
# ==== Main Program ====
|
|
# ======================
|
|
|
|
# Set system dependent vars (arch, OS, distro and version)
|
|
set_sys_vars $(uname -m) $(get_os_version)
|
|
|
|
# Initializing global variables
|
|
export CHECK_ONLY=false
|
|
export JUMP=false
|
|
export KEEPGOING=false
|
|
export RESUME=false
|
|
export STAGE_FILE="$MYPATH/stage"
|
|
|
|
read_commandline $@
|
|
|
|
# After this we need to be root
|
|
# (--help and --version are allowed as unprivileged user)
|
|
check_root
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Logfile variable treatment -- cannot be a function
|
|
|
|
if [[ -n "$NEW_LOGFILE" ]]; then
|
|
export LOGFILE="$NEW_LOGFILE"
|
|
else
|
|
export LOGFILE=${LOGFILE:-"$MYPATH/log/init-$(uname -n)-$(stdtime).log"}
|
|
fi
|
|
|
|
prnt I "Creating log files welcoming directory..."
|
|
if [[ ! -d $(dirname "$LOGFILE") ]]; then
|
|
mkdir -pv $(dirname "$LOGFILE")
|
|
fi
|
|
|
|
# Log all outputs to the logfile
|
|
exec 3>&1 4>&2
|
|
trap 'exec 2>&4 1>&3' 0 1 2 3
|
|
exec > >(tee -a "$LOGFILE")
|
|
exec 2> >(tee -a "$LOGFILE" >&2)
|
|
prnt I "Starting init.sh version $VERSION."
|
|
prnt I "The log file is $LOGFILE."
|
|
if [[ -n $SYS_CODE ]]; then
|
|
prnt I "Launch on $SYS_DIST version $SYS_VER ($SYS_CODE) on $SYS_ARCH architecture"
|
|
else
|
|
prnt I "Launch on $SYS_DIST version $SYS_VER on $SYS_ARCH architecture"
|
|
fi
|
|
|
|
# -- Cannot be a function ends here
|
|
# ------------------------------------------------------------------------------
|
|
|
|
separator
|
|
|
|
if [[ -n "$CHROOT_PATH" && -z $CHROOT_DONE ]]; then
|
|
chroot_bootstrap $@
|
|
prnt I "Normal end of chrooted execution!"
|
|
exit 0
|
|
fi
|
|
|
|
load_autoconf
|
|
|
|
load_configuration
|
|
|
|
load_prepost_actions
|
|
|
|
process_commandline_and_vars
|
|
|
|
set_system_proxy
|
|
|
|
# Loading activated modules
|
|
for mod in $MODULE_LIST; do
|
|
. modules/$mod.sh
|
|
done
|
|
unset mod
|
|
|
|
separator
|
|
|
|
if [[ $RUN_SHELL == true ]]; then
|
|
prnt I "Launching an interactive shell..."
|
|
bash --rcfile "$MYPATH/bash.rc" -i
|
|
prnt I "Script execution terminated after interactive shell execution."
|
|
exit 0
|
|
fi
|
|
|
|
# If cron mode, run cron tasks then exit
|
|
if [[ $CRON_MODE == true ]]; then
|
|
for mod in $MODULE_LIST; do
|
|
if [[ $(function_exists cron_$mod) ]]; then
|
|
prnt I "Running cron task for module $mod ..."
|
|
cron_$mod
|
|
else
|
|
prnt I "No cron task for module $mod."
|
|
fi
|
|
done
|
|
prnt I "All cron executed successfully!"
|
|
exit 0
|
|
fi
|
|
|
|
# Install basic dependencies if needed
|
|
if ! command -v wget &> /dev/null; then
|
|
prnt I "Installing wget as a requirement for init.sh to work..."
|
|
pkginst wget
|
|
fi
|
|
|
|
# Run prechecks
|
|
if [[ $JUMP != true ]]; then
|
|
tmpfile="$(mktemp /tmp/init-XXXXXX)"
|
|
if [[ -n $MANUAL_MODULE_LIST ]]; then
|
|
prnt W "Dependency checks are deactivated with a manual module list."
|
|
fi
|
|
if [[ $NO_DEPS == true ]]; then
|
|
prnt W "Dependency checks have been deactivated manually."
|
|
fi
|
|
if [[ $RESUME == true ]]; then
|
|
cat "$STAGE_FILE" >> $tmpfile
|
|
fi
|
|
for mod in $MODULE_LIST; do
|
|
version=VER_$mod
|
|
if [[ $RESUME == true ]] && [[ $(grep $mod "$STAGE_FILE") ]]; then
|
|
prnt I "Checks previously executed for $mod version ${!version}."
|
|
continue
|
|
fi
|
|
prnt I "Running initial checks for $mod version ${!version}..."
|
|
if [[ -z $MANUAL_MODULE_LIST && $NO_DEPS != true ]]; then
|
|
deps=DEP_$mod
|
|
for dep in ${!deps}; do
|
|
if [[ ! $(grep $dep "$tmpfile") ]]; then
|
|
prnt E "Module $mod have unsatisfied dependencies or is executed too early."
|
|
prnt E " * $dep must be executed before $mod, please check your module list."
|
|
die 9
|
|
fi
|
|
done
|
|
unset deps
|
|
fi
|
|
# We run in a subshell to protect main environment
|
|
(
|
|
precheck_$mod
|
|
)
|
|
echo $mod >> "$tmpfile"
|
|
done
|
|
rm -f "$tmpfile"
|
|
unset mod
|
|
fi
|
|
|
|
# If we only checks, we stop here
|
|
if [[ $CHECK_ONLY == true ]]; then
|
|
prnt I "Checking mode only, not going any further."
|
|
exit 0
|
|
fi
|
|
|
|
if [[ $JUMP == true ]]; then
|
|
prnt W "Not doing any checks, please use with care!"
|
|
else
|
|
prnt I "All checks have been run successfully."
|
|
fi
|
|
echo && separator && echo
|
|
|
|
if [[ $KEEPGOING == true ]]; then
|
|
echo -e "${BRed}ATTENTION : You asked to continue the script even if error occurs.${DEFAULTCOL}"
|
|
echo -e "${BRed}ATTENTION : That option could produce some chaotic results.${DEFAULTCOL}"
|
|
echo -e "${BRed}ATTENTION : That option should be only used on test systems.${DEFAULTCOL}"
|
|
echo
|
|
fi
|
|
echo -e "${BYellow}If you continue after that step system will have changes!${DEFAULTCOL}"
|
|
echo
|
|
|
|
dump_key_buffer
|
|
read -n 1 -rsp $"Press <C> key to continue or an other one to stop now..." key && echo
|
|
|
|
echo && separator && echo
|
|
|
|
if [[ $key == "C" || $key == 'c' ]]; then
|
|
# Reinit stage file if no resuming
|
|
if [[ $RESUME != true ]] && [[ -f $STAGE_FILE ]]; then
|
|
rm -f "$STAGE_FILE"
|
|
fi
|
|
|
|
# We launch modules one after one
|
|
for mod in $MODULE_LIST; do
|
|
if [[ $RESUME == true ]] && [[ $(grep $mod "$STAGE_FILE") ]]; then
|
|
continue
|
|
fi
|
|
# We need this only if JUMP is set but doesn't matter if it's done again
|
|
version=VER_$mod
|
|
prnt I "Applying changes for $mod version ${!version}..."
|
|
# Yet again, executed in a subshell
|
|
(
|
|
export REBOOT_NEEDED=false
|
|
$mod
|
|
if [[ $REBOOT_NEEDED == true ]]; then
|
|
echo "$mod reboot" >> "$STAGE_FILE" # Mark as done for resuming
|
|
else
|
|
echo "$mod" >> "$STAGE_FILE" # Mark as done for resuming function
|
|
fi
|
|
)
|
|
separator
|
|
done
|
|
unset mod
|
|
else
|
|
echo -e "${Yellow}The system has not undergone any modification.${DEFAULTCOL}"
|
|
fi
|
|
|
|
prnt I "That's all folks !"
|
|
echo
|
|
|
|
if [[ -s "$STAGE_FILE" && $(grep " reboot" "$STAGE_FILE") ]]; then
|
|
prnt W "A reboot is required to apply some changes by the following packages:"
|
|
prnt m " * $(grep ' reboot' "$STAGE_FILE" | \
|
|
sed 's/ reboot//' | \
|
|
sed ':a' -e 'N' -e '$!ba' -e 's/\n/ /g')"
|
|
prnt I "Please reboot now or as soon as possible!"
|
|
echo
|
|
fi
|
|
|
|
rm -f "$STAGE_FILE"
|
|
exit 0
|
|
# EOF
|