From c7b4a4a17ed69bdcc33b95c7d4584b9d0576204b Mon Sep 17 00:00:00 2001 From: m8in Date: Sat, 20 Jun 2026 15:31:35 +0200 Subject: [PATCH] Using print module and moved composition script --- core/base.module.sh | 30 ++---- module/{log.module.sh => print.module.sh} | 102 +++++++++++------- module/ssh.module.sh | 3 +- .../composition}/startOwn.sh | 0 script/host/zfs/composition-sync/sync-send.sh | 6 +- script/host/zfs/composition-sync/sync.sh | 47 ++++---- 6 files changed, 101 insertions(+), 87 deletions(-) rename module/{log.module.sh => print.module.sh} (58%) rename {composition => script/composition}/startOwn.sh (100%) diff --git a/core/base.module.sh b/core/base.module.sh index f9a592c..8289160 100755 --- a/core/base.module.sh +++ b/core/base.module.sh @@ -211,35 +211,27 @@ function prepare.setREGEX() { function base.abort() { # Minimalmode in case of emergency [ "${COLOR[SET]:+isset}" != 'isset' ] \ - && printf -- "\n%b\n" "Script aborted during preparation (State: '${CIS[SET]:-""}')!" >&2 \ - && printf -- " %b\n\n" "${@}" >&2 \ + && printf -- "\n%s\n" "Script '${BASH_SOURCE[0]}' aborted during preparation (State: '${CIS[SET]:-""}')!" >&2 \ + && printf -- " %s\n\n" "${@}" >&2 \ && exit 1 - local _FULLSCRIPTNAME=$(realpath "${0}" 2> /dev/null) - local _SCRIPTNAME="${_FULLSCRIPTNAME##*/}" - [ "${1:+isset}" != "isset" ] \ - && base.printWithColor LIGHTRED "\nScript ${_SCRIPTNAME} aborted!\n\n" >&2 \ + && base.printWithColor LIGHTRED "\nScript ${CIS[SCRIPTNAME]} aborted!\n\n" >&2 \ && exit 1 [ "${2:+isset}" != "isset" ] \ - && base.printWithColor LIGHTRED "\nScript ${_SCRIPTNAME} aborted!\n" >&2 \ + && base.printWithColor LIGHTRED "\nScript ${CIS[SCRIPTNAME]} aborted!\n" >&2 \ && base.printWithColor WHITE "${1:?"Missing parameter MESSAGE."}\n\n" >&2 \ && exit 1 - [ "${3:+isset}" != "isset" ] \ - && base.printWithColor LIGHTRED "\nScript ${_SCRIPTNAME} aborted!\n" >&2 \ - && base.printWithColor WHITE "${1:?"Missing parameter MESSAGE."}\n\n" >&2 \ - && base.printWithColor CYAN "TIP: ${2:?"Missing parameter TIP."}\n" >&2 \ - && exit 1 - - base.printWithColor LIGHTRED "\nScript ${_SCRIPTNAME} aborted!\n" >&2 - base.printWithColor WHITE "${1:?"Missing parameter MESSAGE."}\n\n" >&2 - base.printWithColor CYAN "TIP - ${2:?"Missing parameter TIP."}:\n" >&2 - while shift; do - [ -z "${2:-""}" ] && break - base.printWithColor LIGHTGREY " ${2}\n" >&2 + base.printWithColor LIGHTRED "\nScript ${CIS[SCRIPTNAME]} aborted!\n" >&2 + base.printWithColor WHITE "${1:?"Missing parameter MESSAGE."}\n" >&2 + base.printWithColor CYAN "TIP: ${2:?"Missing parameter TIP."}:\n" >&2 + while [ -n "${3}" ]; do + base.printWithColor LIGHTGREY " ${3:-""}\n" >&2 + shift done + echo >&2 exit 1 } diff --git a/module/log.module.sh b/module/print.module.sh similarity index 58% rename from module/log.module.sh rename to module/print.module.sh index 9027410..4df2b54 100755 --- a/module/log.module.sh +++ b/module/print.module.sh @@ -4,8 +4,8 @@ source /cis/core/base.module.sh #Function, to highlight bad messages. -function log.bad() { - local _MESSAGE="${@:?"log.bad(): Missing first parameter MESSAGE."}" +function print.bad() { + local _MESSAGE="${@:?"print.bad(): Missing first parameter MESSAGE."}" base.printWithColor LIGHTRED "${_MESSAGE}" >&2 \ && return 0 @@ -14,17 +14,17 @@ function log.bad() { } #Function, for data. -function log.data() { - local _MESSAGE="${@:?"log.data(): Missing first parameter MESSAGE."}" +function print.data() { + local _MESSAGE="${@:?"print.data(): Missing first parameter MESSAGE."}" - base.printWithColor LIGHTGREY "${_MESSAGE}" >&2 \ + base.printWithColor DARKGREY "${_MESSAGE}" >&2 \ && return 0 return 1 } #Function, for uncorrectable errors. -function log.error() { +function print.error() { local _MESSAGE="${@:-""}" [ -z "${_MESSAGE:-""}" ] \ @@ -39,8 +39,8 @@ function log.error() { } #Function, for very important information. -function log.essential() { - local _MESSAGE="${@:?"log.essential(): Missing first parameter MESSAGE."}" +function print.essential() { + local _MESSAGE="${@:?"print.essential(): Missing first parameter MESSAGE."}" base.printWithColor LIGHTRED "${_MESSAGE}" >&2 \ && return 0 @@ -49,23 +49,33 @@ function log.essential() { } #Function, for failures. -function log.failure() { - local _MESSAGE="${@:-""}" - - [ -z "${_MESSAGE:-""}" ] \ - && base.printWithColor LIGHTRED "FAILURE!\n" >&2 \ +function print.failure() { + [ "${1:+isset}" != "isset" ] \ + && base.printWithColor LIGHTRED "\nFAILURE:" >&2 \ + && base.printWithColor WHITE " ${CIS[SCRIPTNAME]}\n\n" >&2 \ && return 0 - base.printWithColor LIGHTRED "FAILURE!\n" >&2 \ - && base.printWithColor WHITE " ${_MESSAGE}\n" >&2 \ + [ "${2:+isset}" != "isset" ] \ + && base.printWithColor LIGHTRED "\nFAILURE:" >&2 \ + && base.printWithColor WHITE " ${CIS[SCRIPTNAME]}\n" >&2 \ + && base.printWithColor WHITE " ${1:?"Missing parameter MESSAGE."}\n\n" >&2 \ && return 0 - return 1 + base.printWithColor LIGHTRED "\nFAILURE:" >&2 + base.printWithColor WHITE " ${CIS[SCRIPTNAME]}\n" >&2 + base.printWithColor WHITE " ${1:?"Missing parameter MESSAGE."}\n" >&2 + base.printWithColor CYAN "TIP: ${2:?"Missing parameter TIP."}:\n" >&2 + while [ -n "${3}" ]; do + base.printWithColor LIGHTGREY " ${3:-""}\n" >&2 + shift + done + echo >&2 + return 0 } #Function, to finish a script. -function log.finish() { - local _SCRIPTNAME="${CIS[SCRIPTNAME]:?"log.finish(): Missing CIS[SCRIPTNAME]."}" +function print.finish() { + local _SCRIPTNAME="${CIS[SCRIPTNAME]:?"print.finish(): Missing CIS[SCRIPTNAME]."}" base.printWithColor WHITE "\nScript ${_SCRIPTNAME}: " >&2 \ && base.printWithColor LIGHTGREEN "successful!\n\n" >&2 \ @@ -75,8 +85,8 @@ function log.finish() { } #Function, to highlight good messages. -function log.good() { - local _MESSAGE="${@:?"log.good(): Missing first parameter MESSAGE."}" +function print.good() { + local _MESSAGE="${@:?"print.good(): Missing first parameter MESSAGE."}" base.printWithColor LIGHTGREEN "${_MESSAGE}" >&2 \ && return 0 @@ -84,9 +94,19 @@ function log.good() { return 1 } +#Function, for highlighted messages. +function print.highlight() { + local _MESSAGE="${@:?"print.highlight(): Missing first parameter MESSAGE."}" + + base.printWithColor WHITE "${_MESSAGE}" >&2 \ + && return 0 + + return 1 +} + #Function, for important information. -function log.important() { - local _MESSAGE="${@:?"log.important(): Missing first parameter MESSAGE."}" +function print.important() { + local _MESSAGE="${@:?"print.important(): Missing first parameter MESSAGE."}" base.printWithColor YELLOW "${_MESSAGE}" >&2 \ && return 0 @@ -95,8 +115,8 @@ function log.important() { } #Function, for normal information. -function log.info(){ - local _MESSAGE="${1:?"log.info(): Missing first parameter MESSAGE."}" +function print.info() { + local _MESSAGE="${1:?"print.info(): Missing first parameter MESSAGE."}" shift local _DECRIPTION="${@:-""}" @@ -113,19 +133,19 @@ function log.info(){ return 1 } -#Function, for highlighted messages. -function log.message(){ - local _MESSAGE="${@:?"log.message(): Missing first parameter MESSAGE."}" +#Function, for normal messages. +function print.message() { + local _MESSAGE="${@:?"print.message(): Missing first parameter MESSAGE."}" - base.printWithColor WHITE "${_MESSAGE}" >&2 \ + base.printWithColor LIGHTGREY "${_MESSAGE}" >&2 \ && return 0 return 1 } #Function, for additional information. -function log.optional(){ - local _MESSAGE="${@:?"log.optional(): Missing first parameter MESSAGE."}" +function print.optional() { + local _MESSAGE="${@:?"print.optional(): Missing first parameter MESSAGE."}" base.printWithColor LIGHTBLUE "${_MESSAGE}" >&2 \ && return 0 @@ -134,10 +154,10 @@ function log.optional(){ } #Function, to start a script. -function log.start(){ +function print.start() { local _MESSAGE="${@:-""}" - local _SERVICE="$(echo "${_SCRIPTDIR##${CIS[ROOT]:?"log.start(): Missing CIS[ROOT]"}/}" | tr '[:lower:]' '[:upper:]')" - local _COMMAND="${CIS[SCRIPTNAME]:?"log.start(): Missing CIS[SCRIPTNAME]."}" + local _SERVICE="$(echo "${_SCRIPTDIR##${CIS[ROOT]:?"print.start(): Missing CIS[ROOT]"}/}" | tr '[:lower:]' '[:upper:]')" + local _COMMAND="${CIS[SCRIPTNAME]:?"print.start(): Missing CIS[SCRIPTNAME]."}" [ -z "${_MESSAGE:-""}" ] \ && base.printWithColor YELLOW "${_SERVICE} ${_COMMAND}:\n\n" >&2 \ @@ -151,7 +171,7 @@ function log.start(){ } #Function, for successful messages. -function log.success(){ +function print.success() { local _MESSAGE="${@:-""}" [ -z "${_MESSAGE:-""}" ] \ @@ -166,8 +186,8 @@ function log.success(){ } #Function, for tips. -function log.tip(){ - local _MESSAGE="${1:?"log.tip(): Missing first parameter MESSAGE."}" +function print.tip() { + local _MESSAGE="${1:?"print.tip(): Missing first parameter MESSAGE."}" base.printWithColor CYAN "TIP:\n" >&2 while [ "${_MESSAGE:-""}" != "" ]; do @@ -182,8 +202,8 @@ function log.tip(){ } #Function, for warnings. -function log.warn(){ - local _MESSAGE="${@:?"log.warn(): Missing first parameter MESSAGE."}" +function print.warn() { + local _MESSAGE="${@:?"print.warn(): Missing first parameter MESSAGE."}" base.printWithColor YELLOW "WARNING:\n" >&2 \ && base.printWithColor WHITE " ${_MESSAGE}\n" >&2 \ @@ -197,7 +217,7 @@ function log.warn(){ # Check if this module was started correctly using source if [ "${BASH_SOURCE[0]}" == "${0}" ]; then # Script was executed directly - echo "FAILURE: you are using this module 'log.module.sh' in a wrong way." + echo "FAILURE: you are using this module 'print.module.sh' in a wrong way." echo " It is intended as a utility library and should not be called directly." echo echo "Usage: Call this module at the beginning of your script e.g. like this:" @@ -206,9 +226,9 @@ if [ "${BASH_SOURCE[0]}" == "${0}" ]; then echo ' source /cis/core/base.module.sh' echo echo ' #Loads this module' - echo ' base.loadModule log' + echo ' base.loadModule print' echo - base.explain 'log' "${1}" "${2}" + base.explain 'print' "${1}" "${2}" echo exit 1 fi diff --git a/module/ssh.module.sh b/module/ssh.module.sh index f6dd11f..6a36f26 100755 --- a/module/ssh.module.sh +++ b/module/ssh.module.sh @@ -1,5 +1,6 @@ #!/bin/bash source /cis/core/base.module.sh +base.loadModule print @@ -41,7 +42,7 @@ function ssh.onHostRun() { -f ${_REMOTE_USER}@${_REMOTE_HOSTNAME_FQDN} exit &> /dev/null \ && return 0 - base.abort "FAILURE: Establishing SSH connection" "Is the setup ok?" + print.failure "Establishing SSH connection" "Is the setup ok?" return 1 } diff --git a/composition/startOwn.sh b/script/composition/startOwn.sh similarity index 100% rename from composition/startOwn.sh rename to script/composition/startOwn.sh diff --git a/script/host/zfs/composition-sync/sync-send.sh b/script/host/zfs/composition-sync/sync-send.sh index f2cad89..be22d0d 100755 --- a/script/host/zfs/composition-sync/sync-send.sh +++ b/script/host/zfs/composition-sync/sync-send.sh @@ -1,6 +1,7 @@ #!/bin/bash source /cis/core/base.module.sh base.loadModule composition +base.loadModule print @@ -138,8 +139,7 @@ base.set RECEIVERS_SNAPSHOT "${4}" "${REGEX[SNAPSHOT]}" optional base.set RESUME_TOKEN "${5}" '^[a-zA-Z0-9][a-zA-Z0-9._:-]*$' optional ! composition.shouldBeSyncedByGivenHost "${COMPOSITION}" "${RECEIVERHOST}" \ - && echo "FAILURE: The host '${RECEIVERHOST}' is no sync-host for composition: '${COMPOSITION}'" >&2 \ - && exit 1 + && base.abort "The host '${RECEIVERHOST}' is no sync-host for composition: '${COMPOSITION}'" # Resume mode if [ "${RECEIVERS_SNAPSHOT}" == "@RESUME" ] && [ -n "${RESUME_TOKEN}" ]; then @@ -152,5 +152,5 @@ fi send "${ZFS_BRANCH}" "${COMPOSITION}" "${RECEIVERHOST}" "${RECEIVERS_SNAPSHOT}" \ && exit 0 -echo "Failure in sync-send.sh: Something unexpected happend." >&2 +print.failure "Something unexpected happend." exit 1 diff --git a/script/host/zfs/composition-sync/sync.sh b/script/host/zfs/composition-sync/sync.sh index 12d292b..a03b1c2 100755 --- a/script/host/zfs/composition-sync/sync.sh +++ b/script/host/zfs/composition-sync/sync.sh @@ -1,6 +1,7 @@ #!/bin/bash source /cis/core/base.module.sh base.loadModule composition +base.loadModule print @@ -38,9 +39,9 @@ function removeForeignSyncSnapshots() { readonly _RECEIVERHOST _ZFS zfs list -t snapshot -H -o name "${_ZFS}" | grep -- "${_ZFS}@SYNC" | grep -v -i "@SYNC_${_RECEIVERHOST}_" | while read _SNAP; do - echo -n "Removing foreign snapshot: ${_SNAP} ... " \ + print.data "Removing foreign snapshot: ${_SNAP} ... " \ && destroySyncSnapshot "${_ZFS}" "${_SNAP}" \ - && echo "done" + && print.good "done\n" done return 0 @@ -58,9 +59,9 @@ function removeOutdatedSyncSnapshots() { # Remove all but the newest snapshot, which is the common snapshot in the next run zfs list -t snapshot -H -o name "${_ZFS}" | grep -- "${_ZFS}@SYNC_${_RECEIVERHOST}_" | grep -v -i "${_NEWEST_SNAPSHOT}" | while read _SNAP; do - echo -n "Removing outdated snapshot: ${_SNAP} ... " \ + print.data "Removing outdated snapshot: ${_SNAP} ... " \ && destroySyncSnapshot "${_ZFS}" "${_SNAP}" \ - && echo "done" + && print.good "done\n" done return 0 @@ -80,7 +81,7 @@ function tryRollbackToRepair() { [ -z "${_ROLLBACK_SNAPSHOT}" ] && return 1 # Remove at most the two newest sync snapshots, if the day matches with the rollback file - echo "Try to fix by removing: '${_ROLLBACK_SNAPSHOT}'" \ + print highlight "Try to fix by removing: '${_ROLLBACK_SNAPSHOT}'\n" \ && zfs destroy "${_ROLLBACK_SNAPSHOT:?"tryRollbackToRepair(): Missing _ROLLBACK_SNAPSHOT"}" \ && return 0 @@ -107,27 +108,29 @@ function receive() { _COMMON_SNAPSHOT="" _RESUME_TOKEN=$(zfs get -H -o value receive_resume_token "${_ZFS}" 2> /dev/null) if [ -n "${_RESUME_TOKEN}" ] && [ "${_RESUME_TOKEN}" != "-" ]; then - echo "Resume token present trying to resume at ${_RESUME_TOKEN}" + print.important "Resume token present trying to resume at ${_RESUME_TOKEN}\n" _COMMON_SNAPSHOT="@RESUME" else _RESUME_TOKEN="" _COMMON_SNAPSHOT=$(zfs list -H -o name -S creation -t snapshot "${_ZFS}" 2> /dev/null | head -n 1) ! [ -z "${_COMMON_SNAPSHOT}" ] \ - && echo "Rolling back to newest snapshot: ${_COMMON_SNAPSHOT}" \ - && zfs rollback -r "${_COMMON_SNAPSHOT}" + && print.data "Rolling back to newest snapshot: ${_COMMON_SNAPSHOT} ... " \ + && zfs rollback -r "${_COMMON_SNAPSHOT}" \ + && print.good "done\n" fi # Add "-s" for resumable streams in the next line at zfs receive. Not done yet because of: cannot receive resume stream: kernel modules must be upgraded to receive this stream. ${_SSH_COMMAND} "sudo ${_SEND_SCRIPT:?"Missing SEND_SCRIPT"} \"${_RECEIVERHOST}\" \"${_ZFS_BRANCH}\" \"${_COMPOSITION}\" \"@${_COMMON_SNAPSHOT#*@}\" \"${_RESUME_TOKEN}\"" | zfs receive -v "${_ZFS}" if [ $? -ne 0 ]; then - echo "Unable to receive stream using these settings:" - echo " - Sending host: ${_SOURCEHOST}:${_SSH_PORT}" - echo " - Receiving host: ${_RECEIVERHOST}" - echo " - ZFS Branch: ${_ZFS_BRANCH}" - echo " - Composition: ${_COMPOSITION}" - echo " - Offered snapshot: @${_COMMON_SNAPSHOT#*@}" - echo " - Resume token: ${_RESUME_TOKEN}" - echo "Current state of snapshots:" + print.failure "Unable to receive stream" \ + "These settings were used" \ + "- Sending host: ${_SOURCEHOST}:${_SSH_PORT}" \ + "- Receiving host: ${_RECEIVERHOST}" \ + "- ZFS Branch: ${_ZFS_BRANCH}" \ + "- Composition: ${_COMPOSITION}" \ + "- Offered snapshot: @${_COMMON_SNAPSHOT#*@}" \ + "- Resume token: ${_RESUME_TOKEN}" + print.highlight "Current state of snapshots:\n" zfs list -t snapshot "${_ZFS}" 2> /dev/null | tail tryRollbackToRepair "${_COMPOSITION}" "${_ZFS}" && return 0 return 1 @@ -151,7 +154,7 @@ function receiveLoopAll() { composition.printAllSyncedByThisHost | while read -r _COMPOSITION; do ! screen -ls | grep -qoE "[0-9]+\.compositionsync\.${_COMPOSITION}" \ - && echo "Starting screen sync session of composition: ${_COMPOSITION}" \ + && print.highlight "Starting screen sync session of composition: ${_COMPOSITION}\n" \ && screen -dmS "composition-sync:${_COMPOSITION}" "${_SCRIPT}" --loopSingle "${_COMPOSITION}" done } @@ -163,20 +166,18 @@ function receiveLoopSingle() { while composition.shouldBeSyncedByGivenHost "${_COMPOSITION}" "${CIS[HOST]}"; do receive "${_COMPOSITION}" \ - && echo "Sleep for 5s" \ + && print.info "Sleep for 5s\n" \ && sleep 5 \ - && echo \ && continue # If there is a screen session this keeps it alive in case of an error for debugging - echo - echo "Waiting 5min then ABORT!" + print.info "Waiting 5min then ABORT!\n" sleep 300 return 1 done ! composition.shouldBeSyncedByGivenHost "${_COMPOSITION}" "${CIS[HOST]}" \ - && echo "This host '${CIS[HOST]}' is no sync-host (anymore) for composition: '${_COMPOSITION}'" + && print.important "This host '${CIS[HOST]}' is no sync-host (anymore) for composition: '${_COMPOSITION}'\n" } function receiveOnceAll() { @@ -195,7 +196,7 @@ function receiveOnceSingle() { readonly _COMPOSITION ! composition.shouldBeSyncedByGivenHost "${_COMPOSITION}" "${CIS[HOST]}" \ - && echo "This host '${CIS[HOST]}' is no sync-host for composition: '${_COMPOSITION}'" \ + && print.failure "This host '${CIS[HOST]}' is no sync-host for composition: '${_COMPOSITION}'" \ && return 1 receive "${_COMPOSITION}" \