From 7f678baa64ef1344e7d5212c3853f9b386a723718b5614f68fb06d9b9ab3bccd Mon Sep 17 00:00:00 2001 From: "Marc S. Weidner" Date: Tue, 7 Oct 2025 00:08:40 +0100 Subject: [PATCH] V8.13.048.2025.10.06 Signed-off-by: Marc S. Weidner --- .../trigger/t_generate_PRIVATE_trixie_1.yaml | 2 +- lib/lib_arg_parser.sh | 45 ++++++++----- lib/lib_arg_priority_check.sh | 22 ++++++- lib/lib_boot_screen.sh | 21 ++++-- lib/lib_cdi.sh | 11 +++- lib/lib_change_splash.sh | 13 +++- lib/lib_check_dhcp.sh | 11 +++- lib/lib_check_hooks.sh | 18 ++++- lib/lib_check_kernel.sh | 23 ++++++- lib/lib_check_pkgs.sh | 29 ++++++++- lib/lib_check_provider.sh | 11 +++- lib/lib_check_stats.sh | 11 +++- lib/lib_check_var.sh | 17 ++++- lib/lib_clean_screen.sh | 5 +- scripts/9000-cdi-starter | 65 ++++++++++++++----- 15 files changed, 249 insertions(+), 55 deletions(-) diff --git a/.gitea/trigger/t_generate_PRIVATE_trixie_1.yaml b/.gitea/trigger/t_generate_PRIVATE_trixie_1.yaml index a035741..4888026 100644 --- a/.gitea/trigger/t_generate_PRIVATE_trixie_1.yaml +++ b/.gitea/trigger/t_generate_PRIVATE_trixie_1.yaml @@ -10,6 +10,6 @@ # SPDX-Security-Contact: security@coresecret.eu build: - counter: 1024 + counter: 1023 version: V8.13.048.2025.10.06 # vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=yaml diff --git a/lib/lib_arg_parser.sh b/lib/lib_arg_parser.sh index 5fe99b8..ebf9fa7 100644 --- a/lib/lib_arg_parser.sh +++ b/lib/lib_arg_parser.sh @@ -17,22 +17,6 @@ guard_sourcing # Globals: # ARY_HANDLER_JUMPHOST # ARY_HANDLER_NETCUP_IPV6 -# ERR_ARG_MSMTCH -# ERR_CONTROL_CT -# ERR_MISS_PWD_F -# ERR_MISS_PWD_P -# ERR_NOTABSPATH -# ERR_OWNS_PWD_F -# ERR_PASS_LENGH -# ERR_PASS_PLICY -# ERR_REIONICE_P -# ERR_REIO_C_VAL -# ERR_REIO_P_VAL -# ERR_RENICE_PRI -# ERR_RGHT_PWD_F -# ERR_SPLASH_PNG -# ERR_UNCRITICAL -# ERR__SSH__PORT # VAR_ARCHITECTURE # VAR_BUILD_LOG # VAR_EARLY_DEBUG @@ -49,14 +33,35 @@ guard_sourcing # VAR_ISO8601 # VAR_REIONICE_CLASS # VAR_REIONICE_PRIORITY +# VAR_SSHFP # VAR_SSHPORT # VAR_SSHPUBKEY +# VAR_SUITE # Arguments: -# None +# None +# Returns: +# 0: on success +# ERR_ARG_MSMTCH: on failure +# ERR_CONTROL_CT: on failure +# ERR_MISS_PWD_F: on failure +# ERR_MISS_PWD_P: on failure +# ERR_NOTABSPATH: on failure +# ERR_OWNS_PWD_F: on failure +# ERR_PASS_LENGH: on failure +# ERR_PASS_PLICY: on failure +# ERR_REIONICE_P: on failure +# ERR_REIO_C_VAL: on failure +# ERR_REIO_P_VAL: on failure +# ERR_RENICE_PRI: on failure +# ERR_RGHT_PWD_F: on failure +# ERR_SPLASH_PNG: on failure +# ERR__SSH__PORT: on failure ####################################### arg_parser() { while [[ $# -gt 0 ]]; do + declare argument="${1}" + case "${argument,,}" in -a=* | --autobuild=*) @@ -421,6 +426,12 @@ arg_parser() { usage ;; esac + done + + return 0 } +### Prevents accidental 'unset -f'. +# shellcheck disable=SC2034 +readonly -f arg_parser # vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh diff --git a/lib/lib_arg_priority_check.sh b/lib/lib_arg_priority_check.sh index 8d2e99e..1e67e21 100644 --- a/lib/lib_arg_priority_check.sh +++ b/lib/lib_arg_priority_check.sh @@ -19,34 +19,54 @@ guard_sourcing # VAR_REIONICE_CLASS # VAR_REIONICE_PRIORITY # Arguments: -# None +# None +# Returns: +# 0: on success ####################################### arg_priority_check() { declare var + ### Check if nice PRIORITY is set and adjust nice priority. if [[ "${VAR_HANDLER_PRIORITY:-}" -ne 0 ]]; then + if command -v renice >/dev/null; then + renice "${VAR_HANDLER_PRIORITY}" -p "$$" var=$(ps -o ni= -p $$) > /dev/null 2>&1 printf "\e[92m++++ ++++ ++++ ++++ ++++ ++++ ++ โœ… New renice value: %s\e[0m\n" "${var}" # sleep 1 unset var + else + printf "\e[93m++++ ++++ ++++ ++++ ++++ ++++ ++ โŒ renice not installed (util-linux) \e[0m\n" + fi + fi ### Check if ionice PRIORITY is set and adjust ionice priority. if [[ "${VAR_REIONICE_CLASS:-}" -ne 2 ]]; then + if command -v ionice >/dev/null; then + ionice -c"${VAR_REIONICE_CLASS:-2}" -n"${VAR_REIONICE_PRIORITY:-4}" -p "$$" var=$(ionice -p $$) > /dev/null 2>&1 printf "\e[92m++++ ++++ ++++ ++++ ++++ ++++ ++ โœ… New ionice value: %s\e[0m\n" "${var}" # sleep 1 unset var + else + printf "\e[93m++++ ++++ ++++ ++++ ++++ ++++ ++ โŒ ionice not installed (util-linux) \e[0m\n" + fi + fi + + return 0 } +### Prevents accidental 'unset -f'. +# shellcheck disable=SC2034 +readonly -f arg_priority_check # vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh diff --git a/lib/lib_boot_screen.sh b/lib/lib_boot_screen.sh index 86cdfd1..813883a 100644 --- a/lib/lib_boot_screen.sh +++ b/lib/lib_boot_screen.sh @@ -18,7 +18,9 @@ guard_sourcing # PID_BOOT_SCREEN # PIPE_BOOT_SCREEN # Arguments: -# None +# None +# Returns: +# 0: on success ####################################### boot_screen() { clear @@ -34,15 +36,22 @@ boot_screen() { < "${PIPE_BOOT_SCREEN}" & declare -gr PID_BOOT_SCREEN="$!" exec 3> "${PIPE_BOOT_SCREEN}" + + return 0 } +### Prevents accidental 'unset -f'. +# shellcheck disable=SC2034 +readonly -f boot_screen ####################################### # Boot Screen Terminal Cleaner # Globals: -# boot_screen_pid -# boot_screen_pipe +# PID_BOOT_SCREEN +# PIPE_BOOT_SCREEN # Arguments: -# None +# None +# Returns: +# 0: on success ####################################### boot_screen_cleaner() { exec 3>&- @@ -51,5 +60,9 @@ boot_screen_cleaner() { rm -f "${PIPE_BOOT_SCREEN}" clean_screen sleep 1 + return 0 } +### Prevents accidental 'unset -f'. +# shellcheck disable=SC2034 +readonly -f boot_screen_cleaner # vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh diff --git a/lib/lib_cdi.sh b/lib/lib_cdi.sh index 43ef6be..8a88a3b 100644 --- a/lib/lib_cdi.sh +++ b/lib/lib_cdi.sh @@ -13,7 +13,7 @@ guard_sourcing ####################################### -# CISS.2025.debian.installer GRUB and Autostart Generator +# CISS.debian.installer 'GRUB' and 'Autostart' generator. # Globals: # BASH_SOURCE # VAR_HANDLER_BUILD_DIR @@ -21,7 +21,9 @@ guard_sourcing # VAR_KERNEL # VAR_WORKDIR # Arguments: -# None +# None +# Returns: +# 0: on success ####################################### cdi() { printf "\e[95m++++ ++++ ++++ ++++ ++++ ++++ ++ ๐Ÿงช %s starting ... \e[0m\n" "${BASH_SOURCE[0]}" @@ -63,5 +65,10 @@ EOF fi printf "\e[92m++++ ++++ ++++ ++++ ++++ ++++ ++ โœ… %s successfully applied. \e[0m\n" "${BASH_SOURCE[0]}" + + return 0 } +### Prevents accidental 'unset -f'. +# shellcheck disable=SC2034 +readonly -f cdi # vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh diff --git a/lib/lib_change_splash.sh b/lib/lib_change_splash.sh index 16fffaf..3609ed8 100644 --- a/lib/lib_change_splash.sh +++ b/lib/lib_change_splash.sh @@ -19,21 +19,32 @@ guard_sourcing # VAR_HANDLER_SPLASH # VAR_WORKDIR # Arguments: -# None +# None +# Returns: +# 0: on success ####################################### change_splash() { if [[ ${VAR_HANDLER_SPLASH} == "club" ]]; then + printf "\e[95m++++ ++++ ++++ ++++ ++++ ++++ ++ ๐Ÿงช Grub Splash 'club.png' selected ...\e[0m\n" cp -af "${VAR_WORKDIR}"/.archive/background/club.png "${VAR_HANDLER_BUILD_DIR}"/config/bootloaders/splash.png cp -af "${VAR_WORKDIR}"/.archive/background/club.png "${VAR_HANDLER_BUILD_DIR}"/config/bootloaders/grub-efi/splash.png cp -af "${VAR_WORKDIR}"/.archive/background/club.png "${VAR_HANDLER_BUILD_DIR}"/config/bootloaders/grub-pc/splash.png printf "\e[92m++++ ++++ ++++ ++++ ++++ ++++ ++ โœ… Grub Splash 'club.png' selected done. \e[0m\n" + elif [[ ${VAR_HANDLER_SPLASH} == "hexagon" ]]; then + printf "\e[95m++++ ++++ ++++ ++++ ++++ ++++ ++ ๐Ÿงช Grub Splash 'hexagon.png' selected ...\e[0m\n" cp -af "${VAR_WORKDIR}"/.archive/background/hexagon.png "${VAR_HANDLER_BUILD_DIR}"/config/bootloaders/splash.png cp -af "${VAR_WORKDIR}"/.archive/background/hexagon.png "${VAR_HANDLER_BUILD_DIR}"/config/bootloaders/grub-efi/splash.png cp -af "${VAR_WORKDIR}"/.archive/background/hexagon.png "${VAR_HANDLER_BUILD_DIR}"/config/bootloaders/grub-pc/splash.png printf "\e[92m++++ ++++ ++++ ++++ ++++ ++++ ++ โœ… Grub Splash 'hexagon.png' selected done. \e[0m\n" + fi + + return 0 } +### Prevents accidental 'unset -f'. +# shellcheck disable=SC2034 +readonly -f change_splash # vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh diff --git a/lib/lib_check_dhcp.sh b/lib/lib_check_dhcp.sh index df29d8f..66dcbb8 100644 --- a/lib/lib_check_dhcp.sh +++ b/lib/lib_check_dhcp.sh @@ -18,11 +18,18 @@ guard_sourcing # VAR_HANDLER_DHCP # VAR_WORKDIR # Arguments: -# None +# None +# Returns: +# 0: on success ####################################### check_dhcp() { if [[ ${VAR_HANDLER_DHCP} -eq 1 ]]; then - chmod +x "${VAR_WORKDIR}"/scripts/0010_dhcp_supersede.sh && "${VAR_WORKDIR}"/scripts/0010_dhcp_supersede.sh + chmod +x "${VAR_WORKDIR}/scripts/0010_dhcp_supersede.sh" && "${VAR_WORKDIR}/scripts/0010_dhcp_supersede.sh" fi + + return 0 } +### Prevents accidental 'unset -f'. +# shellcheck disable=SC2034 +readonly -f check_dhcp # vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh diff --git a/lib/lib_check_hooks.sh b/lib/lib_check_hooks.sh index 199befe..9d6f704 100644 --- a/lib/lib_check_hooks.sh +++ b/lib/lib_check_hooks.sh @@ -15,10 +15,12 @@ guard_sourcing ####################################### # Check and apply 0755 Permissions on every ./config/hooks/live/*.chroot file # Globals: -# ERR_UNCRITICAL # VAR_WORKDIR # Arguments: -# None +# None +# Returns: +# 0: on success +# ERR_UNCRITICAL: on failure ####################################### check_hooks() { declare ifs @@ -27,13 +29,23 @@ check_hooks() { declare -a files=("${VAR_WORKDIR}"/config/hooks/live/*.chroot) if (( ${#files[@]} == 0 )); then + printf "\e[91mโŒ No '*.chroot' files found in '%s/config/hooks/live'. \e[0m\n" "${VAR_WORKDIR}" >&2 exit "${ERR_UNCRITICAL}" + fi - declare file + declare file="" + for file in "${files[@]}"; do + chmod 0755 "${file}" + done + + return 0 } +### Prevents accidental 'unset -f'. +# shellcheck disable=SC2034 +readonly -f check_hooks # vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh diff --git a/lib/lib_check_kernel.sh b/lib/lib_check_kernel.sh index 8760f81..5bdc93d 100644 --- a/lib/lib_check_kernel.sh +++ b/lib/lib_check_kernel.sh @@ -20,7 +20,7 @@ guard_sourcing # VAR_KERNEL_SRT # VAR_KERNEL_TMP # Arguments: -# None +# None # Returns: # 42: Sorting Error. ####################################### @@ -34,9 +34,15 @@ check_kernel() { declare options="" if [[ ${VAR_ARCHITECTURE} != arm64 ]]; then + + # shellcheck disable=SC2312 apt-cache search linux-image | grep linux-image | grep amd64 | grep -v "meta-package" | grep -v "dbg" | grep -v "template" >> "${VAR_KERNEL_TMP}" + else + + # shellcheck disable=SC2312 apt-cache search linux-image | grep linux-image | grep arm64 | grep -v "meta-package" | grep -v "dbg" | grep -v "template" >> "${VAR_KERNEL_TMP}" + fi sort --output="${VAR_KERNEL_SRT}" "${VAR_KERNEL_TMP}" || { @@ -47,12 +53,14 @@ check_kernel() { } while IFS= read -r line; do + first_string=${line%% *} name=${first_string#linux-image-} options+=("${name}" "${counter}" off) ((counter++)) done < "${VAR_KERNEL_SRT}" + # shellcheck disable=SC2155 if declare -gx VAR_KERNEL=$(dialog \ --no-collapse \ @@ -62,13 +70,26 @@ check_kernel() { --title "Select the Kernel for the CISS Hardened Debian Live Image ISO" \ --radiolist "Kernel available \n *+bpo* : Debian Backported Kernel \n *cloud* : Special lightweight images for KVM \n *unsigned* : Unsigned Kernel \n *preempt_rt* : Special Kernel for real-time-computing \n Not unsigned marked are MS signed Kernel for Secure Boot \n" 0 0 "${options[@]}" 3>&1 1>&2 2>&3 3>&-); then clear + else + clear + if [[ "${VAR_ARCHITECTURE}" == "amd64" ]]; then + declare -gx VAR_KERNEL="amd64" + elif [[ "${VAR_ARCHITECTURE}" == "arm64" ]]; then + declare -gx VAR_KERNEL="arm64" + fi + fi + + return 0 } +### Prevents accidental 'unset -f'. +# shellcheck disable=SC2034 +readonly -f check_kernel # vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh diff --git a/lib/lib_check_pkgs.sh b/lib/lib_check_pkgs.sh index 0e62da4..068026b 100644 --- a/lib/lib_check_pkgs.sh +++ b/lib/lib_check_pkgs.sh @@ -15,41 +15,66 @@ guard_sourcing ####################################### # Check for required Deb Packages to run the script. # Arguments: -# None +# None +# Returns: +# 0: on success ####################################### check_pkgs() { - apt-get update -y > /dev/null 2>&1 + apt-get update > /dev/null 2>&1 if [[ -z "$(command -v batcat || true)" ]]; then + apt-get install -y --no-install-recommends bat + fi if [[ -z "$(command -v lsb_release || true)" ]]; then + apt-get install -y --no-install-recommends lsb-release + fi if [[ -z "$(command -v debootstrap || true)" ]]; then + if grep -RqsE '^[[:space:]]*deb .*backports' /etc/apt/sources.list /etc/apt/sources.list.d; then + # shellcheck disable=SC2155 declare codename=$(lsb_release -sc) apt-get install -y -t "${codename}-backports" debootstrap + else + apt-get install -y debootstrap + fi + fi if [[ ! -f /usr/share/live/build/VERSION ]]; then + apt-get install -y live-build + fi if [[ "${VAR_HANDLER_AUTOBUILD}" == false ]]; then + if [[ -z "$(command -v dialog || true)" ]]; then + apt-get install -y --no-install-recommends dialog + fi + fi if [[ -z "$(command -v mkpasswd || true)" ]]; then + apt-get install -y --no-install-recommends whois + fi + + return 0 } +### Prevents accidental 'unset -f'. +# shellcheck disable=SC2034 +readonly -f check_pkgs # vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh diff --git a/lib/lib_check_provider.sh b/lib/lib_check_provider.sh index f6cfc29..ed33cfe 100644 --- a/lib/lib_check_provider.sh +++ b/lib/lib_check_provider.sh @@ -13,9 +13,11 @@ guard_sourcing ####################################### -# Notes Textbox +# Notes Textbox. # Arguments: -# None +# None +# Returns: +# 0: on success ####################################### check_provider() { clear @@ -64,5 +66,10 @@ EOF --scrollbar \ --textbox "${VAR_NOTES}" 32 128 clear + + return 0 } +### Prevents accidental 'unset -f'. +# shellcheck disable=SC2034 +readonly -f check_provider # vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh diff --git a/lib/lib_check_stats.sh b/lib/lib_check_stats.sh index 3fd5aea..3dc9daf 100644 --- a/lib/lib_check_stats.sh +++ b/lib/lib_check_stats.sh @@ -17,13 +17,22 @@ guard_sourcing # Globals: # VAR_HANDLER_STA # Arguments: -# None +# None +# Returns: +# 0: on success ####################################### check_stats() { if [[ ${VAR_HANDLER_STA} -eq 1 ]]; then + clear run_analysis exit 0 + fi + + return 0 } +### Prevents accidental 'unset -f'. +# shellcheck disable=SC2034 +readonly -f check_stats # vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh diff --git a/lib/lib_check_var.sh b/lib/lib_check_var.sh index cf1ed5b..8e3d20d 100644 --- a/lib/lib_check_var.sh +++ b/lib/lib_check_var.sh @@ -13,25 +13,38 @@ guard_sourcing ####################################### -# Unbound Variable Check and call Trap on ERR +# Unbound variable check and call trap on 'ERR'. # Globals: # ERR_UNBOUNDVAR # Arguments: # $1: VAR_NAME to check # Returns: -# "${ERR_UNBOUNDVAR}" +# {ERR_UNBOUNDVAR: on failure ####################################### check_var() { declare var_name_to_check="$1" + if [[ -n "${!var_name_to_check+exists}" ]]; then + if [[ -n "${!var_name_to_check}" ]]; then + printf "\e[92mโœ… Variable: '%s' exists and is NOT empty: '%s' \e[0m\n" "${var_name_to_check}" "${!var_name_to_check}" + else + printf "\e[92mโœ… Variable: '%s' exists but is empty. \e[0m\n" "${var_name_to_check}" + fi + else + printf "\e[91mโŒ Variable: '%s' is not declared. Exiting Script. \e[0m\n" "${var_name_to_check}" >&2 + return "${ERR_UNBOUNDVAR}" + fi } +### Prevents accidental 'unset -f'. +# shellcheck disable=SC2034 +readonly -f check_var # vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh diff --git a/lib/lib_clean_screen.sh b/lib/lib_clean_screen.sh index 500f1eb..ae5291a 100644 --- a/lib/lib_clean_screen.sh +++ b/lib/lib_clean_screen.sh @@ -15,7 +15,7 @@ guard_sourcing ####################################### # Terminal cleaner before Trap on Error # Arguments: -# None +# None ####################################### clean_screen() { tput cnorm > /dev/tty # Cursor visible @@ -27,4 +27,7 @@ clean_screen() { #tput cup $((lines-1)) 0 > /dev/tty #printf "\n" > /dev/tty } +### Prevents accidental 'unset -f'. +# shellcheck disable=SC2034 +readonly -f clean_screen # vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh diff --git a/scripts/9000-cdi-starter b/scripts/9000-cdi-starter index 7da85a6..2480c9f 100644 --- a/scripts/9000-cdi-starter +++ b/scripts/9000-cdi-starter @@ -11,34 +11,69 @@ # SPDX-Security-Contact: security@coresecret.eu set -Ceuo pipefail -declare -gx PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" -declare -gx IFS=$' \t\n' +umask 0077 -printf "\e[95m++++ ++++ ++++ ++++ ++++ ++++ ++ ๐Ÿงช '%s' starting ... \e[0m\n" "${0}" +install -d -m 0755 /run/lock +exec 9> /run/lock/9000-cdi-starter.lock +flock -n 9 || { echo "9000-cdi-starter already running. Exiting."; exit 0; } -[[ ! -d /root/.cdi/log ]] && mkdir -p /root/.cdi/log -printf "CISS.debian.installer Master V8.13.048.2025.10.06 is up! \n" \ - >| /root/.cdi/log/boot_finished_"$(date +"%Y-%m-%d_%H-%M-%S")".log +####################################### +# Wait for network connectivity by looping. +# Arguments: +# None +####################################### +net_wait() { + declare -i i=1 + for i in {1..30}; do + getent hosts git.coresecret.dev >/dev/null && break + sleep 1 + done +} -cd /root/git +####################################### +# Main autostart function. +# Arguments: +# none +####################################### +main() { + declare -r repo_url="https://git.coresecret.dev/msw/CISS.debian.installer.git" + declare -r repo_dir="/root/git/CISS.debian.installer" -git clone https://git.coresecret.dev/msw/CISS.debian.installer.git + install -d -m 0700 /root/.cdi/log + # shellcheck disable=SC2155 + declare -r log="/root/.cdi/log/9000-cdi-starter_$(date +'%F_%H-%M-%S').log" + # shellcheck disable=SC2312 + exec > >(tee -a "${log}") 2>&1 -chmod 0700 /root/git/CISS.debian.installer/ciss_debian_installer.sh + printf "CISS.debian.installer Master V8.13.048.2025.10.06 is up! \n" >| /root/.cdi/log/auto_start_begin_"$(date +"%Y-%m-%d_%H-%M-%S")".log -cd /root/git/CISS.debian.installer + net_wait -#./ciss_debian_installer.sh \ + cd /root/git + + [[ -d "${repo_dir}" ]] && rm -rf "${repo_dir}" + + git clone --depth 1 "${repo_url}" "${repo_dir}" + + chmod 0700 "${repo_dir}/ciss_debian_installer.sh" + + cd "${repo_dir}" + + #./ciss_debian_installer.sh \ # --autoinstall \ # --debug XTRACE \ # --log debug \ # --reionice-priority 1 0 \ # --renice-priority "-19" -printf "CISS.debian.installer Master V8.13.048.2025.10.06 successfully executed! \n" \ - >| /root/.cdi/log/boot_finished_"$(date +"%Y-%m-%d_%H-%M-%S")".log + printf "CISS.debian.installer Master V8.13.048.2025.10.06 successfully executed! \n" >| /root/.cdi/log/auto_start_finished_"$(date +"%Y-%m-%d_%H-%M-%S")".log -printf "\e[92m++++ ++++ ++++ ++++ ++++ ++++ ++ โœ… '%s' successfully applied. \e[0m\n" "${0}" + exit 0 +} +### Prevents accidental 'unset -f'. +# shellcheck disable=SC2034 +readonly -f main + +main "$@" -exit 0 # vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh