#!/bin/bash
#######################################################################################################################
#
# Script to download, install, configure and uninstall raspiBackup.sh using windows.
# Commandline installation is also possible. Use option -h to get a list of all options.
#
# Visit http://www.linux-tips-and-tricks.de/raspiBackup for latest code and other details
#
# Credits to following people for their translation work
# FI - teemue
# ZH - GoogleBeEvil
# FR - mgrafr
#
#######################################################################################################################
#
# Copyright (c) 2015-2023 framp at linux-tips-and-tricks dot de
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
#
#######################################################################################################################
if [ -z "$BASH_VERSION" ] ;then
echo "??? ERROR: Unable to execute script. bash interpreter missing."
echo "??? DEBUG: $(lsof -a -p $$ -d txt | tail -n 1)"
exit 127
fi
[[ "$(ps --no-headers -o comm 1)" != "systemd" ]]
: "${SYSTEMD_DETECTED:=$?}" # just disable some code for debugging
: "${RASPIBACKUP_INSTALL_DEBUG:=0}" # just disable some code for debugging
MYSELF="$(basename "$(test -L "$0" && readlink "$0" || echo "$0")")" # use linked script name if the link is used
MYNAME=${MYSELF%.*}
VERSION="0.4.8.1" # -beta, -hotfix or -dev suffixes possible
if [[ (( ${BASH_VERSINFO[0]} < 4 )) || ( (( ${BASH_VERSINFO[0]} == 4 )) && (( ${BASH_VERSINFO[1]} < 3 )) ) ]]; then
echo "bash version 0.4.3 or beyond is required by $MYSELF" # nameref feature, declare -n var=$v
exit 1
fi
# Commands used by raspiBackup and which have to be available
# [command]=package
declare -A REQUIRED_COMMANDS=( \
["parted"]="parted" \
["fsck.vfat"]="dosfstools" \
["e2label"]="e2fsprogs" \
["rsync"]="rsync" \
["whiptail"]="whiptail" \
["dosfslabel"]="dosfstools" \
["fdisk"]="fdisk" \
["blkid"]="util-linux" \
["sfdisk"]="fdisk" \
)
requiredCmds=()
for cmd in ${!REQUIRED_COMMANDS[@]}; do
if ! hash $cmd 2>/dev/null; then
requiredCmds+=($cmd)
fi
done
if (( ${#requiredCmds[@]} > 0 )); then
for cmd in ${requiredCmds[@]}; do
echo "$MYSELF depends on $cmd which is available in ${REQUIRED_COMMANDS[$cmd]}"
done
echo -n "Install all the missing package(s)? (Y/n) "
read answer
answer=${answer:0:1} # first char only
answer=${answer:-"y"} # set default yes
answer=${answer,,*} # to lower
if [[ ! "yj" =~ $answer ]]; then
echo "Please install the required package(s) manually first and then invoke ./$MYSELF again."
exit 1
fi
apt -y install ${requiredCmds[@]}
if (( $? )); then
echo "Installation of missing package(s) failed. Please install them manually and then invoke ./$MYSELF again."
exit 1
fi
fi
MYHOMEDOMAIN="www.linux-tips-and-tricks.de"
MYHOMEURL="https://$MYHOMEDOMAIN"
MYDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
GIT_DATE="$Date$"
GIT_DATE_ONLY=${GIT_DATE/: /}
GIT_DATE_ONLY=$(cut -f 2 -d ' ' <<<$GIT_DATE)
GIT_TIME_ONLY=$(cut -f 3 -d ' ' <<<$GIT_DATE)
GIT_COMMIT="$Sha1$"
GIT_COMMIT_ONLY=$(cut -f 2 -d ' ' <<<$GIT_COMMIT | sed 's/\$//')
GIT_CODEVERSION="$MYSELF $VERSION, $GIT_DATE_ONLY/$GIT_TIME_ONLY - $GIT_COMMIT_ONLY"
FILE_TO_INSTALL="raspiBackup.sh"
RASPIBACKUP_NAME=${FILE_TO_INSTALL%.*}
CURRENT_DIR=$(pwd)
NL=$'\n'
IGNORE_START_STOP_CHAR=":"
declare -A CONFIG_DOWNLOAD_FILE=(['DE']="raspiBackup_de.conf" ['EN']="raspiBackup_en.conf")
CONFIG_FILE="raspiBackup.conf"
SAMPLEEXTENSION_TAR_FILE="raspiBackupSampleExtensions.tgz"
DEFAULT_IFS="$IFS"
MASQUERADE_STRING="@@@@"
[[ -n $URLTARGET ]] && URLTARGET="/$URLTARGET"
PROPERTY_URL="$MYHOMEURL/raspiBackup${URLTARGET}/raspiBackup.properties"
BETA_DOWNLOAD_URL="$MYHOMEURL/raspiBackup${URLTARGET}/beta/raspiBackup.sh"
PROPERTY_FILE_NAME="$MYNAME.properties"
LATEST_TEMP_PROPERTY_FILE="/tmp/$PROPERTY_FILE_NAME"
LOCAL_PROPERTY_FILE="$CURRENT_DIR/.$PROPERTY_FILE_NAME"
INSTALLER_DOWNLOAD_URL="$MYHOMEURL/raspiBackup${URLTARGET}/raspiBackupInstallUI.sh"
STABLE_CODE_URL="$FILE_TO_INSTALL"
INCLUDE_SERVICES_REGEX_FILE="/usr/local/etc/raspiBackup.iservices"
EXCLUDE_SERVICES_REGEX_FILE="/usr/local/etc/raspiBackup.eservices"
read -r -d '' CRON_CONTENTS <<-'EOF'
#
# Crontab entry for raspiBackup.sh
#
# (C) 2017-2019 framp at linux-tips-and-tricks dot de
#
# Create a backup once a week on Sunday morning at 5 am (default)
#
#0 5 * * 0 root /usr/local/bin/raspiBackup.sh
EOF
read -r -d '' SYSTEMD_SERVICE <<-'EOF'
[Unit]
Description=Creation of a Raspberry backup with raspiBackup
[Service]
Type=simple
ExecStart=/usr/local/bin/raspiBackup.sh
# For Use with Wrapper Script: ExecStart=/usr/local/bin/raspiBackupWrapper.sh
[Install]
WantedBy=multi-user.target
EOF
read -r -d '' SYSTEMD_TIMER <<-'EOF'
[Unit]
Description=Timer for raspiBackup.service to start backup
[Timer]
OnCalendar=Sun *-*-* 05:00:42
# Create a backup once a week on Sunday morning at 5 am (default)
Unit=raspiBackup.service
[Install]
WantedBy=multi-user.target
EOF
if [[ -f $EXCLUDE_SERVICES_REGEX_FILE ]]; then
EXCLUDE_SERVICES_REGEX="$(<$EXCLUDE_SERVICES_REGEX_FILE)"
else
read -r -d '' EXCLUDE_SERVICES_REGEX <<-'EOF'
acpid
alsa-state
avahi.*
argononed
bluetooth
colord
dbus
dhcpcd
hciuart
kernel.*
LightDM
lvm.*
ModemManager
nfs-
ntp
rng-tools
rpcbind
rsyslog
ssh
smartd
smartmontools
systemd-.*
thermald
triggerhappy
udisks.*
unattended.*
upower
wpa_supplicant
.*@.*
EOF
fi
if [[ -f $INCLUDE_SERVICES_REGEX_FILE ]]; then
INCLUDE_SERVICES_REGEX="$(<$INCLUDE_SERVICES_REGEX_FILE)"
else
read -r -d '' INCLUDE_SERVICES_REGEX <<-'EOF'
apache.*
containerd
cron
cups
fhem
influxd
iobroker
lighttpd
minidlna
mysql
mariadb
nfs-kernel-server
nmbd
nginx
smbd
snapd
wordpress
EOF
fi
DOWNLOAD_TIMEOUT=60 # seconds
DOWNLOAD_RETRIES=3
BIN_DIR="/usr/local/bin"
ETC_DIR="/usr/local/etc"
CRON_DIR="/etc/cron.d"
LOG_FILE="$MYNAME.log"
SYSTEMD_DIR="/etc/systemd/system"
CONFIG_FILE_ABS_PATH="$ETC_DIR"
CONFIG_ABS_FILE="$CONFIG_FILE_ABS_PATH/$CONFIG_FILE"
FILE_TO_INSTALL_ABS_PATH="$BIN_DIR"
FILE_TO_INSTALL_ABS_FILE="$FILE_TO_INSTALL_ABS_PATH/$FILE_TO_INSTALL"
CRON_ABS_FILE="$CRON_DIR/$RASPIBACKUP_NAME"
SYSTEMD_SERVICE_FILE_NAME="${RASPIBACKUP_NAME}.service"
SYSTEMD_SERVICE_ABS_FILE="$SYSTEMD_DIR/$SYSTEMD_SERVICE_FILE_NAME"
SYSTEMD_TIMER_FILE_NAME="${RASPIBACKUP_NAME}.timer"
SYSTEMD_TIMER_ABS_FILE="$SYSTEMD_DIR/$SYSTEMD_TIMER_FILE_NAME"
INSTALLER_ABS_PATH="$BIN_DIR"
INSTALLER_ABS_FILE="$INSTALLER_ABS_PATH/$MYSELF"
VAR_LIB_DIRECTORY="/var/lib/$RASPIBACKUP_NAME"
PROPERTY_REGEX='.*="([^"]*)"'
# borrowed from http://stackoverflow.com/questions/3685970/check-if-an-array-contains-a-value
function containsElement () {
local e
for e in "${@:2}"; do [[ "$e" == "$1" ]] && return 0; done
return 1
}
#
# NLS: Either use system language if language is supported and use English otherwise
#
SUPPORTED_LANGUAGES=("EN" "DE" "FI" "FR" "ZH")
[[ -z "${LANG}" ]] && LANG="en_US.UTF-8"
LANG_EXT="${LANG^^*}"
LANG_SYSTEM="${LANG_EXT:0:2}"
if ! containsElement "${LANG_SYSTEM^^*}" "${SUPPORTED_LANGUAGES[@]}"; then
LANG_SYSTEM="EN"
fi
# default configs
CONFIG_LANGUAGE=$LANG_SYSTEM
# CONFIG_LANGUAGE= will become the configured language later on
CONFIG_MSG_LEVEL="0"
CONFIG_BACKUPTYPE="rsync"
CONFIG_KEEPBACKUPS="3"
DEFAULT_CONFIG_SMART_RECYCLE="0"
CONFIG_SMART_RECYCLE="$DEFAULT_CONFIG_SMART_RECYCLE"
DEFAULT_CONFIG_SMART_RECYCLE_OPTIONS="7 4 12 1"
CONFIG_SMART_RECYCLE_OPTIONS="$DEFAULT_CONFIG_SMART_RECYCLE_OPTIONS"
DEFAULT_CONFIG_SMART_RECYCLE_DRYRUN="1"
CONFIG_SMART_RECYCLE_DRYRUN="$DEFAULT_CONFIG_SMART_RECYCLE_DRYRUN"
CONFIG_BACKUPPATH="/backup"
CONFIG_PARTITIONBASED_BACKUP="0"
DEFAULT_CONFIG_PARTITIONS_TO_BACKUP="1 2"
CONFIG_PARTITIONS_TO_BACKUP="$DEFAULT_CONFIG_PARTITIONS_TO_BACKUP"
CONFIG_ZIP_BACKUP="0"
CONFIG_CRON_HOUR="5"
CONFIG_CRON_MINUTE="0"
CONFIG_CRON_DAY="1" # Sun
CONFIG_SYSTEMD_HOUR=$CONFIG_CRON_HOUR
CONFIG_SYSTEMD_MINUTE=$CONFIG_CRON_MINUTE
CONFIG_SYSTEMD_DAY="1" # Sun
CONFIG_MAIL_PROGRAM="mail"
CONFIG_EMAIL=""
CONFIG_RESIZE_ROOTFS="1"
# Whiptail box sizes
ROWS_MSGBOX=20
ROWS_ABOUT=20
ROWS_MENU=20
WINDOW_COLS=60
#
# Messages
#
# To add a new language just execute following steps:
# 1) Add new language id LL (e.g. FI for Finnish) in variable SUPPORTED_LANGUAGES (see above)
# 2) For every MSG_ add a new message MSG_LL
#
MSG_PRF="RBI"
SCNT=0
MSG_UNDEFINED=$((SCNT++))
MSG_EN[$MSG_UNDEFINED]="${MSG_PRF}0000E: Undefined messageid."
MSG_DE[$MSG_UNDEFINED]="${MSG_PRF}0000E: Unbekannte Meldungsid."
MSG_FI[$MSG_UNDEFINED]="${MSG_PRF}0000E: Viestitunnus puuttuu."
MSG_FR[$MSG_UNDEFINED]="${MSG_PRF}0000E: ID de message non défini."
MSG_ZH[$MSG_UNDEFINED]="${MSG_PRF}0000E: 未定义的错误ID."
MSG_VERSION=$((SCNT++))
MSG_EN[$MSG_VERSION]="${MSG_PRF}0001I: %1"
MSG_DE[$MSG_VERSION]="${MSG_PRF}0001I: %1"
MSG_FI[$MSG_VERSION]="${MSG_PRF}0001I: %1"
MSG_FR[$MSG_VERSION]="${MSG_PRF}0001I: %1"
MSG_ZH[$MSG_VERSION]="${MSG_PRF}0001I: %1"
MSG_DOWNLOADING=$((SCNT++))
MSG_EN[$MSG_DOWNLOADING]="${MSG_PRF}0002I: Downloading %1..."
MSG_DE[$MSG_DOWNLOADING]="${MSG_PRF}0002I: %1 wird aus dem Netz geladen..."
MSG_FI[$MSG_DOWNLOADING]="${MSG_PRF}0002I: Ladataan %1..."
MSG_FR[$MSG_DOWNLOADING]="${MSG_PRF}0002I: Téléchargement %1..."
MSG_ZH[$MSG_DOWNLOADING]="${MSG_PRF}0002I: 下载中 %1..."
MSG_DOWNLOAD_FAILED=$((SCNT++))
MSG_EN[$MSG_DOWNLOAD_FAILED]="${MSG_PRF}0003E: Download of %1 failed. HTTP code: %2."
MSG_DE[$MSG_DOWNLOAD_FAILED]="${MSG_PRF}0003E: %1 kann nicht aus dem Netz geladen werden. HTTP code: %2."
MSG_FI[$MSG_DOWNLOAD_FAILED]="${MSG_PRF}0003E: Kohteen %1 lataus epäonnistui. HTTP-koodi: %2."
MSG_FR[$MSG_DOWNLOAD_FAILED]="${MSG_PRF}0003E: Le téléchargement de %1 a échoué. Code HTTP : %2."
MSG_ZH[$MSG_DOWNLOAD_FAILED]="${MSG_PRF}0003E: 下载 %1 失败. HTTP-代码: %2."
MSG_INSTALLATION_FAILED=$((SCNT++))
MSG_EN[$MSG_INSTALLATION_FAILED]="${MSG_PRF}0004E: Installation of %1 failed. Check %2."
MSG_DE[$MSG_INSTALLATION_FAILED]="${MSG_PRF}0004E: Installation von %1 fehlerhaft beendet. Prüfe %2."
MSG_FI[$MSG_INSTALLATION_FAILED]="${MSG_PRF}0004E: Kohteen %1 asennus epäonnistui. Tarkista %2."
MSG_FR[$MSG_INSTALLATION_FAILED]="${MSG_PRF}0004E: L'installation de %1 a échoué. Vérifiez %2."
MSG_ZH[$MSG_INSTALLATION_FAILED]="${MSG_PRF}0004E: 安装 %1 失败. 检查 %2."
MSG_SAVING_FILE=$((SCNT++))
MSG_EN[$MSG_SAVING_FILE]="${MSG_PRF}0005I: Existing file %1 saved as %2."
MSG_DE[$MSG_SAVING_FILE]="${MSG_PRF}0005I: Existierende Datei %1 wurde als %2 gesichert."
MSG_FI[$MSG_SAVING_FILE]="${MSG_PRF}0005I: Tiedosto %1 tallennettiin nimellä %2."
MSG_FR[$MSG_SAVING_FILE]="${MSG_PRF}0005I: Fichier existant %1 enregistré en tant que %2."
MSG_ZH[$MSG_SAVING_FILE]="${MSG_PRF}0005I: %1 已存在,另存为 %2."
MSG_CHMOD_FAILED=$((SCNT++))
MSG_EN[$MSG_CHMOD_FAILED]="${MSG_PRF}0006E: chmod of %1 failed."
MSG_DE[$MSG_CHMOD_FAILED]="${MSG_PRF}0006E: chmod von %1 nicht möglich."
MSG_FI[$MSG_CHMOD_FAILED]="${MSG_PRF}0006E: chmod %1 epäonnistui."
MSG_FR[$MSG_CHMOD_FAILED]="${MSG_PRF}0006E: chmod de %1 a échoué."
MSG_ZH[$MSG_CHMOD_FAILED]="${MSG_PRF}0006E: chmod %1 失败."
MSG_MOVE_FAILED=$((SCNT++))
MSG_EN[$MSG_MOVE_FAILED]="${MSG_PRF}0007E: mv of %1 failed."
MSG_DE[$MSG_MOVE_FAILED]="${MSG_PRF}0007E: mv von %1 nicht möglich."
MSG_FI[$MSG_MOVE_FAILED]="${MSG_PRF}0007E: mv %1 epäonnistui."
MSG_FR[$MSG_MOVE_FAILED]="${MSG_PRF}0007E: Impossible de faire mv à partir de %1."
MSG_ZH[$MSG_MOVE_FAILED]="${MSG_PRF}0007E: mv %1 失败."
MSG_CLEANUP=$((SCNT++))
MSG_EN[$MSG_CLEANUP]="${MSG_PRF}0008I: Cleaning up..."
MSG_DE[$MSG_CLEANUP]="${MSG_PRF}0008I: Räume auf..."
MSG_FI[$MSG_CLEANUP]="${MSG_PRF}0008I: Puhdistetaan..."
MSG_FR[$MSG_CLEANUP]="${MSG_PRF}0008I: Nettoyer..."
MSG_ZH[$MSG_CLEANUP]="${MSG_PRF}0008I: 正在清理..."
MSG_INSTALLATION_FINISHED=$((SCNT++))
MSG_EN[$MSG_INSTALLATION_FINISHED]="${MSG_PRF}0009I: Installation of %1 finished successfully."
MSG_DE[$MSG_INSTALLATION_FINISHED]="${MSG_PRF}0009I: Installation von %1 erfolgreich beendet."
MSG_FI[$MSG_INSTALLATION_FINISHED]="${MSG_PRF}0009I: Kohde %1 asennettu onnistuneesti."
MSG_FR[$MSG_INSTALLATION_FINISHED]="${MSG_PRF}0009I: L'installation de %1 s'est terminée avec succès."
MSG_ZH[$MSG_INSTALLATION_FINISHED]="${MSG_PRF}0009I: 安装 %1 成功."
MSG_UPDATING_CONFIG=$((SCNT++))
MSG_EN[$MSG_UPDATING_CONFIG]="${MSG_PRF}0010I: Updating configuration in %1."
MSG_DE[$MSG_UPDATING_CONFIG]="${MSG_PRF}0010I: Konfigurationsdatei %1 wird angepasst."
MSG_FI[$MSG_UPDATING_CONFIG]="${MSG_PRF}0010I: Päivitetään asetukset tiedostossa %1."
MSG_FR[$MSG_UPDATING_CONFIG]="${MSG_PRF}0010I: Mise à jour de la configuration dans %1."
MSG_ZH[$MSG_UPDATING_CONFIG]="${MSG_PRF}0010I: 更新设置 %1."
MSG_DELETE_FILE=$((SCNT++))
MSG_EN[$MSG_DELETE_FILE]="${MSG_PRF}0011I: Deleting %1..."
MSG_DE[$MSG_DELETE_FILE]="${MSG_PRF}0011I: Lösche %1..."
MSG_FI[$MSG_DELETE_FILE]="${MSG_PRF}0011I: Poistetaan %1..."
MSG_FR[$MSG_DELETE_FILE]="${MSG_PRF}0011I: Suppression de %1..."
MSG_ZH[$MSG_DELETE_FILE]="${MSG_PRF}0011I: 删除 %1..."
MSG_UNINSTALL_FINISHED=$((SCNT++))
MSG_EN[$MSG_UNINSTALL_FINISHED]="${MSG_PRF}0012I: Uninstall of %1 finished successfully."
MSG_DE[$MSG_UNINSTALL_FINISHED]="${MSG_PRF}0012I: Deinstallation von %1 erfolgreich beendet."
MSG_FI[$MSG_UNINSTALL_FINISHED]="${MSG_PRF}0012I: Kohteen %1 asennus poistettu onnistuneesti."
MSG_FR[$MSG_UNINSTALL_FINISHED]="${MSG_PRF}0012I: La désinstallation de %1 s'est terminée avec succès."
MSG_ZH[$MSG_UNINSTALL_FINISHED]="${MSG_PRF}0012I: 卸载 %1 成功."
MSG_UNINSTALL_FAILED=$((SCNT++))
MSG_EN[$MSG_UNINSTALL_FAILED]="${MSG_PRF}0013E: Delete of %1 failed."
MSG_DE[$MSG_UNINSTALL_FAILED]="${MSG_PRF}0013E: Löschen von %1 fehlerhaft beendet."
MSG_FI[$MSG_UNINSTALL_FAILED]="${MSG_PRF}0013E: Kohteen %1 poisto epäonnistui."
MSG_FR[$MSG_UNINSTALL_FAILED]="${MSG_PRF}0013E: Échec de la suppression de %1."
MSG_ZH[$MSG_UNINSTALL_FAILED]="${MSG_PRF}0013E: 删除 %1 失败."
MSG_DOWNLOADING_BETA=$((SCNT++))
MSG_EN[$MSG_DOWNLOADING_BETA]="${MSG_PRF}0014I: Downloading %1 beta..."
MSG_DE[$MSG_DOWNLOADING_BETA]="${MSG_PRF}0014I: %1 beta wird aus dem Netz geladen..."
MSG_FI[$MSG_DOWNLOADING_BETA]="${MSG_PRF}0014I: Ladataan kohteen %1 beta-versiota..."
MSG_FR[$MSG_DOWNLOADING_BETA]="${MSG_PRF}0014I: Téléchargement de %1 bêta..."
MSG_ZH[$MSG_DOWNLOADING_BETA]="${MSG_PRF}0014I: 下载 %1 beta版本..."
MSG_CODE_INSTALLED=$((SCNT++))
MSG_EN[$MSG_CODE_INSTALLED]="${MSG_PRF}0015I: Created %1."
MSG_DE[$MSG_CODE_INSTALLED]="${MSG_PRF}0015I: %1 wurde erstellt."
MSG_FI[$MSG_CODE_INSTALLED]="${MSG_PRF}0015I: Kohde %1 luotu."
MSG_FR[$MSG_CODE_INSTALLED]="${MSG_PRF}0015I: %1 a été créé."
MSG_ZH[$MSG_CODE_INSTALLED]="${MSG_PRF}0015I: 创建 %1."
MSG_NOT_INSTALLED=$((SCNT++))
MSG_EN[$MSG_NOT_INSTALLED]="${MSG_PRF}0016I: %1 not installed."
MSG_DE[$MSG_NOT_INSTALLED]="${MSG_PRF}0016I: %1 nicht installiert."
MSG_FI[$MSG_NOT_INSTALLED]="${MSG_PRF}0016I: %1 ei ole asennettu."
MSG_FR[$MSG_NOT_INSTALLED]="${MSG_PRF}0016I: %1 non installé."
MSG_ZH[$MSG_NOT_INSTALLED]="${MSG_PRF}0016I: %1 未安装."
MSG_CHOWN_FAILED=$((SCNT++))
MSG_EN[$MSG_CHOWN_FAILED]="${MSG_PRF}0017E: chown of %1 failed."
MSG_DE[$MSG_CHOWN_FAILED]="${MSG_PRF}0017E: chown von %1 nicht möglich."
MSG_FI[$MSG_CHOWN_FAILED]="${MSG_PRF}0017E: chown %1 epäonnistui."
MSG_FR[$MSG_CHOWN_FAILED]="${MSG_PRF}0017E: Impossible d'exécuter chown %1."
MSG_ZH[$MSG_CHOWN_FAILED]="${MSG_PRF}0017E: chown of %1 失败."
MSG_SAMPLEEXTENSION_INSTALL_FAILED=$((SCNT++))
MSG_EN[$MSG_SAMPLEEXTENSION_INSTALL_FAILED]="${MSG_PRF}0018E: Sample extension installation failed. %1"
MSG_DE[$MSG_SAMPLEEXTENSION_INSTALL_FAILED]="${MSG_PRF}0018E: Beispielserweiterungsinstallation fehlgeschlagen. %1"
MSG_FI[$MSG_SAMPLEEXTENSION_INSTALL_FAILED]="${MSG_PRF}0018E: Näytelisäosien asennus epäonnistui. %1"
MSG_FR[$MSG_SAMPLEEXTENSION_INSTALL_FAILED]="${MSG_PRF}0018E: L'installation de l'exemple d'extension a échoué. %1"
MSG_ZH[$MSG_SAMPLEEXTENSION_INSTALL_FAILED]="${MSG_PRF}0018E: 扩展安装失败. %1"
MSG_SAMPLEEXTENSION_INSTALL_SUCCESS=$((SCNT++))
MSG_EN[$MSG_SAMPLEEXTENSION_INSTALL_SUCCESS]="${MSG_PRF}0019I: Sample extensions successfully installed and enabled."
MSG_DE[$MSG_SAMPLEEXTENSION_INSTALL_SUCCESS]="${MSG_PRF}0019I: Beispielserweiterungen erfolgreich installiert und eingeschaltet."
MSG_FI[$MSG_SAMPLEEXTENSION_INSTALL_SUCCESS]="${MSG_PRF}0019I: Näytelisäosat asennettu ja otettu käyttöön onnistuneesti."
MSG_FR[$MSG_SAMPLEEXTENSION_INSTALL_SUCCESS]="${MSG_PRF}0019I: Les exemples d'extensions ont été installés et activés avec succès."
MSG_ZH[$MSG_SAMPLEEXTENSION_INSTALL_SUCCESS]="${MSG_PRF}0019I: 扩展安装成功并激活."
MSG_INSTALLING_CRON_TEMPLATE=$((SCNT++))
MSG_EN[$MSG_INSTALLING_CRON_TEMPLATE]="${MSG_PRF}0020I: Creating cron file %1."
MSG_DE[$MSG_INSTALLING_CRON_TEMPLATE]="${MSG_PRF}0020I: Crondatei %1 wird erstellt."
MSG_FI[$MSG_INSTALLING_CRON_TEMPLATE]="${MSG_PRF}0020I: Luodaan cron-tiedosto %1."
MSG_FR[$MSG_INSTALLING_CRON_TEMPLATE]="${MSG_PRF}0020I: Création du fichier cron %1."
MSG_ZH[$MSG_INSTALLING_CRON_TEMPLATE]="${MSG_PRF}0020I: 创建cron文件 %1."
MSG_NO_INTERNET_CONNECTION_FOUND=$((SCNT++))
MSG_EN[$MSG_NO_INTERNET_CONNECTION_FOUND]="${MSG_PRF}0021E: Unable to connect to $MYHOMEDOMAIN. wget RC: %1"
MSG_DE[$MSG_NO_INTERNET_CONNECTION_FOUND]="${MSG_PRF}0021E: Es kann nicht auf $MYHOMEDOMAIN zugegriffen werden. wget RC: %1"
MSG_FI[$MSG_NO_INTERNET_CONNECTION_FOUND]="${MSG_PRF}0021E: Yhdistäminen kohteeseen $MYHOMEDOMAIN epäonnistui. wget RC: %1"
MSG_FR[$MSG_NO_INTERNET_CONNECTION_FOUND]="${MSG_PRF}0021E: Impossible de se connecter à $MYHOMEDOMAIN. Code erreur wget : %1"
MSG_ZH[$MSG_NO_INTERNET_CONNECTION_FOUND]="${MSG_PRF}0021E: 连接 $MYHOMEDOMAIN 失败. wget RC: %1"
MSG_CHECK_INTERNET_CONNECTION=$((SCNT++))
MSG_EN[$MSG_CHECK_INTERNET_CONNECTION]="${MSG_PRF}0022I: Checking internet connection."
MSG_DE[$MSG_CHECK_INTERNET_CONNECTION]="${MSG_PRF}0022I: Teste Internetverbindung."
MSG_FI[$MSG_CHECK_INTERNET_CONNECTION]="${MSG_PRF}0022I: Tarkistetaan verkkoyhteyttä."
MSG_FR[$MSG_CHECK_INTERNET_CONNECTION]="${MSG_PRF}0022I: Vérification de la connexion Internet."
MSG_ZH[$MSG_CHECK_INTERNET_CONNECTION]="${MSG_PRF}0022I: 检查网络连接."
MSG_SAMPLEEXTENSION_UNINSTALL_FAILED=$((SCNT++))
MSG_EN[$MSG_SAMPLEEXTENSION_UNINSTALL_FAILED]="${MSG_PRF}0023E: Sample extension uninstall failed. %1"
MSG_DE[$MSG_SAMPLEEXTENSION_UNINSTALL_FAILED]="${MSG_PRF}0023E: Beispielserweiterungsdeinstallation fehlgeschlagen. %1"
MSG_FI[$MSG_SAMPLEEXTENSION_UNINSTALL_FAILED]="${MSG_PRF}0023E: Näytelisäosien asennuksen poisto epäonnistui. %1"
MSG_FR[$MSG_SAMPLEEXTENSION_UNINSTALL_FAILED]="${MSG_PRF}0023E: Échec de la désinstallation de l'extension de l'exemple. %1"
MSG_ZH[$MSG_SAMPLEEXTENSION_UNINSTALL_FAILED]="${MSG_PRF}0023E: 扩展卸载失败. %1"
MSG_SAMPLEEXTENSION_UNINSTALL_SUCCESS=$((SCNT++))
MSG_EN[$MSG_SAMPLEEXTENSION_UNINSTALL_SUCCESS]="${MSG_PRF}0024I: Sample extensions successfully deleted."
MSG_DE[$MSG_SAMPLEEXTENSION_UNINSTALL_SUCCESS]="${MSG_PRF}0024I: Beispielserweiterungen erfolgreich gelöscht."
MSG_FI[$MSG_SAMPLEEXTENSION_UNINSTALL_SUCCESS]="${MSG_PRF}0024I: Näytelisäosat poistettiin onnistuneesti."
MSG_FR[$MSG_SAMPLEEXTENSION_UNINSTALL_SUCCESS]="${MSG_PRF}0024I: Exemples d'extensions supprimés avec succès."
MSG_ZH[$MSG_SAMPLEEXTENSION_UNINSTALL_SUCCESS]="${MSG_PRF}0024I: 扩展已被删除."
MSG_UNINSTALLING_CRON_TEMPLATE=$((SCNT++))
MSG_EN[$MSG_UNINSTALLING_CRON_TEMPLATE]="${MSG_PRF}0025I: Deleting cron file %1."
MSG_DE[$MSG_UNINSTALLING_CRON_TEMPLATE]="${MSG_PRF}0025I: Crondatei %1 wird gelöscht."
MSG_FI[$MSG_UNINSTALLING_CRON_TEMPLATE]="${MSG_PRF}0025I: Poistetaan cron-tiedosto %1."
MSG_FR[$MSG_UNINSTALLING_CRON_TEMPLATE]="${MSG_PRF}0025I: Suppression du fichier cron %1."
MSG_ZH[$MSG_UNINSTALLING_CRON_TEMPLATE]="${MSG_PRF}0025I: 删除cron文件 %1."
MSG_UPDATING_CRON=$((SCNT++))
MSG_EN[$MSG_UPDATING_CRON]="${MSG_PRF}0026I: Updating cron configuration in %1."
MSG_DE[$MSG_UPDATING_CRON]="${MSG_PRF}0026I: Cron Konfigurationsdatei %1 wird angepasst."
MSG_FI[$MSG_UPDATING_CRON]="${MSG_PRF}0026I: Päivitetään cron-asetukset kohteessa %1."
MSG_FR[$MSG_UPDATING_CRON]="${MSG_PRF}0026I: Le fichier de configuration Cron %1 a été mis à jour."
MSG_ZH[$MSG_UPDATING_CRON]="${MSG_PRF}0026I: 更新cron文件 %1."
MSG_MISSING_DIRECTORY=$((SCNT++))
MSG_EN[$MSG_MISSING_DIRECTORY]="${MSG_PRF}0027E: Missing required directory %1."
MSG_DE[$MSG_MISSING_DIRECTORY]="${MSG_PRF}0027E: Erforderliches Verzeichnis %1 existiert nicht."
MSG_FI[$MSG_MISSING_DIRECTORY]="${MSG_PRF}0027E: Vaadittu hakemisto %1 puuttuu."
MSG_FR[$MSG_MISSING_DIRECTORY]="${MSG_PRF}0027E: Le répertoire requis %1 n'existe pas."
MSG_ZH[$MSG_MISSING_DIRECTORY]="${MSG_PRF}0027E: 缺少必要的路径 %1."
MSG_CODE_UPDATED=$((SCNT++))
MSG_EN[$MSG_CODE_UPDATED]="${MSG_PRF}0028I: Updated %1 with latest available release."
MSG_DE[$MSG_CODE_UPDATED]="${MSG_PRF}0028I: %1 wurde mit dem letzen aktuellen Release erneuert."
MSG_FI[$MSG_CODE_UPDATED]="${MSG_PRF}0028I: %1 päivitetty viimeisimpään julkaisuun."
MSG_FR[$MSG_CODE_UPDATED]="${MSG_PRF}0028I: %1 a été remplacé par la version la plus récente."
MSG_ZH[$MSG_CODE_UPDATED]="${MSG_PRF}0028I: 更新 %1 到最新版本."
MSG_INSTALLING_SYSTEMD_TEMPLATE=$((SCNT++))
MSG_EN[$MSG_INSTALLING_SYSTEMD_TEMPLATE]="${MSG_PRF}0029I: Creating systemd file %1."
MSG_DE[$MSG_INSTALLING_SYSTEMD_TEMPLATE]="${MSG_PRF}0029I: Systemddatei %1 wird erstellt."
MSG_UNINSTALLING_SYSTEMD_TEMPLATE=$((SCNT++))
MSG_EN[$MSG_UNINSTALLING_SYSTEMD_TEMPLATE]="${MSG_PRF}0030I: Deleting systemd file %1."
MSG_DE[$MSG_UNINSTALLING_SYSTEMD_TEMPLATE]="${MSG_PRF}0030I: Systemddatei %1 wird gelöscht."
MSG_UPDATING_SYSTEMD=$((SCNT++))
MSG_EN[$MSG_UPDATING_SYSTEMD]="${MSG_PRF}0031I: Updating systemd configuration in %1."
MSG_DE[$MSG_UPDATING_SYSTEMD]="${MSG_PRF}0031I: Systemd Konfigurationsdatei %1 wird angepasst."
MSG_SYSTEMD_ENABLED=$((SCNT++))
MSG_EN[$MSG_SYSTEMD_ENABLED]="${MSG_PRF}0032I: Systemd enabled."
MSG_DE[$MSG_SYSTEMD_ENABLED]="${MSG_PRF}0032I: Systemd eingeschaltet."
MSG_SYSTEMD_DISABLED=$((SCNT++))
MSG_EN[$MSG_SYSTEMD_DISABLED]="${MSG_PRF}0033I: $RASPIBACKUP_NAME systemd timer disabled."
MSG_DE[$MSG_SYSTEMD_DISABLED]="${MSG_PRF}0033I: $RASPIBACKUP_NAME systemd timer ausgeschaltet."
MSG_TITLE=$((SCNT++))
MSG_EN[$MSG_TITLE]="$RASPIBACKUP_NAME Installation and Configuration Tool V${VERSION}"
MSG_DE[$MSG_TITLE]="$RASPIBACKUP_NAME Installations- und Konfigurations Tool V${VERSION}"
MSG_FI[$MSG_TITLE]="$RASPIBACKUP_NAME Asennus- ja määritystyökalu V${VERSION}"
MSG_FR[$MSG_TITLE]="$RASPIBACKUP_NAME Outil d'installation et de configuration V${VERSION}"
MSG_ZH[$MSG_TITLE]="$RASPIBACKUP_NAME 安装和设置工具 版本V${VERSION}"
BUTTON_FINISH=$((SCNT++))
MSG_EN[$BUTTON_FINISH]="Finish"
MSG_DE[$BUTTON_FINISH]="Beenden"
MSG_FI[$BUTTON_FINISH]="Lopeta"
MSG_FR[$BUTTON_FINISH]="Terminer"
MSG_ZH[$BUTTON_FINISH]="完成"
BUTTON_SELECT=$((SCNT++))
MSG_EN[$BUTTON_SELECT]="Select"
MSG_DE[$BUTTON_SELECT]="Auswahl"
MSG_FI[$BUTTON_SELECT]="Valitse"
MSG_FR[$BUTTON_SELECT]="Valider"
MSG_ZH[$BUTTON_SELECT]="选择"
BUTTON_BACK=$((SCNT++))
MSG_EN[$BUTTON_BACK]="Back"
MSG_DE[$BUTTON_BACK]="Zurück"
MSG_FI[$BUTTON_BACK]="Takaisin"
MSG_FR[$BUTTON_BACK]="Retour"
MSG_ZH[$BUTTON_BACK]="返回"
SELECT_TIME=$((SCNT++))
MSG_EN[$SELECT_TIME]="Enter time of backup in format hh:mm"
MSG_DE[$SELECT_TIME]="Die Backupzeit im Format hh:mm eingeben"
MSG_FI[$SELECT_TIME]="Syötä varmuuskopioinnin kellonaika muodossa hh:mm"
MSG_FR[$SELECT_TIME]="Saisissez l'heure de la sauvegarde au format hh:mm"
MSG_ZH[$SELECT_TIME]="输入以时间命名备份的格式 hh:mm"
BUTTON_CANCEL=$((SCNT++))
MSG_EN[$BUTTON_CANCEL]="Cancel"
MSG_DE[$BUTTON_CANCEL]="Abbruch"
MSG_FI[$BUTTON_CANCEL]="Peruuta"
MSG_FR[$BUTTON_CANCEL]="Annuler"
MSG_ZH[$BUTTON_CANCEL]="取消"
BUTTON_OK=$((SCNT++))
MSG_EN[$BUTTON_OK]="Ok"
MSG_DE[$BUTTON_OK]="Bestätigen"
MSG_FI[$BUTTON_OK]="OK"
MSG_FR[$BUTTON_OK]="Confirmer"
MSG_ZH[$BUTTON_OK]="确认"
MSG_QUESTION_UPDATE_CONFIG=$((SCNT++))
MSG_EN[$MSG_QUESTION_UPDATE_CONFIG]="Do you want to save the updated $RASPIBACKUP_NAME configuration now?"
MSG_DE[$MSG_QUESTION_UPDATE_CONFIG]="Soll die geänderte Konfiguration von $RASPIBACKUP_NAME jetzt gespeichert werden?"
MSG_FI[$MSG_QUESTION_UPDATE_CONFIG]="Haluatko tallentaa päivitetyt $RASPIBACKUP_NAME-asetukset nyt?"
MSG_FR[$MSG_QUESTION_UPDATE_CONFIG]="La configuration de $RASPIBACKUP_NAME a été modifiée, Enregistrer maintenant?"
MSG_ZH[$MSG_QUESTION_UPDATE_CONFIG]="是否立刻更新 $RASPIBACKUP_NAME 设置?"
MSG_QUESTION_IGNORE_MISSING_STARTSTOP=$((SCNT++))
MSG_EN[$MSG_QUESTION_IGNORE_MISSING_STARTSTOP]="There are no services stopped before starting the backup.${NL}WARNING${NL}Inconsistent backups may be created with $RASPIBACKUP_NAME.${NL}Are you sure?"
MSG_DE[$MSG_QUESTION_IGNORE_MISSING_STARTSTOP]="Es werden keine Services vor dem Start des Backups gestoppt.${NL}WARNUNG${NL}Dadurch können inkonsistente Backups mit $RASPIBACKUP_NAME entstehen.${NL}Ist das beabsichtigt?"
MSG_FI[$MSG_QUESTION_IGNORE_MISSING_STARTSTOP]="Palveluita ei ole valittu pysäytettäväksi ennen varmuuskopiointia.${NL}VAROITUS${NL}Tämä voi johtaa $RASPIBACKUP_NAME-varmuuskopioiden epäyhtenäisyyteen.${NL}Oletko varma?"
MSG_FR[$MSG_QUESTION_IGNORE_MISSING_STARTSTOP]="Aucun service ne sera arrêté avant le démarrage de la sauvegarde.${NL}VAROITUS${NL}Cela peut entraîner des incohérences avec $RASPIBACKUP_NAME.${NL}Etes-vous sûre?"
MSG_ZH[$MSG_QUESTION_IGNORE_MISSING_STARTSTOP]="备份前没有停止任何服务.${NL}警告${NL}可能会创建一个与$RASPIBACKUP_NAME名称不一致的备份.${NL}是否继续?"
MSG_QUESTION_UPDATE_CRON=$((SCNT++))
MSG_EN[$MSG_QUESTION_UPDATE_CRON]="Do you want to save the updated cron settings for $RASPIBACKUP_NAME now?"
MSG_DE[$MSG_QUESTION_UPDATE_CRON]="Soll die geänderte cron Konfiguration für $RASPIBACKUP_NAME jetzt gespeichert werden?"
MSG_FI[$MSG_QUESTION_UPDATE_CRON]="Haluatko tallentaa nyt päivitetyt cron-asetukset kohteelle $RASPIBACKUP_NAME?"
MSG_FR[$MSG_QUESTION_UPDATE_CRON]="Voulez-vous enregistrer les paramètres cron mis à jour pour $RASPIBACKUP_NAME maintenant ?"
MSG_ZH[$MSG_QUESTION_UPDATE_CRON]="是否保存$RASPIBACKUP_NAME 更新的cron设置?"
MSG_QUESTION_UPDATE_SYSTEMD=$((SCNT++))
MSG_EN[$MSG_QUESTION_UPDATE_SYSTEMD]="Do you want to save the updated systemd settings for $RASPIBACKUP_NAME now?"
MSG_DE[$MSG_QUESTION_UPDATE_SYSTEMD]="Soll die geänderte systemd Konfiguration für $RASPIBACKUP_NAME jetzt gespeichert werden?"
MSG_SEQUENCE_OK=$((SCNT++))
MSG_EN[$MSG_SEQUENCE_OK]="Stopcommands for services will be executed in following sequence. Startcommands will be executed in reverse sequence. Sequence OK?"
MSG_DE[$MSG_SEQUENCE_OK]="Stopbefehle für die Services werden in folgender Reihenfolge ausgeführt. Startbefehle werden umgekehrt ausgeführt. Ist die Reihenfolge richtig?"
MSG_FI[$MSG_SEQUENCE_OK]="Palvelut pysäytetään seuraavassa järjestyksessä ja ne käynnistetään uudelleen käänteisessä järjestyksessä. Onko järjestys OK?"
MSG_FR[$MSG_SEQUENCE_OK]="Les commandes d'arrêt pour les services seront exécutées dans l'ordre suivant. Les commandes de démarrage seront exécutées dans l'ordre inverse. d'accord?"
MSG_ZH[$MSG_SEQUENCE_OK]="停止服务命令将按以下顺序停止,启动服务命令按反序执行 OK?"
BUTTON_YES=$((SCNT++))
MSG_EN[$BUTTON_YES]="Yes"
MSG_DE[$BUTTON_YES]="Ja"
MSG_FI[$BUTTON_YES]="Kyllä"
MSG_FR[$BUTTON_YES]="Oui"
MSG_ZH[$BUTTON_YES]="Yes"
BUTTON_NO=$((SCNT++))
MSG_EN[$BUTTON_NO]="No"
MSG_DE[$BUTTON_NO]="Nein"
MSG_FI[$BUTTON_NO]="Ei"
MSG_FR[$BUTTON_NO]="Non"
MSG_ZH[$BUTTON_NO]="No"
MSG_QUESTION_UNINSTALL=$((SCNT++))
MSG_EN[$MSG_QUESTION_UNINSTALL]="Are you sure to uninstall $RASPIBACKUP_NAME ?"
MSG_DE[$MSG_QUESTION_UNINSTALL]="Soll $RASPIBACKUP_NAME wirklich deinstalliert werden ?"
MSG_FI[$MSG_QUESTION_UNINSTALL]="Haluatko varmasti poistaa koko kohteen $RASPIBACKUP_NAME ?"
MSG_FR[$MSG_QUESTION_UNINSTALL]="Êtes-vous sûr de vouloir désinstaller $RASPIBACKUP_NAME ?"
MSG_ZH[$MSG_QUESTION_UNINSTALL]="确认卸载 $RASPIBACKUP_NAME 么?"
MSG_SCRIPT_NOT_INSTALLED=$((SCNT++))
MSG_EN[$MSG_SCRIPT_NOT_INSTALLED]="$RASPIBACKUP_NAME not installed."
MSG_DE[$MSG_SCRIPT_NOT_INSTALLED]="$RASPIBACKUP_NAME ist nicht installiert"
MSG_FI[$MSG_SCRIPT_NOT_INSTALLED]="$RASPIBACKUP_NAME ei ole asennettuna."
MSG_FR[$MSG_SCRIPT_NOT_INSTALLED]="$RASPIBACKUP_NAME n'est pas installé."
MSG_ZH[$MSG_SCRIPT_NOT_INSTALLED]="$RASPIBACKUP_NAME 尚未安装."
MSG_TIMER_NA=$((SCNT++))
MSG_EN[$MSG_TIMER_NA]="Weekly backup disabled."
MSG_DE[$MSG_TIMER_NA]="Wöchentliches Backup ist ausgeschaltet."
MSG_FI[$MSG_TIMER_NA]="Viikoittainen varmuuskopiointi ei ole käytössä."
MSG_FR[$MSG_TIMER_NA]="La sauvegarde hebdomadaire est désactivée."
MSG_ZH[$MSG_TIMER_NA]="每周备份已禁用."
MSG_CONFIG_NOT_INSTALLED=$((SCNT++))
MSG_EN[$MSG_CONFIG_NOT_INSTALLED]="No configuration found."
MSG_DE[$MSG_CONFIG_NOT_INSTALLED]="Keine Konfiguration gefunden."
MSG_FI[$MSG_CONFIG_NOT_INSTALLED]="Asetuksia ei löytynyt."
MSG_FR[$MSG_CONFIG_NOT_INSTALLED]="Aucune configuration trouvée."
MSG_ZH[$MSG_CONFIG_NOT_INSTALLED]="未找到配置文件."
MSG_CRON_NOT_INSTALLED=$((SCNT++))
MSG_EN[$MSG_CRON_NOT_INSTALLED]="No cron configuration found."
MSG_DE[$MSG_CRON_NOT_INSTALLED]="Keine cron Konfiguration gefunden."
MSG_FI[$MSG_CRON_NOT_INSTALLED]="Cron-asetuksia ei löytynyt."
MSG_FR[$MSG_CRON_NOT_INSTALLED]="Aucune configuration cron trouvée.."
MSG_ZH[$MSG_CRON_NOT_INSTALLED]="Cron未找到."
MSG_NO_UPDATE_AVAILABLE=$((SCNT++))
MSG_EN[$MSG_NO_UPDATE_AVAILABLE]="(No update available)"
MSG_DE[$MSG_NO_UPDATE_AVAILABLE]="(Kein Update verfügbar)"
MSG_FI[$MSG_NO_UPDATE_AVAILABLE]="(Päivitystä ei ole saatavilla)"
MSG_FR[$MSG_NO_UPDATE_AVAILABLE]="(Pas de mise a jour disponible)"
MSG_ZH[$MSG_NO_UPDATE_AVAILABLE]="(没有可用更新)"
MSG_NO_EXTENSIONS_FOUND=$((SCNT++))
MSG_EN[$MSG_NO_EXTENSIONS_FOUND]="No extensions installed."
MSG_DE[$MSG_NO_EXTENSIONS_FOUND]="Keine Erweiterungen installiert."
MSG_FI[$MSG_NO_EXTENSIONS_FOUND]="Lisäosia ei ole asennettu."
MSG_FR[$MSG_NO_EXTENSIONS_FOUND]="Aucune extension installée."
MSG_ZH[$MSG_NO_EXTENSIONS_FOUND]="尚未安装扩展."
MSG_EXTENSIONS_ALREADY_INSTALLED=$((SCNT++))
MSG_EN[$MSG_EXTENSIONS_ALREADY_INSTALLED]="Extensions already installed."
MSG_DE[$MSG_EXTENSIONS_ALREADY_INSTALLED]="Extensions sind bereits installiert."
MSG_FI[$MSG_EXTENSIONS_ALREADY_INSTALLED]="Lisäosat ovat jo asennettuna."
MSG_FR[$MSG_EXTENSIONS_ALREADY_INSTALLED]="Les extensions sont déjà installées."
MSG_ZH[$MSG_EXTENSIONS_ALREADY_INSTALLED]="扩展已安装."
MSG_SCRIPT_ALREADY_INSTALLED=$((SCNT++))
MSG_EN[$MSG_SCRIPT_ALREADY_INSTALLED]="$RASPIBACKUP_NAME already installed.${NL}Do you want to reinstall $RASPIBACKUP_NAME ?"
MSG_DE[$MSG_SCRIPT_ALREADY_INSTALLED]="$RASPIBACKUP_NAME ist bereits installiert.${NL}Soll die bestehende Installation überschrieben werden ?"
MSG_FI[$MSG_SCRIPT_ALREADY_INSTALLED]="$RASPIBACKUP_NAME on jo asennettu.${NL} Haluatko uudelleenasentaa kohteen $RASPIBACKUP_NAME ?"
MSG_FR[$MSG_SCRIPT_ALREADY_INSTALLED]="$RASPIBACKUP_NAME est déjà installé.${NL}Voulez-vous écraser l'installation existante ?"
MSG_DOWNLOADING_PROPERTYFILE=$((SCNT++))
MSG_EN[$MSG_DOWNLOADING_PROPERTYFILE]="Downloading version information."
MSG_DE[$MSG_DOWNLOADING_PROPERTYFILE]="Versionsinformationen werden runtergeladen."
MSG_FI[$MSG_DOWNLOADING_PROPERTYFILE]="Ladataan version tietoja."
MSG_FR[$MSG_DOWNLOADING_PROPERTYFILE]="Les informations de version seront téléchargées."
MSG_ZH[$MSG_DOWNLOADING_PROPERTYFILE]="下载版本信息."
MSG_INVALID_KEEP=$((SCNT++))
MSG_EN[$MSG_INVALID_KEEP]="Invalid number %1 entered. Number has to be between 1 and 52."
MSG_DE[$MSG_INVALID_KEEP]="Ungültige Zahl %1 eingegeben. Sie muss zwischen 1 und 52 liegen."
MSG_FI[$MSG_INVALID_KEEP]="Epäkelpo numero %1 syötetty. Numeron tulee olla 1:n ja 52:n väliltä."
MSG_FR[$MSG_INVALID_KEEP]="Nombre non valide %1 saisi. Il doit être compris entre 1 et 52."
MSG_ZH[$MSG_INVALID_KEEP]="输入的 %1 无效. 数字必须在1和52之间."
MSG_INVALID_KEEP_NUMBER_COUNT=$((SCNT++))
MSG_EN[$MSG_INVALID_KEEP_NUMBER_COUNT]="Insert one number only."
MSG_DE[$MSG_INVALID_KEEP_NUMBER_COUNT]="Nur eine Zahl eingeben."
MSG_FI[$MSG_INVALID_KEEP_NUMBER_COUNT]="Syötä vain yksi numero."
MSG_FR[$MSG_INVALID_KEEP_NUMBER_COUNT]="Entrez un seul numéro."
MSG_ZH[$MSG_INVALID_KEEP_NUMBER_COUNT]="请仅插入一个数字."
MSG_INVALID_SMART=$((SCNT++))
MSG_EN[$MSG_INVALID_SMART]="Invalid number %1 entered. Number has to be >= 0."
MSG_DE[$MSG_INVALID_SMART]="Ungültige Zahl %1 eingegeben. Sie muss >= 0 sein."
MSG_FI[$MSG_INVALID_SMART]="Epäkelpo numero %1 syötetty. Numeron tulee olla >= 0."
MSG_FR[$MSG_INVALID_SMART]="Nombre non valide %1 saisi. Il doit être >= 0."
MSG_ZH[$MSG_INVALID_SMART]="输入的 %1 无效. 数字必须>= 0."
MSG_INVALID_SMART_NUMBER_COUNT=$((SCNT++))
MSG_EN[$MSG_INVALID_SMART_NUMBER_COUNT]="Expect four numbers separated by spaces: daily, weekly, monthly and yearly backups."
MSG_DE[$MSG_INVALID_SMART_NUMBER_COUNT]="Vier durch Leerzeichen getrennte Zahlen werden erwartet: Tägliche, wöchentliche, monatliche und jährliche Backups."
MSG_FI[$MSG_INVALID_SMART_NUMBER_COUNT]="Vaaditaan neljä välilyönnein erotettua numeroa: päivittäinen, viikoittainen, kuukausittainen ja vuosittainen varmuuskopiointien lukumäärä"
MSG_FR[$MSG_INVALID_SMART_NUMBER_COUNT]="Quatre nombres séparés par des espaces sont attendus : sauvegardes quotidiennes, hebdomadaires, mensuelles et annuelles."
MSG_ZH[$MSG_INVALID_SMART_NUMBER_COUNT]="四个分隔数字分别代表:按日、按周、按月、按年的备份"
MSG_INVALID_KEEP_NUMBER_COUNT=$((SCNT++))
MSG_EN[$MSG_INVALID_KEEP_NUMBER_COUNT]="Enter one single number only."
MSG_DE[$MSG_INVALID_KEEP_NUMBER_COUNT]="Nur eine einzige Zahl eingeben."
MSG_FI[$MSG_INVALID_KEEP_NUMBER_COUNT]="Syötä vain yksi numero."
MSG_FR[$MSG_INVALID_KEEP_NUMBER_COUNT]="Entrez un seul numéro."
MSG_ZH[$MSG_INVALID_KEEP_NUMBER_COUNT]="请仅输入一个数字."
MSG_INVALID_TIME=$((SCNT++))
MSG_EN[$MSG_INVALID_TIME]="Invalid time '%1'. Input has to be in format hh:mm and 0<=hh<24 and 0<=mm<60."
MSG_DE[$MSG_INVALID_TIME]="Ungültige Zeit '%1'. Die Eingabe muss im Format hh:mm sein und 0<=hh<24 und 0<=mm<60."
MSG_FI[$MSG_INVALID_TIME]="Epäkelpo kellonaika '%1'. Ajan tulee olla muodossa hh:mm ja 0<=hh<24 sekä 0<=mm<60."
MSG_FR[$MSG_INVALID_TIME]="Heure non valide '%1'. L'entrée doit être au format hh:mm et 0<=hh<24 et 0<=mm<60."
MSG_ZH[$MSG_INVALID_TIME]="无效的时间 '%1'. 输入的格式必须为 hh:mm 0<=hh<24 且 0<=mm<60."
MSG_RUNASROOT=$((SCNT++))
MSG_EN[$MSG_RUNASROOT]="$MYSELF has to be started as root. Try 'sudo %1%2'."
MSG_DE[$MSG_RUNASROOT]="$MYSELF muss als root gestartet werden. Benutze 'sudo %1%2'."
MSG_FI[$MSG_RUNASROOT]="$MYSELF tulee käynnistää root-oikeuksin. Käynnistä 'sudo %1%2'."
MSG_FR[$MSG_RUNASROOT]="$MYSELF doit être démarré en tant que root. Utilisez 'sudo %1%2'."
MSG_ZH[$MSG_RUNASROOT]="$MYSELF 必须以root身份开启. 请尝试 'sudo %1%2'."
MSG_SYSTEMD_NOT_INSTALLED=$((SCNT++))
MSG_EN[$MSG_SYSTEMD_NOT_INSTALLED]="No systemd configuration found."
MSG_DE[$MSG_SYSTEMD_NOT_INSTALLED]="Keine systemd Konfiguration gefunden."
DESCRIPTION_INSTALLATION=$((SCNT++))
MSG_EN[$DESCRIPTION_INSTALLATION]="${NL}$RASPIBACKUP_NAME allows to plug in custom extensions which are called before and after the backup process. \
There exist sample extensions which report the memory usage, CPU temperature and disk usage of the backup partition. \
For details see${NL}https://www.linux-tips-and-tricks.de/en/raspibackupcategoryy/443-raspibackup-extensions."
MSG_DE[$DESCRIPTION_INSTALLATION]="${NL}$RASPIBACKUP_NAME erlaubt selbstgeschriebene Erweiterungen vor und nach dem Backupprozess aufzurufen. \
Es gibt Beispielerweiterungen die die Speicherauslastung, die CPU Temperatur sowie die Speicherplatzbenutzung der Backuppartition anzeigen. \
Für weitere Details siehe${NL}https://www.linux-tips-and-tricks.de/de/13-raspberry/442-raspibackup-erweiterungen."
MSG_FI[$DESCRIPTION_INSTALLATION]="${NL}$RASPIBACKUP_NAME tukee lisäosia, joiden toimintoja voidaan suorittaa ennen ja jälkeen varmuuskopioinnin. \
Mukana tulevat näytelisäosat esittävät prosessorin lämpötilan sekä tietoja muistin ja varmuuskopiointilevyn käytöstä. \
${NL}Lue lisätietoja osoitteesta https://www.linux-tips-and-tricks.de/en/raspibackupcategoryy/443-raspibackup-extensions."
MSG_FR[$DESCRIPTION_INSTALLATION]="${NL}$RASPIBACKUP_NAME vous permet d'appeler des extensions auto-écrites avant et après le processus de sauvegarde. \
Il existe des exemples d'extensions qui montrent l'utilisation de la mémoire, la température du processeur et l'utilisation de l'espace de stockage de la partition de sauvegarde. \
${NL}Pour plus de détails voir https://www.linux-tips-and-tricks.de/en/raspibackupcategoryy/443-raspibackup-extensions."
MSG_ZH[$DESCRIPTION_INSTALLATION]="${NL}$RASPIBACKUP_NAME 允许插入自定义扩展,备份前后均可插入. \
已有示例扩展报告内存占用,CPU温度和备份硬盘占用. \
${NL}详情请 https://www.linux-tips-and-tricks.de/en/raspibackupcategoryy/443-raspibackup-extensions."
DESCRIPTION_COMPRESS=$((SCNT++))
MSG_EN[$DESCRIPTION_COMPRESS]="${NL}$RASPIBACKUP_NAME can compress dd and tar backups to reduce the size of the backup. Please note this will increase backup time and will heaten the CPU. \
Please note an option of $FILE_TO_INSTALL which will reduce the size of a dd backup also. \
For details see https://www.linux-tips-and-tricks.de/en/faq#a16."
MSG_DE[$DESCRIPTION_COMPRESS]="${NL}$RASPIBACKUP_NAME kann dd und tar Backups kompressen um die Backupgröße zu reduzieren. Das bedeutet aber dass die Backupzeit steigt und die CPU erwärmen wird. \
$FILE_TO_INSTALL bietet auch eine Option an mit der ein dd Backup verkleinert werden kann. Siehe dazu \
https://www.linux-tips-and-tricks.de/de/faq#a16."
MSG_FI[$DESCRIPTION_COMPRESS]="${NL}$RASPIBACKUP_NAME voi pakata dd- ja tar-varmuuskopiot, jotta ne veisivät vähemmän tilaa. Huomioithan, että tämä pidentää varmuuskopioinnin aikaa ja nostaa CPU:n lämpötilaa. \
Huomioi myös vaihtoehto $FILE_TO_INSTALL, joka vähentää dd-varmuuskopioiden käyttämää tilaa. \
Lisätietoja löydät osoitteesta https://www.linux-tips-and-tricks.de/en/faq#a16."
MSG_FR[$DESCRIPTION_COMPRESS]="${NL}$RASPIBACKUP_NAME peut compresser les sauvegardes dd et tar pour réduire leurs tailles . Cependant, cela signifie que le temps de sauvegarde augmentera et que le cpu se réchauffera. \
$FILE_TO_INSTALL, offre également une option avec laquelle une sauvegarde dd peut être réduite. Voir. \
https://www.linux-tips-and-tricks.de/en/faq#a16."
MSG_ZH[$DESCRIPTION_COMPRESS]="${NL}$RASPIBACKUP_NAME 可以压缩 dd和tar备份文件. 但是这会在备份期间增加备份时间和使CPU升温. \
勾选 $FILE_TO_INSTALL, 开启压缩. \
详情见 https://www.linux-tips-and-tricks.de/en/faq#a16."
DESCRIPTION_CRON=$((SCNT++))
MSG_EN[$DESCRIPTION_CRON]="${NL}$RASPIBACKUP_NAME should be started on a regular base when the initial configuration and backup and restore testing was done. \
Configure the backup to be created daily or weekly. For other backup intervals you have to modify /etc/cron.d/raspiBackup manually."
MSG_DE[$DESCRIPTION_CRON]="${NL}$RASPIBACKUP_NAME sollte regelmäßig gestartet werden wenn die initiale Konfiguration sowie Backup und Restore Tests beendet sind. \
Konfiguriere den Backup täglich oder wöchentlich zu erstellen. Für andere Intervalle muss die Datei /etc/cron.d/raspiBackup manuell geändert werden."
MSG_FI[$DESCRIPTION_CRON]="${NL}$RASPIBACKUP_NAME tulisi ajaa äännöllisesti se jälkeen, kun asetusten määritysten jälkeen ensimmäinen varmuuskopio on suoritettu ja varmuuskopion palautus on testattu. \
Ajasta varmuuskopiointi päivittäiseksi tai viikottaiseksi. Muita varmuuskopioinnin aikavälejä varten tulee muokata tiedostoa /etc/cron.d/raspiBackup manuaalisesti."
MSG_FR[$DESCRIPTION_CRON]="${NL}$RASPIBACKUP_NAME doit être démarré régulièrement lorsque les premiers tests de configuration ,de sauvegarde et de restauration sont terminés. \
Configurez la sauvegarde à exécuter quotidiennement ou hebdomadairement. Pour d'autres intervalles de sauvegardes vous devez modifier manuellement le fichier /etc/cron.d/raspiBackup ."
MSG_ZH[$DESCRIPTION_CRON]="${NL}$RASPIBACKUP_NAME 会在完成初始配置以及备份和恢复测试后定期启动. \
配置每天或每周创建备份。对于其他备份间隔,您必须手动修改/etc/cron.d/raspiBackup."
DESCRIPTION_SYSTEMD=$((SCNT++))
MSG_EN[$DESCRIPTION_SYSTEMD]="${NL}$RASPIBACKUP_NAME should be started on a regular base when the initial configuration and backup and restore testing was done. \
Configure the backup to be created daily or weekly. For other backup intervals you have to modify /etc/systemd/system/raspiBackup.timer manually."
MSG_DE[$DESCRIPTION_SYSTEMD]="${NL}$RASPIBACKUP_NAME sollte regelmäßig gestartet werden wenn die initiale Konfiguration sowie Backup und Restore Tests beendet sind. \
Konfiguriere den Backup täglich oder wöchentlich zu erstellen. Für andere Intervalle muss die Datei /etc/systemd/system/raspiBackup.timer manuell geändert werden."
DESCRIPTION_SMARTMODE=$((SCNT++))
MSG_EN[$DESCRIPTION_SMARTMODE]="${NL}There exist two different ways to define the number of backups. Just by defining the maximum number of backups to keep or \
by using the smart backup strategy. See https://www.linux-tips-and-tricks.de/en/smart-recycle/ for details about the strategy."
MSG_DE[$DESCRIPTION_SMARTMODE]="${NL}Es gibt grundsätzlich zwei Methoden, die Anzahl der vorzuhaltenden Backups festzulegen. Dies erfolgt entweder durch die Definition der maximalen Anzahl oder durch Verwendung der intelligenten Backupstrategie. \
Eine Detailbeschreibung der Strategie befindet sich auf https://www.linux-tips-and-tricks.de/de/rotationsstrategie/."
MSG_FI[$DESCRIPTION_SMARTMODE]="${NL}Voit määrittää säilytettävien varmuuskopioiden lukumäärän joko määrittämällä säilytettävien varmuuskopioiden maksimimäärän tai \
käyttämällä älykästä varmuuskopiointia.${NL}Katso lisätietoa osoitteesta https://www.linux-tips-and-tricks.de/en/smart-recycle/."
MSG_FR[$DESCRIPTION_SMARTMODE]="${NL}Il existe deux méthodes pour définir le nombre de sauvegardes à conserver : SIMPLE ou INTELLIGENTE. Cela se fait soit en définissant un nombre maximum, soit en utilisant la stratégie de sauvegarde intelligente. \
Une description détaillée de la stratégie est disponible sur https://www.linux-tips-and-tricks.de/en/smart-recycle/."
MSG_ZH[$DESCRIPTION_SMARTMODE]="${NL}当前有两种方法定义备份数量:定义最大备份数或者用只能备份策略,策略详情: \
${NL} https://www.linux-tips-and-tricks.de/en/smart-recycle/."
DESCRIPTION_MESSAGEDETAIL=$((SCNT++))
MSG_EN[$DESCRIPTION_MESSAGEDETAIL]="${NL}$RASPIBACKUP_NAME can either be very verbose or just write important messages. \
Usually it makes sense to turn all on when installing $RASPIBACKUP_NAME the first time. Later on you can change it to write important messages only."
MSG_DE[$DESCRIPTION_MESSAGEDETAIL]="${NL}$RASPIBACKUP_NAME kann viele Meldungen schreiben oder nur die Wichtigsten. \
Es macht Sinn alle beim ersten Installieren von $RASPIBACKUP_NAME anzuschalten. Später können sie auf die Wichtigsten reduziert werden."
MSG_FI[$DESCRIPTION_MESSAGEDETAIL]="${NL}$RASPIBACKUP_NAME voi joko kirjoittaa yksityiskohtaiset tai vain tärkeät viestit. \
Yleensä ensimmäisen $RASPIBACKUP_NAME-asennuksen jälkeen yksityiskohtaiset viestit on hyvä näyttää. Voit myöhemmin valita kirjoitettavaksi vain tärkeät viestit."
MSG_FR[$DESCRIPTION_MESSAGEDETAIL]="${NL}$RASPIBACKUP_NAME peut écrire de nombreux messages ou seulement les plus importants. \
Il est logique de les activer tous lors de la première installation de $RASPIBACKUP_NAME Plus tard, ils peuvent être réduits aux plus importants."
MSG_ZH[$DESCRIPTION_MESSAGEDETAIL]="${NL}$RASPIBACKUP_NAME 可以非常详细或者只显示重要信息. \
通常第一次安装$RASPIBACKUP_NAME后打开所有选项是有意义的,随后你可切换至只写入重要信息."
DESCRIPTION_STARTSTOP=$((SCNT++))
MSG_EN[$DESCRIPTION_STARTSTOP]="${NL}Before and after creating a backup important services should be stopped and started. Add the required services separated by a space which should be stopped in the correct order. \
The services will be started in reverse order when backup finished. For further details see https://www.linux-tips-and-tricks.de/en/faq#a18."
MSG_DE[$DESCRIPTION_STARTSTOP]="${NL}Vor und nach einem Backup sollten immer alle wichtigen Services gestoppt und gestartet werden. Dazu müssen die notwendigen Services die gestoppt werden sollen getrennt durch Leerzeichen in der richtigen Reihenfolge eingegeben werden. \
In umgekehrter Reihenfolge werden die Services nach dem Backup wieder gestartet. Weitere Details finden sich auf https://www.linux-tips-and-tricks.de/de/faq#a18."
MSG_FI[$DESCRIPTION_STARTSTOP]="${NL}Tärkeät palvelut tulisi pysäyttää varmuuskopioinnin ajaksi. Lisää pysäytettävät palvelut välilyönnillä erotettuna pysäytysjärjestyksessä. \
Palvelut käynnistetään käänteisessä järjestyksessä varmuuskopioinnin päättyessä. Lisätietoa löydät osoitteesta https://www.linux-tips-and-tricks.de/en/faq#a18."
MSG_FR[$DESCRIPTION_STARTSTOP]="${NL}Avant et après une sauvegarde, tous les services importants doivent toujours être arrêtés et démarrés. Pour ce faire, les services nécessaires qui doivent être arrêtés doivent être saisis dans le bon ordre, séparés par des espaces. \
Les services sont redémarrés dans l'ordre inverse après la sauvegarde. Vous trouverez plus de détails sur https://www.linux-tips-and-tricks.de/de/faq#a18."
MSG_ZH[$DESCRIPTION_STARTSTOP]="${NL}备份前,重要服务会被停止,备份后自动重启服务.按顺序添加需要停止的服务,多个服务用空格分割 \
服务会在备份完成后按反序重启,详情见 https://www.linux-tips-and-tricks.de/en/faq#a18."
DESCRIPTION_STARTSTOP_SEQUENCE=$((SCNT++))
MSG_EN[$DESCRIPTION_STARTSTOP_SEQUENCE]="${NL}Select step by step every service which should be stopped first, second, third and so on and confirm every single service with until there is no service any more. \
Actual sequence is displayed top down. \
For further details see https://www.linux-tips-and-tricks.de/en/faq#a18."
MSG_DE[$DESCRIPTION_STARTSTOP_SEQUENCE]="${NL}Wähle der Reihe nach die Services aus wie sie vor dem Backup gestoppt werden sollen und bestätige jeden einzelnen Service mit bis keine Services mehr angezeigt werden. \
Die aktuelle Reihenfolge wird von oben nach unten angezeigt. \
Weitere Details finden sich auf https://www.linux-tips-and-tricks.de/de/faq#a18."
MSG_FI[$DESCRIPTION_STARTSTOP_SEQUENCE]="${NL}Valitse pysäytettävät palvelut yksi kerrallaan painaen , kunnes listalla ei ole palveluita. \
Toteutuva järjestys näytetään ylhäältä alas. \
${NL}Lisätietoja näet osoitteesta https://www.linux-tips-and-tricks.de/en/faq#a18."
MSG_FR[$DESCRIPTION_STARTSTOP_SEQUENCE]="${NL}Sélectionnez les services les uns après les autres car ils doivent être arrêtés avant la sauvegarde et confirmez chaque service individuel avec jusqu'à ce qu'aucun autre service ne s'affiche. \
L'ordre en cours est affiché de haut en bas. \
Vous trouverez plus de détails sur https://www.linux-tips-and-tricks.de/de/faq#a18."
MSG_ZH[$DESCRIPTION_STARTSTOP_SEQUENCE]="${NL}一个一个的选择需要停止的服务,按确定. \
停止顺序自上而下. \
${NL}详情见 https://www.linux-tips-and-tricks.de/en/faq#a18."
DESCRIPTION_STARTSTOP_SERVICES=$((SCNT++))
MSG_EN[$DESCRIPTION_STARTSTOP_SERVICES]="${NL}Select all services in sequence how they should be stopped before the backup starts. \
Current sequence is displayed.\
They will be started in reverse sequence again when the backup finished."
MSG_DE[$DESCRIPTION_STARTSTOP_SERVICES]="${NL}Wähle alle wichtigen Services aus die vor dem Backup gestoppt werden sollen. \
Sie werden wieder in umgekehrter Reihenfolge gestartet wenn der Backup beendet wurde."
MSG_FI[$DESCRIPTION_STARTSTOP_SERVICES]="${NL}Palvelut pysäytetään ennen varmuuskopiointia siinä järjestyksessä, kun valitset ne. \
Listalla näytetään nykyinen järjestys. \
Palvelut käynnistetään käänteisessä järjestyksessä varmuuskopioinnin päättyessä."
MSG_FR[$DESCRIPTION_STARTSTOP_SERVICES]="${NL}Sélectionnez tous les services importants qui doivent être arrêtés avant la sauvegarde. \
La séquence en cours est affichée. \
Ils sont redémarrés dans l'ordre inverse lorsque la sauvegarde est terminée."
MSG_ZH[$DESCRIPTION_STARTSTOP_SERVICES]="${NL}按顺序选择备份开始前应停止的所有服务. \
当前序列已显示. \
备份完成后会按反序重启."
DESCRIPTION_PARTITIONS=$((SCNT++))
MSG_EN[$DESCRIPTION_PARTITIONS]="${NL}Select all partitions which should be included in the backup. \
${NL}${NL}Note: The first two partitions have to be selected all the time."
MSG_DE[$DESCRIPTION_PARTITIONS]="${NL}Wähle alle Partitionen aus die im Backup enthalten sein sollen. \
${NL}${NL}Hinweis: Die ersten beiden Partitionen müssen immer ausgewählt werden."
MSG_FI[$DESCRIPTION_PARTITIONS]="${NL}Valitse kaikki varmuuskopioitavat osiot. \
${NL}${NL}Huom: Kaksi ensimmäistä osiota tulee olla aina valittuna."
MSG_FR[$DESCRIPTION_PARTITIONS]="${NL}Sélectionnez toutes les partitions qui doivent être incluses dans la sauvegarde. \
${NL}${NL}Remarque : les deux premières partitions doivent toujours être sélectionnées."
MSG_ZH[$DESCRIPTION_PARTITIONS]="${NL}选择所有需要备份的分区. \
${NL}${NL}注意:前两个分区总会默认被选中."
DESCRIPTION_LANGUAGE=$((SCNT++))
MSG_EN[$DESCRIPTION_LANGUAGE]="${NL}$RASPIBACKUP_NAME and this installer support following languages as of now. Default language is the system language.\
${NL}${NL}Any help to add another language is welcome."
MSG_DE[$DESCRIPTION_LANGUAGE]="${NL}$RASPIBACKUP_NAME und dieser Installer unterstützen momentan folgende Sprachen. Standardsprache ist die Systemsprache.\
${NL}${NL}Jede Hilfe eine weitere Sprache dazuzubringen ist herzlich willkommen."
MSG_FI[$DESCRIPTION_LANGUAGE]="${NL}$RASPIBACKUP_NAME ja tämä asennustyökalu tukevat tällä hetkellä ${NL}alla lueteltuja kieliä. Oletuksena on järjestelmän kieli.\
${NL}${NL}Apu muiden kielien lisäämiseen on tervetullut."
MSG_FR[$DESCRIPTION_LANGUAGE]="${NL}$RASPIBACKUP_NAME et ce programme d'installation prend actuellement en charge les langues suivantes. La langue du système est la langue standard.\
${NL}${NL}Toute aide pour ajouter une autre langue est la bienvenue."
MSG_ZH[$DESCRIPTION_LANGUAGE]="${NL}$RASPIBACKUP_NAME 目前支持下列语言,默认使用系统语言.\
${NL}${NL}欢迎翻译其他语言!."
DESCRIPTION_KEEP=$((SCNT++))
MSG_EN[$DESCRIPTION_KEEP]="${NL}Enter number of backups to keep. Number hast to be between 1 and 52."
MSG_DE[$DESCRIPTION_KEEP]="${NL}Gib die Anzahl der Beackups die vorzuhalten sind. Die Zahl muss zwischen 1 und 52 liegen."
MSG_FI[$DESCRIPTION_KEEP]="${NL}Syötä säilytettävien varmuuskopioiden lukumäärä. Numeron tulee olla 1:n ja 52:n väliltä."
MSG_FR[$DESCRIPTION_KEEP]="${NL}Entrez le nombre de sauvegardes à conserver. Le nombre doit être compris entre 1 et 52."
MSG_ZH[$DESCRIPTION_KEEP]="${NL}输入保存的备份数,在1和52之间."
DESCRIPTION_SMART=$((SCNT++))
MSG_EN[$DESCRIPTION_SMART]="${NL}Enter four numbers separated by spaces to define the smart recycle backup strategy parameters. The numbers define how many daily, weekly, monthly and yearly backups are kept. \
For details about the backup strategy see https://www.linux-tips-and-tricks.de/en/smart-recycle/."
MSG_DE[$DESCRIPTION_SMART]="${NL}Gib mit vier durch Leerzeichen getrennten Zahlen die Parameter für die intelligente Rotationsstrategie ein. Die Zahlen definieren wie viele tägliche, wöchentliche, monatliche und jährliche Backups vorgehalten werden. \
Details zur Backupstrategie können auf https://www.linux-tips-and-tricks.de/de/rotationsstrategie/ nachgelesen werden."
MSG_FI[$DESCRIPTION_SMART]="${NL}Syötä neljä välilyönnein erotettua numeroa määrittääksesi älykkään varmuuskopioinnin parametrit. Numerot määrittävät kuinka monta päivittäistä, viikoittaista, kuukausittaista ja vuosittaista varmuuskopiota säilytetään. \
Lisätietoa löydät osoitteesta https://www.linux-tips-and-tricks.de/en/smart-recycle/."
MSG_FR[$DESCRIPTION_SMART]="${NL}Saisissez les paramètres de la stratégie intelligente avec quatre nombres séparés par des espaces. Les nombres définissent combien de sauvegardes quotidiennes, hebdomadaires, mensuelles et annuelles sont conservées. \
Des détails sur la stratégie de sauvegarde sont disponibles sur https://www.linux-tips-and-tricks.de/de/rotationsstrategy/."
MSG_ZH[$DESCRIPTION_SMART]="${NL}输入四个数字定义备份策略. 这决定备份周期. \
详情见 https://www.linux-tips-and-tricks.de/en/smart-recycle/."
DESCRIPTION_ERROR=$((SCNT++))
MSG_EN[$DESCRIPTION_ERROR]="Unrecoverable error occurred. Check logfile $LOG_FILE."
MSG_DE[$DESCRIPTION_ERROR]="Ein nicht behebbarer Fehler ist aufgetreten. Siehe Logdatei $LOG_FILE."
MSG_FI[$DESCRIPTION_ERROR]="Tapahtui peruuttamaton virhe. Tarkista lokitiedosto $LOG_FILE."
MSG_FR[$DESCRIPTION_ERROR]="Une erreur irrécupérable s'est produite. Voir le fichier journal $LOG_FILE."
MSG_ZH[$DESCRIPTION_ERROR]="发生了无法恢复的错误。检查日志文件$LOG_FILE."
DESCRIPTION_BACKUPPATH=$((SCNT++))
MSG_EN[$DESCRIPTION_BACKUPPATH]="${NL}On the backup path a partition has to be be mounted which is used by $FILE_TO_INSTALL to store the backups. \
This can be a local partition or a mounted remote partition."
MSG_DE[$DESCRIPTION_BACKUPPATH]="${NL}Am Backuppfad muss eine Partition gemounted sein auf welcher $FILE_TO_INSTALL die Backups ablegt. \
Das kann eine lokale Partition oder eine remote gemountete Partition."
MSG_FI[$DESCRIPTION_BACKUPPATH]="${NL}Sijainti, johon $FILE_TO_INSTALL:n varmuuskopiot tallennetaan, tulee olla otettuna käyttöön. \
Sijainti voi olla otettu käyttöön joko paikallisesti tai etänä."
MSG_FR[$DESCRIPTION_BACKUPPATH]="${NL}Vous devez indiquer le chemin de sauvegarde: la partition utilisée $FILE_TO_INSTALL doit être montée. \
Cela peut être une partition locale ou une partition distante(ex:samba)."
MSG_ZH[$DESCRIPTION_BACKUPPATH]="${NL}在备份路径必须挂载一个分区,用来为$FILE_TO_INSTALL存储备份文件. \
可以是本地磁盘或者云端磁盘."
DESCRIPTION_BACKUPMODE=$((SCNT++))
MSG_EN[$DESCRIPTION_BACKUPMODE]="${NL}Preferred mode is the normal backup mode. If you need to save more than two partitions with tar or rsync use the partition oriented mode. \
Use normal mode and dd backup if you need a dd backup. Default is to backup the first two partitions only but it's possible to add any additional partition."
MSG_DE[$DESCRIPTION_BACKUPMODE]="${NL}Empfohlener Modus ist der normale Backup Modus. Wenn allerdings mehr als zwei Partitionen gesichert werden sollen mit tar oder rsync ist der paritionsorientiert Modus zu wählen. \
Den normalen Modus muss man aber wählen wenn man ein dd Backup haben möchte. Standard ist nur die ersten beiden Partitionen zu sichern aber es kann jede weitere Partition dazugefügt werden."
MSG_FI[$DESCRIPTION_BACKUPMODE]="${NL}Oletuksena on suositeltu normaali varmuuskopiointitila, jolloin kaksi ensimmäistä osiota varmuuskopioidaan. Jos haluat varmuuskopioida useamman kuin kaksi osiota käyttäen tar:ia tai rsync:iä, käytä jälkimmäistä, osio-orientoitua tilaa. \
Käytä normaalia tilaa ja dd-varmuuskopiointia, jos haluat dd-varmuuskopion."
MSG_FR[$DESCRIPTION_BACKUPMODE]="${NL}Le mode recommandé est le mode de sauvegarde normal. Cependant, si plus de deux partitions doivent être sauvegardées avec tar ou rsync, le mode orienté partition doit être sélectionné. \
Vous devez choisir le mode normal si vous souhaitez une sauvegarde dd. La norme est de ne sauvegarder que les deux premières partitions, mais toute partition supplémentaire peut être ajoutée."
MSG_ZH[$DESCRIPTION_BACKUPMODE]="${NL}预设的是常规备份模式, 若想用tar 或rsync备份2个以上分区,请选择分区导向模式. \
默认只备份前两个分区,但是其他分区也可以自定义."
DESCRIPTION_BACKUPTYPE=$((SCNT++))
MSG_EN[$DESCRIPTION_BACKUPTYPE]="${NL}rsync is the suggested backuptype because when using hardlinks from EXT3/4 filesystem it's fast because only changed or new files will be saved. \
tar should be used if the backup filesystem is no EXT3/4, e.g a remote mounted samba share. Don't use a FAT32 filesystem because the maximum filesize is 4GB. \
dd should be used if you want to restore the backup on a Windows OS. \
dd and tar backups can be compressed. \
For further details about backup type see${NL}https://www.linux-tips-and-tricks.de/en/backup#butypes. \
For further details about the option for dd see${NL}https://www.linux-tips-and-tricks.de/en/faq#a16"
MSG_DE[$DESCRIPTION_BACKUPTYPE]="${NL}rsync ist der empfohlene Backuptyp da durch Hardlinks vom ETX3/4 Dateisystem der Backup schnell ist da nur neue oder geänderte Dateien gesichert werden. \
tar sollte man benutzen wenn das Backupdateisystem kein EXT3/4 ist, z.B. ein remotes Samba Laufwerk. Ein FAT32 Dateisystem ist ungeeignet da die maximale Dateigröße nur 4GB ist. \
dd ist die richtige Wahl wenn man den Backup auf einem Windows OS wiederherstellen will. \
dd und tar Backups können noch zusätzlich komprimiert werden. \
Weiter Details zum Backuptyp finden sich${NL}https://www.linux-tips-and-tricks.de/de/raspibackup#vornach. \
Weitere Details zu der Option für dd siehe${NL}https://www.linux-tips-and-tricks.de/de/faq#a16"
MSG_FI[$DESCRIPTION_BACKUPTYPE]="${NL}EXT3/4-tiedostojärjetelmässä on suositeltavaa valita rsync, sillä hardlinkit nopeuttavat varmuuskopiointia: vain uudet ja muuttuneet tiedostot kopioidaan. \
Valitse tar, jos varmuuskopioitava tiedostojärjestelmä ei ole EXT3/4 tai se on esim. etänä käyttöönotettu samba-jako. Älä käytä FAT32-tiedostojärjestelmää, koska sen maksimitiedostokoko on 4Gt. \
Valitse dd, jos haluat palauttaa varmuuskopion Windows-järjestelmässä. dd- ja tar-varmuuskopiot voidaan pakata tilan säästämiseksi. \
${NL}${NL}Lisätietoja varmuuskopiotyypeistä löydät osoitteestahttps://www.linux-tips-and-tricks.de/en/backup#butypes. \
${NL}Lisätietoja dd:n valinnoista löydät osoitteesta https://www.linux-tips-and-tricks.de/en/faq#a16"
MSG_FR[$DESCRIPTION_BACKUPTYPE]="${NL}rsync est le type de sauvegarde recommandé car le système de fichiers ETX3/4 rend la sauvegarde rapide, seuls les fichiers nouveaux ou modifiés sont enregistrés. \
tar doit être utilisé si le système de fichiers de sauvegarde n'est pas un EXT3/4, par exemple un lecteur Samba distant. Un système de fichiers FAT32 ne convient pas car la taille maximale du fichier n'est que de 4 Go. \
dd est le bon choix si vous souhaitez restaurer la sauvegarde sur un système d'exploitation Windows. \
les sauvegardes dd et tar peuvent également être compressées. \
Vous trouverez plus de détails sur le type de sauvegarde sur${NL}https://www.linux-tips-and-tricks.de/de/raspibackup#vornach. \
Pour dd voir : ${NL}https://www.linux-tips-and-tricks.de/de/faq#a16 "
MSG_ZH[$DESCRIPTION_BACKUPTYPE]="${NL}rsync是建议的备份方法.因为ETX3/4文件系统的硬链接只有在改变时才会被保存\
建议tar在非EXT3/4文件系统上使用,比如云端samba设备 \
建议dd模式在有在windows系统上恢复备份需求时使用. \
dd和tar模式下生成的备份可以被压缩. \
${NL}${NL}更多备份模式类型见:https://www.linux-tips-and-tricks.de/en/backup#butypes. \
${NL}更多dd模式详情见 https://www.linux-tips-and-tricks.de/en/faq#a16"
DESCRIPTION_MAIL_PROGRAM=$((SCNT++))
MSG_EN[$DESCRIPTION_MAIL_PROGRAM]="Select the mail program to use to send notification eMails."
MSG_DE[$DESCRIPTION_MAIL_PROGRAM]="Wähle das Mailprogramm aus welches zum Versenden von Benachrichtigungen benutzt werden soll."
MSG_FI[$DESCRIPTION_MAIL_PROGRAM]="Valitse sähköpostisovellus ilmoitussähköpostien lähettämiseen."
MSG_FR[$DESCRIPTION_MAIL_PROGRAM]="Sélectionnez le programme de messagerie qui doit être utilisé pour envoyer des notifications."
MSG_ZH[$DESCRIPTION_MAIL_PROGRAM]="选择发送邮件的程序."
DESCRIPTION_EMAIL=$((SCNT++))
MSG_EN[$DESCRIPTION_EMAIL]="Enter the eMail address to send notifications to. Enter no eMail address to disable notifications."
MSG_DE[$DESCRIPTION_EMAIL]="Gibt die eMail Adresse ein die Benachrichtigungen erhalten soll. Keine eMail Adresse schaltet Benachrichtigungen aus."
MSG_FI[$DESCRIPTION_EMAIL]="Syötä sähköpostiosoite, johon ilmoitukset lähetetään. Jos et halua ilmoituksia, älä syötä lainkaan sähköpostiosoitetta."
MSG_FR[$DESCRIPTION_EMAIL]="Saisissez l'adresse e-mail pour recevoir les notifications. Aucune adresse e-mail désactive les notifications."
MSG_ZH[$DESCRIPTION_EMAIL]="输入邮件地址,留空则禁用邮件通知."
TITLE_ERROR=$((SCNT++))
MSG_EN[$TITLE_ERROR]="Error"
MSG_DE[$TITLE_ERROR]="Fehler"
MSG_FI[$TITLE_ERROR]="Virhe"
MSG_FR[$TITLE_ERROR]="Erreur"
MSG_ZH[$TITLE_ERROR]="错误"
TITLE_FIRST_STEPS=$((SCNT++))
MSG_EN[$TITLE_FIRST_STEPS]="First steps"
MSG_DE[$TITLE_FIRST_STEPS]="Erste Schritte"
MSG_FI[$TITLE_FIRST_STEPS]="Ensiaskeleet"
MSG_FR[$TITLE_FIRST_STEPS]="En premier"
MSG_ZH[$TITLE_FIRST_STEPS]="第一步"
TITLE_HELP=$((SCNT++))
MSG_EN[$TITLE_HELP]="Help"
MSG_DE[$TITLE_HELP]="Hilfe"
MSG_FI[$TITLE_HELP]="Ohje"
MSG_FR[$TITLE_HELP]="Aide"
MSG_ZH[$TITLE_HELP]="帮助"
TITLE_WARNING=$((SCNT++))
MSG_EN[$TITLE_WARNING]="Warning"
MSG_DE[$TITLE_WARNING]="Warnung"
MSG_FI[$TITLE_WARNING]="Varoitus"
MSG_FR[$TITLE_WARNING]="Attention"
MSG_ZH[$TITLE_WARNING]="警告"
TITLE_INFORMATION=$((SCNT++))
MSG_EN[$TITLE_INFORMATION]="Information"
MSG_DE[$TITLE_INFORMATION]="Information"
MSG_FI[$TITLE_INFORMATION]="Tietoa"
MSG_FR[$TITLE_INFORMATION]="Information"
MSG_ZH[$TITLE_INFORMATION]="信息"
TITLE_VALIDATIONERROR=$((SCNT++))
MSG_EN[$TITLE_VALIDATIONERROR]="Invalid input"
MSG_DE[$TITLE_VALIDATIONERROR]="Ungültige Eingabe"
MSG_FI[$TITLE_VALIDATIONERROR]="Virheellinen syöte"
MSG_FR[$TITLE_VALIDATIONERROR]="Entrée invalide"
MSG_ZH[$TITLE_VALIDATIONERROR]="无效输入"
TITLE_CONFIRM=$((SCNT++))
MSG_EN[$TITLE_CONFIRM]="Please confirm"
MSG_DE[$TITLE_CONFIRM]="Bitte bestätigen"
MSG_FI[$TITLE_CONFIRM]="Ole hyvä ja varmista"
MSG_FR[$TITLE_CONFIRM]="SVP Confirmez"
MSG_ZH[$TITLE_CONFIRM]="请确认"
MSG_INVALID_BACKUPPATH=$((SCNT++))
MSG_EN[$MSG_INVALID_BACKUPPATH]="Backup path %1 does not exist"
MSG_DE[$MSG_INVALID_BACKUPPATH]="Sicherungsverzeichnis %1 existiert nicht"
MSG_FI[$MSG_INVALID_BACKUPPATH]="Polkua %1 ei ole"
MSG_FR[$MSG_INVALID_BACKUPPATH]="Le répertoire de sauvegarde %1 n'existe pas"
MSG_ZH[$MSG_INVALID_BACKUPPATH]="备份路径 %1 不存在"
MSG_INVALID_EMAIL=$((SCNT++))
MSG_EN[$MSG_INVALID_EMAIL]="Invalid eMail address %1"
MSG_DE[$MSG_INVALID_EMAIL]="Ungültige eMail Adresse %1"
MSG_FI[$MSG_INVALID_EMAIL]="Virheellinen sähköpostiosoite %1"
MSG_FR[$MSG_INVALID_EMAIL]="Adresse e-mail invalide %1"
MSG_ZH[$MSG_INVALID_EMAIL]="邮箱地址无效 %1"
MSG_LOCAL_BACKUPPATH=$((SCNT++))
MSG_EN[$MSG_LOCAL_BACKUPPATH]="Backup would be stored on SD card"
MSG_DE[$MSG_LOCAL_BACKUPPATH]="Backup würde auf der SD Karte gespeichert werden"
MSG_FI[$MSG_LOCAL_BACKUPPATH]="Varmuuskopio säilytetään SD-kortilla"
MSG_FR[$MSG_LOCAL_BACKUPPATH]="La sauvegarde sera enregistrée sur la carte SD"
MSG_ZH[$MSG_LOCAL_BACKUPPATH]="备份文件将被存储在SD卡"
MSG_NAVIGATION=$((SCNT++))
MSG_EN[$MSG_NAVIGATION]="Cursor keys: Move cursor to next menu item, list item or button${NL}\
Space key: Select/unselect items in a selection list${NL}\
Tab key: Jump to buttons at the bottom${NL}\
${NL}\
Pfeiltasten: Bewege Schreibmarke zum nächsten Menueintrag, Listeneintrag oder Auswahlknopf${NL}\
Leertaste: Selektiere/Deselektieren Einträge in einer Auswahliste${NL}\
Tab Taste: Springe zu den unteren Auswahlknöpfen"
MSG_DE[$MSG_NAVIGATION]="Pfeiltasten: Bewege Schreibmarke zum nächsten Menueintrag, Listeneintrag oder Auswahlknopf${NL}\
Leertaste: Selektiere/Deselektieren Einträge in einer Auswahliste${NL}\
Tab Taste: Springe zu den unteren Auswahlknöpfen${NL}\
${NL}\
Cursor keys: Move cursor to next menu or list item${NL}\
Space key: Select/unselect items in a selection list${NL}\
Tab key: Jump to buttons at the bottom"
MSG_FI[$MSG_NAVIGATION]="Nuolinäppäimet: Siirrä kursori seuraavaan valikon tai listan kohteeseen${NL}\
Välilyönti: Valitse/poista valinta${NL}\
Sarkain: Kohdista alarivin painikkeisiin${NL}\
${NL}\
Cursor keys: Move cursor to next menu or list item${NL}\
Space key: Select/unselect items in a selection list${NL}\
Tab key: Jump to buttons at the bottom"
MSG_FR[$MSG_NAVIGATION]="Les flèches du clavier, déplacent le curseur du menu, des listes ou du bouton de sélection ${NL}\
Barre d'espace : pour sélectionner/désélectionner des entrées dans une liste ${NL}\
Touche de tabulation : pour accéder aux boutons de sélection du bas ${NL}\
${NL}\
Curseur : déplacez le curseur vers le menu ou un élément d'une liste ${NL}\
Touche d'espace : pour sélectionner/désélectionner des éléments dans une liste"
MSG_ZH[$MSG_NAVIGATION]="箭头方向键:上下移动菜单选项、列表选项或者按钮${NL}\
空格键: 选中或取消勾选${NL}\
Tab: 跳至菜单底部按钮${NL}\
${NL}\
Cursor keys: Move cursor to next menu or list item${NL}\
Space key: Select/unselect items in a selection list${NL}\
Tab key: Jump to buttons at the bottom"
MSG_ABOUT=$((SCNT++))
MSG_EN[$MSG_ABOUT]="$GIT_CODEVERSION${NL}\
%1${NL}${NL}\
This tool provides a straight-forward way of doing installation,${NL} updating and configuration of $RASPIBACKUP_NAME.${NL}${NL}\
Visit https://www.linux-tips-and-tricks.de/en/raspibackup#parameters${NL}for details about all configuration options of $RASPIBACKUP_NAME.${NL}${NL}\
Visit https://www.linux-tips-and-tricks.de/en/raspibackup${NL}for details about $RASPIBACKUP_NAME."
MSG_DE[$MSG_ABOUT]="$GIT_CODEVERSION${NL}\
%1${NL}${NL}\
Dieses Tool ermöglicht es möglichst einfach $RASPIBACKUP_NAME zu installieren,${NL} zu updaten und die Konfiguration anzupassen.${NL}${NL}\
Besuche https://www.linux-tips-and-tricks.de/de/raspibackup#parameter${NL}um alle Konfigurationsoptionen von $RASPIBACKUP_NAME kennenzulernen.${NL}${NL}\
Besuche https://www.linux-tips-and-tricks.de/de/raspibackup${NL}um Weiteres zu $RASPIBACKUP_NAME zu erfahren."
MSG_FI[$MSG_ABOUT]="$GIT_CODEVERSION${NL}\
%1${NL}${NL}\
Tämä työkalu tarjoaa $RASPIBACKUP_NAME:n suoraviivaisen asennuksen,${NL} päivittämisen ja asetusten määrittämisen.${NL}${NL}\
Kaikista $RASPIBACKUP_NAME:n asetuksista löydät tietoa osoitteesta${NL}https://www.linux-tips-and-tricks.de/en/raspibackup#parameters${NL}${NL}\
Löydät lisätietoa $RASPIBACKUP_NAME:sta osoitteesta${NL}https://www.linux-tips-and-tricks.de/en/raspibackup"
MSG_FR[$MSG_ABOUT]="$GIT_CODEVERSION${NL}\
%1${NL}${NL}\
Cet outil facilite au maximum la mise en place de $RASPIBACKUP_NAME ,la mise à jour ,${NL} et la configuration.${NL}${NL}\
Visitez https://www.linux-tips-and-tricks.de/en/raspibackup#parameters${NL}pour plus de détails sur toutes les options de configuration de $RASPIBACKUP_NAME.${NL}${NL}\
Visitez https://www.linux-tips-and-tricks.de/en/raspibackup${NL}pour plus de détails sur $RASPIBACKUP_NAME."
MSG_ZH[$MSG_ABOUT]="$GIT_CODEVERSION${NL}\
%1${NL}${NL}\
此界面提供一个$RASPIBACKUP_NAME的安装引导,${NL}更新和设置页面.${NL}${NL}\
$RASPIBACKUP_NAME的的详情设置请访问${NL}https://www.linux-tips-and-tricks.de/en/raspibackup#parameters${NL}${NL}\
获取$RASPIBACKUP_NAME详情请访问:{NL}https://www.linux-tips-and-tricks.de/en/raspibackup "
MSG_FIRST_STEPS=$((SCNT++))
MSG_EN[$MSG_FIRST_STEPS]="Congratulations! $RASPIBACKUP_NAME installed successfully.${NL}${NL}\
Next steps:${NL}
1) Start $RASPIBACKUP_NAME in the commandline and create a backup${NL}\
2) Start $RASPIBACKUP_NAME to restore the backup on a different SD card${NL}\
3) Verify the restored backup works fine.${NL}\
4) Read the FAQ page https://www.linux-tips-and-tricks.de/en/faq${NL}\
5) Visit the options page and fine tune $RASPIBACKUP_NAME${NL}\
https://www.linux-tips-and-tricks.de/en/raspibackup#parameters${NL}\
6) Enable regular backup with the installer${NL}\
7) Visit https://www.linux-tips-and-tricks.de/en/backup for a lot more information about $RASPIBACKUP_NAME"
MSG_DE[$MSG_FIRST_STEPS]="Herzlichen Glückwunsch! $RASPIBACKUP_NAME wurde erfolgreich installiert.${NL}${NL}\
Nächsten Schritte:${NL}
1) Starte $RASPIBACKUP_NAME in der Befehlszeile und erzeuge ein Backup${NL}\
2) Starte $RASPIBACKUP_NAME um das erzeugte Backup auf einer andere SD Karte wiederherzustellen.${NL}\
3) Verifiziere dass das System ohne Probleme läuft.${NL}\
4) Lies die FAQ Seite https://www.linux-tips-and-tricks.de/de/faq${NL}\
5) Besuche die Optionsseite und konfiguriere $RASPIBACKUP_NAME genau nach Deinen Vorstellungen${NL}\
https://www.linux-tips-and-tricks.de/de/raspibackup#parameters${NL}\
6) Schalte den regelmäßigen Backup mit dem Installer ein${NL}\
7) Besuche https://www.linux-tips-and-tricks.de/en/backup um noch wesentlich detailiertere Informationen zu $RASPIBACKUP_NAME zu erhalten"
MSG_FI[$MSG_FIRST_STEPS]="Onnittelut! $RASPIBACKUP_NAME on asennettu onnistuneesti.${NL}${NL}\
Seuraavat vaiheet:${NL}
1) Käynnistä $RASPIBACKUP_NAME komentoriviltä ja luo varmuuskopio${NL}\
2) Käynnistä $RASPIBACKUP_NAME palauttaaksesi varmuuskopion toiselle SD-kortille${NL}\
3) Varmista, että palautettu varmuuskopio toimii oikein.${NL}\
4) Lue FAQ-sivu osoitteessa https://www.linux-tips-and-tricks.de/en/faq${NL}\
5) Käy valintasivulla ja tee $RASPIBACKUP_NAME$-hienosäädöt{NL}\
https://www.linux-tips-and-tricks.de/en/raspibackup#parameters${NL}\
6) Ota käyttöön säännölliset varmuuskopiot asennusohjelmalla${NL}\
7) Käy osoitteessa https://www.linux-tips-and-tricks.de/en/backup ja lue paljon lisää $RASPIBACKUP_NAME-tietoa"
MSG_FR[$MSG_FIRST_STEPS]="Toutes nos félicitations! $RASPIBACKUP_NAME est installé avec succès.${NL}${NL}\
Prochaines étapes :${NL}
1) Démarrez $RASPIBACKUP_NAME dans la ligne de commande et créez une sauvegarde${NL}\
2) Démarrez $RASPIBACKUP_NAME pour restaurer la sauvegarde sur une autre carte SD${NL}\
3) Vérifiez que la sauvegarde restaurée fonctionne correctement.${NL}\
4) Lisez la page FAQ https://www.linux-tips-and-tricks.de/en/faq${NL}\
5) Visitez la page des options et améliorez $RASPIBACKUP_NAME${NL}\
https://www.linux-tips-and-tricks.de/en/raspibackup#parameters${NL}\
6) Activez la sauvegarde régulière avec le programme raspiBackupInstallUI.sh${NL}\
7) Visitez https://www.linux-tips-and-tricks.de/en/backup pour avoir des informations sur $RASPIBACKUP_NAME"
MSG_ZH[$MSG_FIRST_STEPS]="恭喜! $RASPIBACKUP_NAME 安装成功.${NL}${NL}\
接下来你可以:${NL}
1) 在终端输入 $RASPIBACKUP_NAME开始备份 ${NL}\
2) 在终端输入 $RASPIBACKUP_NAME 还原备份到SD卡${NL}\
3) 校验备份文件.${NL}\
4) 参考FAQ页面 https://www.linux-tips-and-tricks.de/en/faq${NL}\
5) 进行设置和微调项 $RASPIBACKUP_NAME${NL}\
https://www.linux-tips-and-tricks.de/en/raspibackup#parameters${NL}\
6) 开启定期备份${NL}\
7) 访问https://www.linux-tips-and-tricks.de/en/backup 获取更多$RASPIBACKUP_NAME信息"
MSG_HELP=$((SCNT++))
MSG_EN[$MSG_HELP]="In case you have any issue or question about $RASPIBACKUP_NAME just use one of the following paths to get help${NL}
1) Read the FAQ page https://www.linux-tips-and-tricks.de/en/faq${NL}\
2) Visit https://www.linux-tips-and-tricks.de/en/backup for a lot more information about $RASPIBACKUP_NAME${NL}\
3) Create an issue on github https://github.com/framps/raspiBackup/issues. That's my preference${NL}\
4) Add comments on any webpage dealing with $RASPIBACKUP_NAME on $MYHOMEDOMAIN${NL}\
5) Visit $RASPIBACKUP_NAME on Facebook"
MSG_DE[$MSG_HELP]="Falls es irgendwelche Fragen oder Probleme zu $RASPIBACKUP_NAME gibt bestehen folgende Möglichkeiten Hilfe zu bekommen${NL}
1) Lies die FAQ Seite https://www.linux-tips-and-tricks.de/de/faq${NL}\
2) Besuche https://www.linux-tips-and-tricks.de/en/backup um noch wesentlich detailiertere Informationen zu $RASPIBACKUP_NAME zu erhalten${NL}\
3) Erstelle einen Fehlerbericht auf github https://github.com/framps/raspiBackup/issues. Gerne auch in Deutsch. Das ist meine Präferenz.${NL} \
4) Erstelle einen Kommentar auf jeder Webseite zu $RASPIBACKUP_NAME auf $MYHOMEDOMAIN${NL}\
5) Besuche $RASPIBACKUP_NAME auf Facebook"
MSG_FI[$MSG_HELP]="Jos sinulla on kysymyksiä tai ongelmia $RASPIBACKUP_NAME:n kanssa, käytä jotain seuraavista tavoista saadaksesi apua${NL}
1) Lue FAQ-sivu osoitteessa https://www.linux-tips-and-tricks.de/en/faq${NL}\
2) Käy osoitteessa https://www.linux-tips-and-tricks.de/en/backup ja lue paljon lisää $RASPIBACKUP_NAME-tietoa${NL}\
3) Luo issue githubissa https://github.com/framps/raspiBackup/issues. Tätä suosin.${NL}\
4) Lisää kommentti $RASPIBACKUP_NAME-verkkosivuilla osoitteessa $MYHOMEDOMAIN${NL}\
5) Käy $RASPIBACKUP_NAME:n Facebook-sivulla"
MSG_FR[$MSG_HELP]="Si vous avez un problème ou une question concernant $RASPIBACKUP_NAME, utilisez simplement un des liens suivants pour obtenir une aide :${NL}
1) Lisez la page FAQ https://www.linux-tips-and-tricks.de/en/faq${NL}\
2) Visitez https://www.linux-tips-and-tricks.de/en/backup pour plus d'informations sur $RASPIBACKUP_NAME${NL}\
3) Exposez le problème sur github https://github.com/framps/raspiBackup/issues. C'est ma préférence${NL}\
4) Ajoutez des commentaires sur toute page Web traitant de $RASPIBACKUP_NAME sur $MYHOMEDOMAIN${NL}\
5) Visitez $RASPIBACKUP_NAME sur Facebook"
MSG_ZH[$MSG_HELP]="如果你有任何关于 $RASPIBACKUP_NAME 的问题,请用以下方式联系${NL}
1) 参考FAQ页面 https://www.linux-tips-and-tricks.de/en/faq${NL}\
2) 访问 https://www.linux-tips-and-tricks.de/en/backup 获取更多$RASPIBACKUP_NAME$信息{NL}\
3) 在github上创建issues https://github.com/framps/raspiBackup/issues. 通常选这项!${NL}\
4) 在 $MYHOMEDOMAIN$上关于$RASPIBACKUP_NAME的页面留言评论{NL}\
5) 访问$RASPIBACKUP_NAME 的Facebook页面"
MSG_FIRST_PARTITIONS_NOT_SELECTED=$((SCNT++))
MSG_EN[$MSG_FIRST_PARTITIONS_NOT_SELECTED]="At least the first two partitions have to be selected."
MSG_DE[$MSG_FIRST_PARTITIONS_NOT_SELECTED]="Wenigstens die beiden ersten Partitionen müssen ausgewählt sein."
MSG_SENSITIVE_WARNING=$((SCNT++))
MSG_EN[$MSG_SENSITIVE_WARNING]="| ===> A lot of sensitive information is masqueraded in this log file. Nevertheless please check the log carefully before you distribute it <=== |"
MSG_DE[$MSG_SENSITIVE_WARNING]="| ===> Viele sensitive Informationen werden in dieser Logdatei maskiert. Vor dem Verteilen des Logs sollte es trotzdem ueberprueft werden <=== |"
MSG_FI[$MSG_SENSITIVE_WARNING]="| ===> Sensitiivisiä tietoja on piilotettu tästä lokitiedostosta. Tarkista lisäksi loki huolellisesti ennen sen jakoa <=== |"
MSG_FR[$MSG_SENSITIVE_WARNING]="| ===>De nombreuses informations sensibles sont masquées dans ce fichier journal. Avant de distribuer le log, il faut quand même le vérifier<=== |"
MSG_SENSITIVE_SEPARATOR=$((SCNT++))
MSG_EN[$MSG_SENSITIVE_SEPARATOR]="+================================================================================================================================================+"
declare -A MENU_EN
declare -A MENU_DE
declare -A MENU_FI
declare -A MENU_FR
declare -A MENU_ZH
MCNT=0
MENU_UNDEFINED=$((MCNT++))
MENU_EN[$MENU_UNDEFINED]="Undefined menuid."
MENU_DE[$MENU_UNDEFINED]="Unbekannte menuid."
MENU_FI[$MENU_UNDEFINED]="Määrittämätön valikon id."
MENU_FR[$MENU_UNDEFINED]="Id du menu inconnu."
MENU_ZH[$MENU_UNDEFINED]="未定义的菜单id."
MENU_LANGUAGE=$((MCNT++))
MENU_EN[$MENU_LANGUAGE]='"M1" "Language"'
MENU_DE[$MENU_LANGUAGE]='"M1" "Sprache"'
MENU_FI[$MENU_LANGUAGE]='"M1" "Kieli"'
MENU_FR[$MENU_LANGUAGE]='"M1" "Choisir la langue"'
MENU_ZH[$MENU_LANGUAGE]='"M1" "语言"'
MENU_INSTALL=$((MCNT++))
MENU_EN[$MENU_INSTALL]='"M2" "Install components"'
MENU_DE[$MENU_INSTALL]='"M2" "Installiere Komponenten"'
MENU_FI[$MENU_INSTALL]='"M2" "Asenna komponentteja"'
MENU_FR[$MENU_INSTALL]='"M2" "Installation des composants"'
MENU_ZH[$MENU_INSTALL]='"M2" "安装组件"'
MENU_CONFIGURE=$((MCNT++))
MENU_EN[$MENU_CONFIGURE]='"M3" "Configure major options"'
MENU_DE[$MENU_CONFIGURE]='"M3" "Konfiguriere die wichtigsten Optionen"'
MENU_FI[$MENU_CONFIGURE]='"M3" "Määritä pääasetukset"'
MENU_FR[$MENU_CONFIGURE]='"M3" "Configurer les options importantes"'
MENU_ZH[$MENU_CONFIGURE]='"M3" "设置主要选项"'
MENU_UNINSTALL=$((MCNT++))
MENU_EN[$MENU_UNINSTALL]='"M4" "Delete components"'
MENU_DE[$MENU_UNINSTALL]='"M4" "Lösche Komponenten"'
MENU_FI[$MENU_UNINSTALL]='"M4" "Poista komponentteja"'
MENU_FR[$MENU_UNINSTALL]='"M4" "Supprimer des composants"'
MENU_ZH[$MENU_UNINSTALL]='"M4" "删除组件"'
MENU_UPDATE=$((MCNT++))
MENU_EN[$MENU_UPDATE]='"M5" "Update components"'
MENU_DE[$MENU_UPDATE]='"M5" "Aktualisiere Komponenten"'
MENU_FI[$MENU_UPDATE]='"M5" "Päivitä komponentteja"'
MENU_FR[$MENU_UPDATE]='"M5" "Mettre à jour des composants"'
MENU_ZH[$MENU_UPDATE]='"M5" "更新组件"'
MENU_ABOUT=$((MCNT++))
MENU_EN[$MENU_ABOUT]='"M9" "About and useful links"'
MENU_DE[$MENU_ABOUT]='"M9" "About und hilfreiche Links"'
MENU_FI[$MENU_ABOUT]='"M9" "Tietoja ja hyödyllisiä linkkejä"'
MENU_FR[$MENU_ABOUT]='"M9" "A propos et liens utiles"'
MENU_ZH[$MENU_ABOUT]='"M9" "关于&链接"'
MENU_REGULARBACKUP_ENABLE=$((MCNT++))
MENU_EN[$MENU_REGULARBACKUP_ENABLE]='"R1" "Enable regular backup"'
MENU_DE[$MENU_REGULARBACKUP_ENABLE]='"R1" "Regelmäßiges Backup einschalten"'
MENU_FI[$MENU_REGULARBACKUP_ENABLE]='"R1" "Ota käyttöön säännöllinen varmuuskopiointi"'
MENU_FR[$MENU_REGULARBACKUP_ENABLE]='"R1" "Activer une sauvegarde régulière"'
MENU_ZH[$MENU_REGULARBACKUP_ENABLE]='"R1" "开启定期备份"'
MENU_REGULARBACKUP_DISABLE=$((MCNT++))
MENU_EN[$MENU_REGULARBACKUP_DISABLE]='"R1" "Disable regular backup"'
MENU_DE[$MENU_REGULARBACKUP_DISABLE]='"R1" "Regelmäßiges Backup auschalten"'
MENU_FI[$MENU_REGULARBACKUP_DISABLE]='"R1" "Poista säännöllinen varmuuskopiointi käytöstä"'
MENU_FR[$MENU_REGULARBACKUP_DISABLE]='"R1" "Désactiver la sauvegarde régulière"'
MENU_ZH[$MENU_REGULARBACKUP_DISABLE]='"R1" "禁用定期备份"'
MENU_CONFIG_DAY=$((MCNT++))
MENU_EN[$MENU_CONFIG_DAY]='"R2" "Weekday of regular backup"'
MENU_DE[$MENU_CONFIG_DAY]='"R2" "Wochentag des regelmäßigen Backups"'
MENU_FI[$MENU_CONFIG_DAY]='"R2" "Säännöllisen varmuuskopioinnin viikonpäivä"'
MENU_FR[$MENU_CONFIG_DAY]='"R2" "Choisir le jour de la semaine de la sauvegarde"'
MENU_ZH[$MENU_CONFIG_DAY]='"R2" "每日备份"'
MENU_CONFIG_TIME=$((MCNT++))
MENU_EN[$MENU_CONFIG_TIME]='"R3" "Time of regular backup"'
MENU_DE[$MENU_CONFIG_TIME]='"R3" "Zeit des regelmäßigen Backups"'
MENU_FI[$MENU_CONFIG_TIME]='"R3" "Säännöllisen varmuuskopioinnin kellonaika"'
MENU_FR[$MENU_CONFIG_TIME]='"R3" "Choisir une heure pour la sauvegarde "'
MENU_ZH[$MENU_CONFIG_TIME]='"R3" "定期备份间隔"'
MENU_CONFIG_LANGUAGE_EN=$((MCNT++))
MENU_EN[$MENU_CONFIG_LANGUAGE_EN]='"EN" "English"'
MENU_DE[$MENU_CONFIG_LANGUAGE_EN]='"EN" "Englisch"'
MENU_FI[$MENU_CONFIG_LANGUAGE_EN]='"EN" "englanti"'
MENU_FR[$MENU_CONFIG_LANGUAGE_EN]='"EN" "Anglais"'
MENU_ZH[$MENU_CONFIG_LANGUAGE_EN]='"EN" "英语"'
MENU_CONFIG_LANGUAGE_DE=$((MCNT++))
MENU_EN[$MENU_CONFIG_LANGUAGE_DE]='"DE" "German"'
MENU_DE[$MENU_CONFIG_LANGUAGE_DE]='"DE" "Deutsch"'
MENU_FI[$MENU_CONFIG_LANGUAGE_DE]='"DE" "saksa"'
MENU_FR[$MENU_CONFIG_LANGUAGE_DE]='"DE" "Allemand"'
MENU_ZH[$MENU_CONFIG_LANGUAGE_DE]='"DE" "德语"'
MENU_CONFIG_LANGUAGE_FI=$((MCNT++))
MENU_EN[$MENU_CONFIG_LANGUAGE_FI]='"FI" "Finnish"'
MENU_DE[$MENU_CONFIG_LANGUAGE_FI]='"FI" "Finnisch"'
MENU_FI[$MENU_CONFIG_LANGUAGE_FI]='"FI" "suomi"'
MENU_FR[$MENU_CONFIG_LANGUAGE_FI]='"FI" "Finlandais"'
MENU_ZH[$MENU_CONFIG_LANGUAGE_FI]='"FI" "芬兰语"'
MENU_CONFIG_LANGUAGE_FR=$((MCNT++))
MENU_EN[$MENU_CONFIG_LANGUAGE_FR]='"FR" "French"'
MENU_DE[$MENU_CONFIG_LANGUAGE_FR]='"FR" "Französisch"'
MENU_FI[$MENU_CONFIG_LANGUAGE_FR]='"FR" "Ranskan kieli"'
MENU_FR[$MENU_CONFIG_LANGUAGE_FR]='"FR" "Français"'
MENU_ZH[$MENU_CONFIG_LANGUAGE_FR]='"FR" "法語"'
MENU_CONFIG_LANGUAGE_ZH=$((MCNT++))
MENU_EN[$MENU_CONFIG_LANGUAGE_ZH]='"ZH" "Chinese"'
MENU_DE[$MENU_CONFIG_LANGUAGE_ZH]='"ZH" "Chinesisch"'
MENU_FI[$MENU_CONFIG_LANGUAGE_ZH]='"ZH" "Kiina"'
MENU_FR[$MENU_CONFIG_LANGUAGE_ZH]='"ZH" "Chinois"'
MENU_ZH[$MENU_CONFIG_LANGUAGE_ZH]='"ZH" "中文"'
MENU_CONFIG_MESSAGE_N=$((MCNT++))
MENU_EN[$MENU_CONFIG_MESSAGE_N]='"Normal" "Display important messages only"'
MENU_DE[$MENU_CONFIG_MESSAGE_N]='"Normal" "Nur wichtige Meldungen anzeigen"'
MENU_FI[$MENU_CONFIG_MESSAGE_N]='"Normaali" "Näytä vain tärkeät viestit"'
MENU_FR[$MENU_CONFIG_MESSAGE_N]='"Normal" "Afficher uniquement les messages importants"'
MENU_ZH[$MENU_CONFIG_MESSAGE_N]='"一般" "仅显示重要信息"'
MENU_CONFIG_MESSAGE_V=$((MCNT++))
MENU_EN[$MENU_CONFIG_MESSAGE_V]='"Verbose" "Display all messages"'
MENU_DE[$MENU_CONFIG_MESSAGE_V]='"Detailiert" "Alle Meldungen anzeigen"'
MENU_FI[$MENU_CONFIG_MESSAGE_V]='"Tarkka" "Näytä kaikki viestit"'
MENU_FR[$MENU_CONFIG_MESSAGE_V]='"Complet" "Afficher tous les messages"'
MENU_ZH[$MENU_CONFIG_MESSAGE_V]='"详细" "显示所有信息"'
MENU_CONFIG_BACKUPPATH=$((MCNT++))
MENU_EN[$MENU_CONFIG_BACKUPPATH]='"C2" "Backup path"'
MENU_DE[$MENU_CONFIG_BACKUPPATH]='"C2" "Backupverzeichnispfad"'
MENU_FI[$MENU_CONFIG_BACKUPPATH]='"C2" "Varmuuskopioiden sijainti"'
MENU_FR[$MENU_CONFIG_BACKUPPATH]='"C2" "Choisir le répertoire de sauvegarde"'
MENU_ZH[$MENU_CONFIG_BACKUPPATH]='"C2" "备份路径"'
MENU_CONFIG_BACKUPS=$((MCNT++))
MENU_EN[$MENU_CONFIG_BACKUPS]='"C3" "Backup versions"'
MENU_DE[$MENU_CONFIG_BACKUPS]='"C3" "Backupversionen"'
MENU_FI[$MENU_CONFIG_BACKUPS]='"C3" "Varmuuskopioiden versioiden säilytys"'
MENU_FR[$MENU_CONFIG_BACKUPS]='"C3" "Versions de sauvegarde"'
MENU_ZH[$MENU_CONFIG_BACKUPS]='"C3" "备份版本"'
MENU_CONFIG_TYPE=$((MCNT++))
MENU_EN[$MENU_CONFIG_TYPE]='"C4" "Backup type"'
MENU_DE[$MENU_CONFIG_TYPE]='"C4" "Backup Typ"'
MENU_FI[$MENU_CONFIG_TYPE]='"C4" "Varmuuskopiontien tyyppi"'
MENU_FR[$MENU_CONFIG_TYPE]='"C4" "Type de sauvegarde"'
MENU_ZH[$MENU_CONFIG_TYPE]='"C4" "备份类型"'
MENU_CONFIG_MODE=$((MCNT++))
MENU_EN[$MENU_CONFIG_MODE]='"C5" "Backup mode"'
MENU_DE[$MENU_CONFIG_MODE]='"C5" "Backup Modus"'
MENU_FI[$MENU_CONFIG_MODE]='"C5" "Varmuuskopiointitila"'
MENU_FR[$MENU_CONFIG_MODE]='"C5" "Mode de sauvegarde"'
MENU_ZH[$MENU_CONFIG_MODE]='"C5" "备份模式"'
MENU_CONFIG_SERVICES=$((MCNT++))
MENU_EN[$MENU_CONFIG_SERVICES]='"C6" "Services to stop and start"'
MENU_DE[$MENU_CONFIG_SERVICES]='"C6" "Zu stoppende und startende Services"'
MENU_FI[$MENU_CONFIG_SERVICES]='"C6" "Palveluiden pysäyttäminen ja uudelleenkäynnistäminen"'
MENU_FR[$MENU_CONFIG_SERVICES]='"C6" "Services à arrêter ou à démarrer"'
MENU_ZH[$MENU_CONFIG_SERVICES]='"C6" "需要处理的系统服务"'
MENU_CONFIG_MESSAGE=$((MCNT++))
MENU_EN[$MENU_CONFIG_MESSAGE]='"C7" "Message verbosity"'
MENU_DE[$MENU_CONFIG_MESSAGE]='"C7" "Meldungsgenauigkeit"'
MENU_FI[$MENU_CONFIG_MESSAGE]='"C7" "Viestien yksityiskohtaisuus"'
MENU_FR[$MENU_CONFIG_MESSAGE]='"C7" "Affichage des messages"'
MENU_ZH[$MENU_CONFIG_MESSAGE]='"C7" "信息设置"'
MENU_CONFIG_EMAIL=$((MCNT++))
MENU_EN[$MENU_CONFIG_EMAIL]='"C8" "eMail notification"'
MENU_DE[$MENU_CONFIG_EMAIL]='"C8" "eMail Benachrichtigung"'
MENU_FI[$MENU_CONFIG_EMAIL]='"C8" "Sähköposti-ilmoitus"'
MENU_FR[$MENU_CONFIG_EMAIL]='"C8" "Notification par courrier électronique"'
MENU_ZH[$MENU_CONFIG_EMAIL]='"C8" "邮件通知"'
MENU_CONFIG_REGULAR=$((MCNT++))
MENU_EN[$MENU_CONFIG_REGULAR]='"C9" "Regular backup"'
MENU_DE[$MENU_CONFIG_REGULAR]='"C9" "Regelmäßiges Backup"'
MENU_FI[$MENU_CONFIG_REGULAR]='"C9" "Säännöllinen varmuuskopiointi"'
MENU_FR[$MENU_CONFIG_REGULAR]='"C9" "Sauvegardes Régulières"'
MENU_ZH[$MENU_CONFIG_REGULAR]='"C9" "定期备份"'
MENU_CONFIG_ZIP=$((MCNT++))
MENU_EN[$MENU_CONFIG_ZIP]='"C10" "Compression"'
MENU_DE[$MENU_CONFIG_ZIP]='"C10" "Komprimierung"'
MENU_FI[$MENU_CONFIG_ZIP]='"C10" "Pakkaaminen"'
MENU_FR[$MENU_CONFIG_ZIP]='"C10" "Compression"'
MENU_ZH[$MENU_CONFIG_ZIP]='"C10" "压缩"'
MENU_CONFIG_ZIP_NA=$((MCNT++))
MENU_EN[$MENU_CONFIG_ZIP_NA]='" " " "'
MENU_DE[$MENU_CONFIG_ZIP_NA]='" " " "'
MENU_FI[$MENU_CONFIG_ZIP_NA]='" " " "'
MENU_FR[$MENU_CONFIG_ZIP_NA]='" " " "'
MENU_ZH[$MENU_CONFIG_ZIP_NA]='" " " "'
MENU_CONFIG_MODE_KEEP=$((MCNT++))
MENU_EN[$MENU_CONFIG_MODE_KEEP]='"Simple" "Keep a maximum number of backups"'
MENU_DE[$MENU_CONFIG_MODE_KEEP]='"Einfach" "Eine maximale Anzahl von Backups vorhalten"'
MENU_FI[$MENU_CONFIG_MODE_KEEP]='"Yksinkertainen" "Säilytä valitsemasi lukumäärän verran varmuuskopioita"'
MENU_FR[$MENU_CONFIG_MODE_KEEP]='"Simple" "En choisissant un nombre maximum de sauvegardes"'
MENU_ZH[$MENU_CONFIG_MODE_KEEP]='"简单" "保留最大数量的备份文件"'
MENU_CONFIG_MODE_SMART=$((MCNT++))
MENU_EN[$MENU_CONFIG_MODE_SMART]='"Smart" "Smart backup strategy"'
MENU_DE[$MENU_CONFIG_MODE_SMART]='"Intelligent" "Intelligente Backupstrategie "'
MENU_FI[$MENU_CONFIG_MODE_SMART]='"Älykäs" "Älykäs varmuuskopiointistrategia"'
MENU_FR[$MENU_CONFIG_MODE_SMART]='"Intelligente" "Avec la stratégie ntelligente"'
MENU_ZH[$MENU_CONFIG_MODE_SMART]='"智能" "智能备份策略"'
MENU_CONFIG_MODE_NORMAL=$((MCNT++))
MENU_EN[$MENU_CONFIG_MODE_NORMAL]='"Standard" "Backup the two standard partitions"'
MENU_DE[$MENU_CONFIG_MODE_NORMAL]='"Standard" "Sichere die zwei Standardpartitionen "'
MENU_FI[$MENU_CONFIG_MODE_NORMAL]='"Standardi" "Varmuuskopioi kaksi standardiosiota"'
MENU_FR[$MENU_CONFIG_MODE_NORMAL]='"Standard" "Sauvegarde des deux partitions standards"'
MENU_ZH[$MENU_CONFIG_MODE_NORMAL]='"标准" "备份2个标准分区"'
MENU_CONFIG_MODE_PARTITION=$((MCNT++))
MENU_EN[$MENU_CONFIG_MODE_PARTITION]='"Extended" "Backup more than two partitions"'
MENU_DE[$MENU_CONFIG_MODE_PARTITION]='"Erweitert" "Sichere mehr als zwei Partitionen"'
MENU_FI[$MENU_CONFIG_MODE_PARTITION]='"Laajennettu" "Varmuuskopioi enemmän kuin kaksi osiota"'
MENU_FR[$MENU_CONFIG_MODE_PARTITION]='"Elargi" "Sauvegarde de plus de deux partitions"'
MENU_ZH[$MENU_CONFIG_MODE_PARTITION]='"扩展" "备份多于2个分区"'
MENU_INSTALL_INSTALL=$((MCNT++))
MENU_EN[$MENU_INSTALL_INSTALL]='"I1" "Install $RASPIBACKUP_NAME using a default configuration"'
MENU_DE[$MENU_INSTALL_INSTALL]='"I1" "Installiere $RASPIBACKUP_NAME mit einer Standardkonfiguration"'
MENU_FI[$MENU_INSTALL_INSTALL]='"I1" "Asenna $RASPIBACKUP_NAME oletusasetuksilla"'
MENU_FR[$MENU_INSTALL_INSTALL]='"I1" "Installer $RASPIBACKUP_NAME en utilisant une configuration par défaut"'
MENU_ZH[$MENU_INSTALL_INSTALL]='"I1" "使用默认设置安装 $RASPIBACKUP_NAME "'
MENU_INSTALL_EXTENSIONS=$((MCNT++))
MENU_EN[$MENU_INSTALL_EXTENSIONS]='"I2" "Install and enable sample extension"'
MENU_DE[$MENU_INSTALL_EXTENSIONS]='"I2" "Installiere Beispielerweiterungen"'
MENU_FI[$MENU_INSTALL_EXTENSIONS]='"I2" "Asenna ja ota käyttöön näytelisäosat"'
MENU_FR[$MENU_INSTALL_EXTENSIONS]='"I2" "Installer et activer l'\''exemple d'\''extension"'
MENU_ZH[$MENU_INSTALL_EXTENSIONS]='"I2" "安装并开启示例扩展"'
MENU_CONFIG_MAIL_MAIL=$((MCNT++))
MENU_EN[$MENU_CONFIG_MAIL_MAIL]='"mail" ""'
MENU_DE[$MENU_CONFIG_MAIL_MAIL]='"mail" ""'
MENU_FI[$MENU_CONFIG_MAIL_MAIL]='"mail" ""'
MENU_FR[$MENU_CONFIG_MAIL_MAIL]='"mail" ""'
MENU_ZH[$MENU_CONFIG_MAIL_MAIL]='"mail" ""'
MENU_CONFIG_MAIL_SSMTP=$((MCNT++))
MENU_EN[$MENU_CONFIG_MAIL_SSMTP]='"ssmtp" ""'
MENU_DE[$MENU_CONFIG_MAIL_SSMTP]='"ssmtp" ""'
MENU_FI[$MENU_CONFIG_MAIL_SSMTP]='"ssmtp" ""'
MENU_FR[$MENU_CONFIG_MAIL_SSMTP]='"ssmtp" ""'
MENU_ZH[$MENU_CONFIG_MAIL_SSMTP]='"ssmtp" ""'
MENU_CONFIG_MAIL_MSMTP=$((MCNT++))
MENU_EN[$MENU_CONFIG_MAIL_MSMTP]='"msmtp" ""'
MENU_DE[$MENU_CONFIG_MAIL_MSMTP]='"msmtp" ""'
MENU_FI[$MENU_CONFIG_MAIL_MSMTP]='"msmtp" ""'
MENU_FR[$MENU_CONFIG_MAIL_MSMTP]='"msmtp" ""'
MENU_ZH[$MENU_CONFIG_MAIL_MSMTP]='"msmtp" ""'
MENU_CONFIG_TYPE_DD=$((MCNT++))
MENU_EN[$MENU_CONFIG_TYPE_DD]='"dd" "Backup with dd and restore on Windows"'
MENU_DE[$MENU_CONFIG_TYPE_DD]='"dd" "Sichere mit dd und stelle unter Windows wieder her"'
MENU_FI[$MENU_CONFIG_TYPE_DD]='"dd" "dd-varmuuskopio, mahdollistaa palautuksen Windowsissa"'
MENU_FR[$MENU_CONFIG_TYPE_DD]='"dd" "Sauvegarder avec dd et restaurer sous Windows"'
MENU_ZH[$MENU_CONFIG_TYPE_DD]='"dd" "使用dd备份并且在Windows上恢复"'
MENU_CONFIG_TYPE_TAR=$((MCNT++))
MENU_EN[$MENU_CONFIG_TYPE_TAR]='"tar" "Backup with tar"'
MENU_DE[$MENU_CONFIG_TYPE_TAR]='"tar" "Sichere mit tar"'
MENU_FI[$MENU_CONFIG_TYPE_TAR]='"tar" "tar-varmuuskopio"'
MENU_FR[$MENU_CONFIG_TYPE_TAR]='"tar" "Sauvegarde avec tar"'
MENU_ZH[$MENU_CONFIG_TYPE_TAR]='"tar" "使用tar备份"'
MENU_CONFIG_TYPE_RSYNC=$((MCNT++))
MENU_EN[$MENU_CONFIG_TYPE_RSYNC]='"rsync" "Backup with rsync and use hardlinks if possible"'
MENU_DE[$MENU_CONFIG_TYPE_RSYNC]='"rsync" "Sichere mit rsync und benutze Hardlinks wenn möglich"'
MENU_FI[$MENU_CONFIG_TYPE_RSYNC]='"rsync" "rsync-varmuuskopio ja hardlinkkien käyttö"'
MENU_FR[$MENU_CONFIG_TYPE_RSYNC]='"rsync" "Sécuriser avec rsync en utilisant si possible des liens physiques"'
MENU_ZH[$MENU_CONFIG_TYPE_RSYNC]='"rsync" "使用rsync备份,如果可能,使用硬链接"'
MENU_UNINSTALL_UNINSTALL=$((MCNT++))
MENU_EN[$MENU_UNINSTALL_UNINSTALL]='"U1" "Uninstall $RASPIBACKUP_NAME"'
MENU_DE[$MENU_UNINSTALL_UNINSTALL]='"U1" "Lösche $RASPIBACKUP_NAME"'
MENU_FI[$MENU_UNINSTALL_UNINSTALL]='"U1" "Poista $RASPIBACKUP_NAME -asennus"'
MENU_FR[$MENU_UNINSTALL_UNINSTALL]='"U1" "Supprimer $RASPIBACKUP_NAME -asennus"'
MENU_ZH[$MENU_UNINSTALL_UNINSTALL]='"U1" "卸载 $RASPIBACKUP_NAME"'
MENU_UNINSTALL_EXTENSION=$((MCNT++))
MENU_EN[$MENU_UNINSTALL_EXTENSION]='"U2" "Uninstall and disable sample extensions"'
MENU_DE[$MENU_UNINSTALL_EXTENSION]='"U2" "Lösche Extensions"'
MENU_FI[$MENU_UNINSTALL_EXTENSION]='"U2" "Poista käytöstä ja pura näytelisäosien asennukset"'
MENU_FR[$MENU_UNINSTALL_EXTENSION]='"U2" "Supprimer les Extensions"'
MENU_ZH[$MENU_UNINSTALL_EXTENSION]='"U2" "卸载并禁用示例扩展"'
MENU_CONFIG_TYPE_DD_NA=$((MCNT++))
MENU_EN[$MENU_CONFIG_TYPE_DD_NA]='"" "Backup with dd not possible with this mode"'
MENU_DE[$MENU_CONFIG_TYPE_DD_NA]='"" "Sichern mit dd nicht möglich bei diesem Modus"'
MENU_FI[$MENU_CONFIG_TYPE_DD_NA]='"" "DD-varmuuskopio ei ole mahdollista tässä tilassa"'
MENU_FR[$MENU_CONFIG_TYPE_DD_NA]='"" "Un enregistrement avec dd ne peut se faire dans ce mode"'
MENU_ZH[$MENU_CONFIG_TYPE_DD_NA]='"" "此模式不可使用dd备份"'
MENU_CONFIG_COMPRESS_OFF=$((MCNT++))
MENU_EN[$MENU_CONFIG_COMPRESS_OFF]='"off" "No backup compression"'
MENU_DE[$MENU_CONFIG_COMPRESS_OFF]='"aus" "Keine Backup Komprimierung"'
MENU_FI[$MENU_CONFIG_COMPRESS_OFF]='"off" "Ei varmuuskopion pakkausta"'
MENU_FR[$MENU_CONFIG_COMPRESS_OFF]='"off" "Pas de compression de sauvegarde"'
MENU_ZH[$MENU_CONFIG_COMPRESS_OFF]='"off" "不压缩"'
MENU_CONFIG_COMPRESS_ON=$((MCNT++))
MENU_EN[$MENU_CONFIG_COMPRESS_ON]='"on" "Compress $CONFIG_BACKUPTYPE backup"'
MENU_DE[$MENU_CONFIG_COMPRESS_ON]='"an" "Komprimiere den $CONFIG_BACKUPTYPE Backup"'
MENU_FI[$MENU_CONFIG_COMPRESS_ON]='"on" "Pakkaa $CONFIG_BACKUPTYPE -varmuuskopio"'
MENU_FR[$MENU_CONFIG_COMPRESS_ON]='"on" "Compresser la sauvegarde $CONFIG_BACKUPTYPE"'
MENU_ZH[$MENU_CONFIG_COMPRESS_ON]='"on" "压缩 $CONFIG_BACKUPTYPE 备份"'
MENU_DAYS_SHORT=$((MCNT++))
MENU_EN[$MENU_DAYS_SHORT]='"Daily" "Sun" "Mon" "Tue" "Wed" "Thu" "Fri" "Sat"'
MENU_DE[$MENU_DAYS_SHORT]='"Täglich" "So" "Mo" "Di" "Mi" "Do" "Fr" "Sa"'
MENU_FI[$MENU_DAYS_SHORT]='"Päivittäin" "Su" "Ma" "Ti" "Ke" "To" "Pe" "La"'
MENU_FR[$MENU_DAYS_SHORT]='"Journalier" "Di" "Lu" "Ma" "Me" "Je" "Ve" "Sa"'
MENU_ZH[$MENU_DAYS_SHORT]='"Daily" "Sun" "Mon" "Tue" "Wed" "Thu" "Fri" "Sat"'
MENU_DAYS_LONG=$((MCNT++))
MENU_EN[$MENU_DAYS_LONG]='"Daily" "Sunday" "Monday" "Tuesday" "Wednesday" "Thursday" "Friday" "Saturday"'
MENU_DE[$MENU_DAYS_LONG]='"Täglich" "Sonntag" "Montag" "Dienstag" "Mittwoch" "Donnerstag" "Freitag" "Samstag"'
MENU_FI[$MENU_DAYS_LONG]='"Päivittäin" "Sunnuntai" "Maanantai" "Tiistai" "Keskiviikko" "Torstai" "Perjantai" "Lauantai"'
MENU_FR[$MENU_DAYS_LONG]='"Journalier" "Dimanche" "Lundi" "Mardi" "Mercredi" "Jeudi" "Vendredi" "Samedi"'
MENU_ZH[$MENU_DAYS_LONG]='"Daily" "Sunday" "Monday" "Tuesday" "Wednesday" "Thursday" "Friday" "Saturday"'
MENU_UPDATE_SCRIPT=$((MCNT++))
MENU_EN[$MENU_UPDATE_SCRIPT]='"P1" "Update $FILE_TO_INSTALL"'
MENU_DE[$MENU_UPDATE_SCRIPT]='"P1" "Aktualisiere $FILE_TO_INSTALL"'
MENU_FI[$MENU_UPDATE_SCRIPT]='"P1" "Päivitä $FILE_TO_INSTALL"'
MENU_FR[$MENU_UPDATE_SCRIPT]='"P1" "Mettre à jour $FILE_TO_INSTALL"'
MENU_ZH[$MENU_UPDATE_SCRIPT]='"P1" "更新 $FILE_TO_INSTALL"'
MENU_UPDATE_INSTALLER=$((MCNT++))
MENU_EN[$MENU_UPDATE_INSTALLER]='"P2" "Update $MYSELF"'
MENU_DE[$MENU_UPDATE_INSTALLER]='"P2" "Aktualisiere $MYSELF"'
MENU_FI[$MENU_UPDATE_INSTALLER]='"P2" "Päivitä $MYSELF"'
MENU_FR[$MENU_UPDATE_INSTALLER]='"P2" "Mettre à jour $MYSELF"'
MENU_ZH[$MENU_UPDATE_INSTALLER]='"P2" "更新 $MYSELF"'
declare -A MSG_HEADER=(['I']="---" ['W']="!!!" ['E']="???")
INSTALLATION_SUCCESSFULL=0
INSTALLATION_STARTED=0
CONFIG_INSTALLED=0
SCRIPT_INSTALLED=0
EXTENSIONS_INSTALLED=0
CRON_INSTALLED=0
SYSTEMD_INSTALLED=0
PROGRESSBAR_DO=0
INSTALL_EXTENSIONS=0
BETA_INSTALL=0
CRONTAB_ENABLED="undefined"
SYSTEMD_ENABLED="undefined"
function findUser() {
local u
if [[ -n "$SUDO_USER" ]]; then
u="$SUDO_USER"
else
u="$USER"
fi
echo "$u"
}
function existsLocalPropertiesFile() {
[[ -e "$LOCAL_PROPERTY_FILE" ]]
}
function checkRequiredDirectories() {
local dirs=( "$BIN_DIR" "$ETC_DIR" "$CRON_DIR")
for d in "${dirs[@]}"; do
logItem "Checking for $d"
if [[ ! -d $d ]]; then
unrecoverableError $MSG_MISSING_DIRECTORY "$d"
return
fi
done
}
# Create message and substitute parameters
function getMessageText() { # messagenumber parm1 parm2 ...
local msg p i s
msgVar="MSG_${CONFIG_LANGUAGE}"
if [[ -n ${SUPPORTED_LANGUAGES[$CONFIG_LANGUAGE]} ]]; then
msgVar="$msgVar[$1]"
msg=${!msgVar}
if [[ -z $msg ]]; then # no translation found
msg="${MSG_EN[$1]}" # fallback into english
fi
else
msg="${MSG_EN[$1]}" # fallback into english
fi
shift
for ((i = 1; $i <= $#; i++)); do # substitute all message parameters
p=${!i}
let s=$i
s="%$s"
msg="$(sed "s|$s|$p|" <<<"$msg" 2>/dev/null)" # have to use explicit command name
done
msg="$(sed "s/%[0-9]+//g" <<<"$msg" 2>/dev/null)" # delete trailing %n definitions
local msgPref=${msg:0:3}
if [[ $msgPref == "RBK" ]]; then # RBK0001E
local severity=${msg:7:1}
if [[ "$severity" =~ [EWI] ]]; then
local msgHeader=${MSG_HEADER[$severity]}
echo "$msgHeader $msg"
else
echo "$msg"
fi
else
echo "$msg"
fi
}
function getMenuText() { # menutextnumber varname
local menu varname
local menuVar="MENU_${CONFIG_LANGUAGE}"
declare -n varname=$2
if [[ -n ${SUPPORTED_LANGUAGES[$CONFIG_LANGUAGE]} ]]; then
menuVar="$menuVar[$1]"
menu="${!menuVar}"
if [[ -z $menu ]]; then # no translation found
menu="${MENU_EN[$1]}" # fallback into english
fi
else
menu="${MENU_EN[$1]}" # fallback into english
fi
eval "varname=( ${menu[@]} )"
}
function writeToConsole() {
local msg="$(getMessageText "$@")"
echo "MSG: $msg" >>"$LOG_FILE"
if (( $MODE_UNATTENDED )); then
echo "$msg"
fi
}
function log() { # logtype message
local lineno=${BASH_LINENO[1]}
local dte=$(date +%Y%m%d-%H%M%S)
local indent=$(printf '%*s' "$LOG_INDENT")
printf "%s: DBG: %04d - %s %s\n" "$dte" "$lineno" "$indent" "$@" >> "$LOG_FILE"
}
function logItem() { # message
log "$@"
}
function downloadURL() { # fileName
logEntry "$1"
local u="$MYHOMEURL/raspiBackup$URLTARGET/$1"
echo "$u"
logExit "$u"
}
function check4InternetAvailable() {
if (( ! RASPIBACKUP_INSTALL_DEBUG )); then
writeToConsole $MSG_LEVEL_MINIMAL $MSG_CHECK_INTERNET_CONNECTION
isInternetAvailable
if (( $? != 0 )); then
writeToConsole $MSG_LEVEL_MINIMAL $MSG_NO_INTERNET_CONNECTION_FOUND
exit
fi
fi
}
function isInternetAvailable() {
logEntry
wget -q --spider -t 1 -T 3 $MYHOMEDOMAIN
local rc=$?
logExit $rc
return $rc
}
function logEntry() {
log "-> ${FUNCNAME[1]} $@"
(( LOG_INDENT+=3 ))
}
function logExit() {
(( LOG_INDENT-=3 ))
log "<- ${FUNCNAME[1]} $@"
}
function finished() {
:
}
function center() { #
local columns="$1"
shift 1
while IFS= read -r line; do
printf "%*s\n" $(((${#line} + columns) / 2)) "$line"
done <<<"$@"
}
function isTimerEnabled() {
logEntry
local rc
if (( $USE_SYSTEMD )); then
isSystemdEnabled
else
isCrontabEnabled
fi
rc=$?
logExit $rc
return $rc
}
function isCrontabEnabled() {
logEntry $CRONTAB_ENABLED
if [[ "$CRONTAB_ENABLED" == "undefined" ]]; then
if isCrontabConfigInstalled; then
local l="$(tail -n 1 < $CRON_ABS_FILE)"
logItem "$l"
[[ ${l:0:1} != "#" ]]
CRONTAB_ENABLED=$?
else
CRONTAB_ENABLED=0
fi
fi
logExit $CRONTAB_ENABLED
return $CRONTAB_ENABLED
}
function isSystemdEnabled() {
logEntry $SYSTEMD_ENABLED
if [[ "$SYSTEMD_ENABLED" == "undefined" ]]; then
if isSystemdConfigInstalled; then
local state="$(systemctl show --no-pager $SYSTEMD_TIMER_FILE_NAME | grep -i "ActiveState" | cut -f 2 -d '=')"
logItem "Current systemd state: $state"
[[ $state == "active" ]]
SYSTEMD_ENABLED=$?
else
SYSTEMD_ENABLED=0
fi
fi
logExit $SYSTEMD_ENABLED
return $SYSTEMD_ENABLED
}
function isCrontabConfigInstalled() {
logEntry
local rc
[[ -f $CRON_ABS_FILE ]]
rc=$?
logExit $rc
return $rc
}
function isSystemdConfigInstalled() {
logEntry
local rc
[[ -f $SYSTEMD_SERVICE_ABS_FILE && -f $SYSTEMD_TIMER_ABS_FILE ]]
rc=$?
logExit $rc
return $rc
}
function isConfigInstalled() {
[[ -f $CONFIG_ABS_FILE ]]
return
}
function isExtensionInstalled() {
ls $FILE_TO_INSTALL_ABS_PATH/${RASPIBACKUP_NAME}_*.sh 2>/dev/null &>>"$LOG_FILE"
return
}
function isRaspiBackupInstalled() {
[[ -f $FILE_TO_INSTALL_ABS_FILE ]]
return
}
function isStartStopDefined() {
[[ ! -z $CONFIG_STOPSERVICES ]] && [[ "$CONFIG_STOPSERVICES" != "$IGNORE_START_STOP_CHAR" ]]
return
}
function createSymLink() { # create link from /usr/local/bin/ to /usr/local/bin/.sh
local fileName="$1"
local linkName="${fileName%.*}"
rm -f $linkName &>/dev/null
if ! ln -s $fileName $linkName; then
unrecoverableError $MSG_MOVE_FAILED "$linkName"
return 1
fi
}
function deleteSymLink() { # delete link from /usr/local/bin/ to /usr/local/bin/.sh
local fileName="$1"
local linkName="${fileName%.*}"
rm -f $linkName &>/dev/null
}
function code_download_execute() {
logEntry
local newName
if [[ -f "$FILE_TO_INSTALL_ABS_FILE" ]]; then
oldVersion=$(grep -o -E "^VERSION=\".+\"" "$FILE_TO_INSTALL_ABS_FILE" | sed -e "s/VERSION=//" -e "s/\"//g")
newName="$FILE_TO_INSTALL_ABS_FILE.$oldVersion.sh"
writeToConsole $MSG_SAVING_FILE "$FILE_TO_INSTALL" "$newName"
mv "$FILE_TO_INSTALL_ABS_FILE" "$newName" &>>"$LOG_FILE"
fi
if (($BETA_INSTALL)); then
FILE_TO_INSTALL_URL="$BETA_CODE_URL"
writeToConsole $MSG_DOWNLOADING_BETA "$FILE_TO_INSTALL"
else
FILE_TO_INSTALL_URL="$STABLE_CODE_URL"
writeToConsole $MSG_DOWNLOADING "$FILE_TO_INSTALL"
fi
local httpCode="$(downloadFile "$(downloadURL "$FILE_TO_INSTALL")" "/tmp/$FILE_TO_INSTALL")"
if (( $? )); then
unrecoverableError $MSG_DOWNLOAD_FAILED "$(downloadURL "$FILE_TO_INSTALL")" "$httpCode"
logExit
return
fi
if ! mv "/tmp/$FILE_TO_INSTALL" "$FILE_TO_INSTALL_ABS_FILE" &>>"$LOG_FILE"; then
unrecoverableError $MSG_MOVE_FAILED "$FILE_TO_INSTALL_ABS_FILE"
logExit
return
fi
SCRIPT_INSTALLED=1
writeToConsole $MSG_CODE_INSTALLED "$FILE_TO_INSTALL_ABS_FILE"
if ! chmod 755 $FILE_TO_INSTALL_ABS_FILE &>>$LOG_FILE; then
unrecoverableError $MSG_CHMOD_FAILED "$FILE_TO_INSTALL_ABS_FILE"
logExit
return
fi
if ! createSymLink "$FILE_TO_INSTALL_ABS_FILE"; then
logExit
return
fi
if [[ -e "$MYDIR/$MYSELF" && "$MYDIR/$MYSELF" != "$FILE_TO_INSTALL_ABS_PATH/$MYSELF" ]]; then
if (( ! $RASPIBACKUP_INSTALL_DEBUG )); then
if ! mv -f "$MYDIR/$MYSELF" "$FILE_TO_INSTALL_ABS_PATH" &>>"$LOG_FILE"; then
unrecoverableError $MSG_MOVE_FAILED "$FILE_TO_INSTALL_ABS_PATH/$MYSELF"
logExit
return
fi
else
cp "$MYDIR/$MYSELF" "$FILE_TO_INSTALL_ABS_PATH" &>>"$LOG_FILE"
fi
fi
writeToConsole $MSG_CODE_INSTALLED "$FILE_TO_INSTALL_ABS_PATH/$MYSELF"
if ! chmod 755 $FILE_TO_INSTALL_ABS_PATH/$MYSELF &>>"$LOG_FILE"; then
unrecoverableError $MSG_CHMOD_FAILED "$FILE_TO_INSTALL_ABS_PATH/$MYSELF"
logExit
return
fi
local chownArgs=$(stat -c "%U:%G" $FILE_TO_INSTALL_ABS_PATH | sed 's/\n//')
if ! chown $chownArgs "$FILE_TO_INSTALL_ABS_PATH/$MYSELF" &>>"$LOG_FILE"; then
unrecoverableError $MSG_CHOWN_FAILED "$FILE_TO_INSTALL_ABS_PATH/$MYSELF"
logExit
return
fi
if ! createSymLink "$FILE_TO_INSTALL_ABS_PATH/$MYSELF"; then
logExit
return
fi
logExit
}
function update_script_execute() {
logEntry
local newName
if [[ -f "$FILE_TO_INSTALL_ABS_FILE" ]]; then
oldVersion=$(grep -o -E "^VERSION=\".+\"" "$FILE_TO_INSTALL_ABS_FILE" | sed -e "s/VERSION=//" -e "s/\"//g")
newName="$FILE_TO_INSTALL_ABS_PATH/${RASPIBACKUP_NAME}.${oldVersion}.sh"
writeToConsole $MSG_SAVING_FILE "$FILE_TO_INSTALL" "$newName"
mv "$FILE_TO_INSTALL_ABS_FILE" "$newName" &>>"$LOG_FILE"
fi
local httpCode="$(downloadFile "$(downloadURL "$FILE_TO_INSTALL")" "/tmp/$FILE_TO_INSTALL" )"
if (( $? )); then
unrecoverableError $MSG_DOWNLOAD_FAILED "$(downloadURL "$FILE_TO_INSTALL")" "$httpCode"
logExit
return
fi
if ! mv "/tmp/$FILE_TO_INSTALL" "$FILE_TO_INSTALL_ABS_FILE" &>>"$LOG_FILE"; then
unrecoverableError $MSG_MOVE_FAILED "$FILE_TO_INSTALL_ABS_FILE"
return
fi
writeToConsole $MSG_CODE_INSTALLED "$FILE_TO_INSTALL_ABS_FILE"
if ! chmod 755 $FILE_TO_INSTALL_ABS_FILE &>>$LOG_FILE; then
unrecoverableError $MSG_CHMOD_FAILED "$FILE_TO_INSTALL_ABS_FILE"
return
fi
logExit
}
function downloadFile() { # url, targetFileName
logEntry "URL: $1, file: $2"
local url="$1"
local file="$2"
local f=$(mktemp)
local httpCode=$(curl -sSL -o "$f" -m $DOWNLOAD_TIMEOUT -w %{http_code} -L "$url" 2>>$LOG_FILE)
local rc=$?
logItem "httpCode: $httpCode RC: $rc"
if [[ $rc != 0 || ${httpCode:0:1} != "2" ]]; then
rm $f &>>$LOG_FILE
logExit $httpCode
return $httpCode
fi
if head -n 1 "$f" | grep -q "^"; then # Download plugin doesn't return 404 if file not found but a HTML doc
rm $f &>>$LOG_FILE
logExit 404
return 404
fi
mv $f $file &>>$LOG_FILE
logExit 0
return 0
}
function update_installer_execute() {
logEntry
local newName
local httpCode="$(downloadFile "$(downloadURL "$MYSELF")" "/tmp/$MYSELF")"
if (( $? )); then
unrecoverableError $MSG_DOWNLOAD_FAILED "$(downloadURL "$MYSELF")" "$httpCode"
return
fi
if ! mv "/tmp/$MYSELF" "$INSTALLER_ABS_FILE" &>>"$LOG_FILE"; then
unrecoverableError $MSG_MOVE_FAILED "$INSTALLER_ABS_FILE"
return
fi
if (( MODE_UPDATE )); then
writeToConsole $MSG_CODE_UPDATED "$INSTALLER_ABS_FILE"
else
writeToConsole $MSG_CODE_INSTALLED "$INSTALLER_ABS_FILE"
fi
if ! chmod 755 $INSTALLER_ABS_FILE &>>$LOG_FILE; then
unrecoverableError $MSG_CHMOD_FAILED "$INSTALLER_ABS_FILE"
return
fi
logExit
}
function config_download_execute() {
logEntry
local newName http_code
if [[ -f "$CONFIG_ABS_FILE" && -f "$FILE_TO_INSTALL_ABS_FILE" ]]; then
oldVersion=$(grep -o -E "^VERSION=\".+\"" "$FILE_TO_INSTALL_ABS_FILE" | sed -e "s/VERSION=//" -e "s/\"//g")
local m=${CONFIG_ABS_FILE##*/}
n=${m%.*}
newName="$n.$oldVersion.conf"
writeToConsole $MSG_SAVING_FILE "$CONFIG_FILE" "$CONFIG_FILE_ABS_PATH/$newName"
[[ "$FILE_TO_INSTALL_ABS_FILE" != "$newName" ]] && mv "$CONFIG_ABS_FILE" "$CONFIG_FILE_ABS_PATH/$newName" &>>"$LOG_FILE"
fi
writeToConsole $MSG_DOWNLOADING "$CONFIG_FILE"
CONFIG_INSTALLED=1
case $CONFIG_LANGUAGE in
DE)
local confFile=${CONFIG_DOWNLOAD_FILE["DE"]}
;;
*)
local confFile=${CONFIG_DOWNLOAD_FILE["EN"]}
;;
esac
httpCode="$(downloadFile "$(downloadURL "$confFile")" "$CONFIG_ABS_FILE")"
if (( $? )); then
unrecoverableError $MSG_DOWNLOAD_FAILED "$(downloadURL "$confFile")" "$httpCode"
return
fi
if ! chmod 600 $CONFIG_ABS_FILE &>>$LOG_FILE; then
unrecoverableError $MSG_CHMOD_FAILED "$CONFIG_ABS_FILE"
return
fi
writeToConsole $MSG_CODE_INSTALLED "$CONFIG_ABS_FILE"
logExit
}
function extensions_install_do() {
logEntry
if ! isRaspiBackupInstalled; then
local m="$(getMessageText $MSG_SCRIPT_NOT_INSTALLED)"
local t=$(center $WINDOW_COLS "$m")
local tt="$(getMessageText $TITLE_INFORMATION)"
whiptail --msgbox "$t" --title "$tt" $ROWS_MSGBOX $WINDOW_COLS 2
logExit
return
fi
if isExtensionInstalled; then
local m="$(getMessageText $MSG_EXTENSIONS_ALREADY_INSTALLED)"
local t=$(center $WINDOW_COLS "$m")
local tt="$(getMessageText $TITLE_INFORMATION)"
whiptail --msgbox "$t" --title "$tt" $ROWS_MSGBOX $WINDOW_COLS 2
logExit
return
fi
INSTALL_DESCRIPTION=("Installing extensions ...")
progressbar_do "INSTALL_DESCRIPTION" "Installing extensions" extensions_install_execute
logExit
}
function extensions_install_execute() {
logEntry
local extensions="mem temp disk"
writeToConsole $MSG_DOWNLOADING "${SAMPLEEXTENSION_TAR_FILE%.*}"
local httpCode="$(downloadFile "$(downloadURL "$SAMPLEEXTENSION_TAR_FILE")" "$SAMPLEEXTENSION_TAR_FILE")"
if (( $? )); then
unrecoverableError $MSG_DOWNLOAD_FAILED "$(downloadURL "$SAMPLEEXTENSION_TAR_FILE")" "$httpCode"
return
fi
if ! tar -xzf "$SAMPLEEXTENSION_TAR_FILE" -C "$FILE_TO_INSTALL_ABS_PATH" &>>"$LOG_FILE"; then
unrecoverableError $MSG_SAMPLEEXTENSION_INSTALL_FAILED "tar -x"
return
fi
if ! chmod 755 $FILE_TO_INSTALL_ABS_PATH/${RASPIBACKUP_NAME}_*.sh &>>"$LOG_FILE"; then
unrecoverableError $MSG_SAMPLEEXTENSION_INSTALL_FAILED "chmod extensions"
return
fi
if ! chown root.root $FILE_TO_INSTALL_ABS_PATH/${RASPIBACKUP_NAME}_*.sh &>>"$LOG_FILE"; then
unrecoverableError $MSG_SAMPLEEXTENSION_INSTALL_FAILED "chmod extensions"
return
fi
if ! rm -f "$SAMPLEEXTENSION_TAR_FILE" 2>>"$LOG_FILE"; then
unrecoverableError $MSG_UNINSTALL_FAILED "$SAMPLEEXTENSION_TAR_FILE"
return
fi
sed -i -E "s/^(#?\s?)?DEFAULT_EXTENSIONS=.*\$/DEFAULT_EXTENSIONS=\"$extensions\"/" $CONFIG_ABS_FILE
EXTENSIONS_INSTALLED=1
writeToConsole $MSG_SAMPLEEXTENSION_INSTALL_SUCCESS
logExit
}
function extensions_uninstall_do() {
logEntry
if ! isExtensionInstalled; then
local a="$(getMessageText $MSG_NO_EXTENSIONS_FOUND)"
local t=$(center $WINDOW_COLS "$a")
local tt="$(getMessageText $TITLE_INFORMATION)"
whiptail --msgbox "$t" --title "$tt" $ROWS_MSGBOX $WINDOW_COLS 2
logExit
return
fi
UNINSTALL_DESCRIPTION=("Uninstalling extensions ...")
progressbar_do "UNINSTALL_DESCRIPTION" "Uninstalling extensions" extensions_uninstall_execute
logExit
}
function extensions_uninstall_execute() {
logEntry
local extensions="mem temp disk"
if ls $FILE_TO_INSTALL_ABS_PATH/${RASPIBACKUP_NAME}_*.sh >&/dev/null; then
if ! rm -f $FILE_TO_INSTALL_ABS_PATH/${RASPIBACKUP_NAME}_*.sh &>>"$LOG_FILE"; then
unrecoverableError $MSG_SAMPLEEXTENSION_UNINSTALL_FAILED "rm extensions"
return
fi
writeToConsole $MSG_SAMPLEEXTENSION_UNINSTALL_SUCCESS
fi
if [[ -f CONFIG_ABS_FILE ]]; then
sed -i -E "s/DEFAULT_EXTENSIONS=.*\$/DEFAULT_EXTENSIONS=\"\"/" $CONFIG_ABS_FILE
fi
EXTENSIONS_INSTALLED=0
logExit
}
function getActiveServices() {
logEntry
logItem "$EXCLUDE_SERVICES_REGEX"
local as=""
IFS=" "
while read s r; do
if [[ $s == *".service" ]]; then
as+=" $(sed 's/.service//' <<< "$s")"
fi
done < <(systemctl list-units --type=service --state=active | grep "active running" | grep -v "$EXCLUDE_SERVICES_REGEX" | awk '{print $1}' )
echo "$as"
logExit "$as"
}
function getPartitionNumbers() { # device, e.g. /dev/mmcblk0
# /dev/sda1 256M c W95
# /dev/sda2 14.3G 83 Linux
# /dev/sda5 265G 83 Linux
logEntry $1
local ap=""
ap="$(LANG=C fdisk -l $1 | grep ^/dev | awk '{ print $1,$5,$6,$7,$8,$9,$10}' | grep -v -E " 8?5 " | sed -E "s@${1}p?@@" )"
# "1 256M c W95"
# "2 14.3G 83 Linux"
# "5 265G 83 Linux"
logItem "Partitions: $ap"
# now remove partition type info
local apr="$(cut -d ' ' -f 1-2,4- <<< "$ap")"
# "1 256M W95"
# "2 14.3G Linux"
# "5 265G Linux"
echo "$apr"
logExit "$apr"
}
function isPathMounted() { # dir
logEntry "$1"
local path
local rc=1
path=$1
while [[ "$path" != "" ]]; do
logItem "Path: $path"
if mountpoint -q "$path"; then
rc=0
break
fi
path=${path%/*}
done
logExit "$rc"
return $rc
}
function getStartStopCommands() { # listOfServicesToStop pcommandvarname scommandvarname
logEntry "$1"
IFS=" "
local startServices=( $1 )
logItem "Number of entries: ${#startServices[@]}"
local sc="" pc="" and=""
for s in "${startServices[@]}"; do
logItem "Processing $s"
pc="$pc $and systemctl stop $s"
sc="systemctl start $s $and $sc"
[[ -z $and ]] && and="&&"
done
#pc="systemctl stop $1"
#sc="systemctl start $1"
pc=$(sed -e 's/ \+/ /g' <<< $pc | xargs)
sc=$(sed -e 's/ \+/ /g' <<< $sc | xargs)
printf -v "${2}" "%s" "$pc"
printf -v "${3}" "%s" "$sc"
logItem "$2: $pc"
logItem "$3: $sc"
logExit
}
function parseConfig() {
logEntry
IFS="" matches=$(grep -E "DEFAULT_(MSG_LEVEL|KEEPBACKUPS|BACKUPPATH|BACKUPTYPE|ZIP_BACKUP|PARTITIONBASED_BACKUP|PARTITIONS_TO_BACKUP|LANGUAGE|STARTSERVICES|STOPSERVICES|EMAIL|MAIL_PROGRAM|SMART_RECYCLE|SMART_RECYCLE_DRYRUN|SMART_RECYCLE_OPTIONS|RESIZE_FS)=" "$CONFIG_ABS_FILE")
while IFS="=" read key value; do
key=${key//\"/}
key=${key/DEFAULT/CONFIG}
value=${value//\"/}
if [[ $key =~ .*SERVICES.* ]]; then
if [[ "$value" == "$IGNORE_START_STOP_CHAR" ]]; then
value=""
else
value=$(sed -e 's/start//g' -e 's/stop//g' -e 's/systemctl//g' -e 's/\&\&//g' -e 's/ \+/ /g' <<< "$value" | xargs )
fi
fi
logItem "$key=$value"
eval "$key=\"$value\""
if [[ $key == "CONFIG_LANGUAGE" ]]; then
[[ -z "$value" ]] && CONFIG_LANGUAGE="${LANG_SYSTEM^^}"
fi
done <<< "$matches"
logExit
}
function config_update_execute() {
logEntry
writeToConsole $MSG_UPDATING_CONFIG "$CONFIG_ABS_FILE"
logItem "Language: $CONFIG_LANGUAGE"
logItem "Mode: $CONFIG_PARTITIONBASED_BACKUP"
logItem "Partitions: $CONFIG_PARTITIONS_TO_BACKUP"
logItem "Type: $CONFIG_BACKUPTYPE"
logItem "Zip: $CONFIG_ZIP_BACKUP"
logItem "Keep: $CONFIG_KEEPBACKUPS"
logItem "Recycle: $CONFIG_SMART_RECYCLE"
logItem "Recycleoptions: $CONFIG_SMART_RECYCLE_OPTIONS"
logItem "Dryrun: $CONFIG_SMART_RECYCLE_DRYRUN"
logItem "Msglevel: $CONFIG_MSG_LEVEL"
logItem "Backuppath: $CONFIG_BACKUPPATH"
logItem "Stop: $CONFIG_STOPSERVICES"
logItem "Start: $CONFIG_STARTSERVICES"
logItem "eMail: $CONFIG_EMAIL"
logItem "mailProgram: $CONFIG_MAIL_PROGRAM"
logItem "Resize: $CONFIG_RESIZE_ROOTFS"
sed -i -E "s/^(#?\s?)?DEFAULT_LANGUAGE=.*\$/DEFAULT_LANGUAGE=\"$CONFIG_LANGUAGE\"/" "$CONFIG_ABS_FILE"
sed -i -E "s/^(#?\s?)?DEFAULT_PARTITIONBASED_BACKUP=.*\$/DEFAULT_PARTITIONBASED_BACKUP=\"$CONFIG_PARTITIONBASED_BACKUP\"/" "$CONFIG_ABS_FILE"
sed -i -E "s/^(#?\s?)?DEFAULT_PARTITIONS_TO_BACKUP=.*\$/DEFAULT_PARTITIONS_TO_BACKUP=\"$CONFIG_PARTITIONS_TO_BACKUP\"/" "$CONFIG_ABS_FILE"
sed -i -E "s/^(#?\s?)?DEFAULT_BACKUPTYPE=.*\$/DEFAULT_BACKUPTYPE=\"$CONFIG_BACKUPTYPE\"/" "$CONFIG_ABS_FILE"
sed -i -E "s/^(#?\s?)?DEFAULT_ZIP_BACKUP=.*\$/DEFAULT_ZIP_BACKUP=\"$CONFIG_ZIP_BACKUP\"/" "$CONFIG_ABS_FILE"
sed -i -E "s/^(#?\s?)?DEFAULT_KEEPBACKUPS=.*$/DEFAULT_KEEPBACKUPS=\"$CONFIG_KEEPBACKUPS\"/" "$CONFIG_ABS_FILE"
sed -i -E "s/^(#?\s?)?DEFAULT_SMART_RECYCLE=.*$/DEFAULT_SMART_RECYCLE=\"$CONFIG_SMART_RECYCLE\"/" "$CONFIG_ABS_FILE"
sed -i -E "s/^(#?\s?)?DEFAULT_SMART_RECYCLE_OPTIONS=.*$/DEFAULT_SMART_RECYCLE_OPTIONS=\"$CONFIG_SMART_RECYCLE_OPTIONS\"/" "$CONFIG_ABS_FILE"
sed -i -E "s/^(#?\s?)?DEFAULT_SMART_RECYCLE_DRYRUN=.*$/DEFAULT_SMART_RECYCLE_DRYRUN=\"$CONFIG_SMART_RECYCLE_DRYRUN\"/" "$CONFIG_ABS_FILE"
sed -i -E "s/^(#?\s?)?DEFAULT_MSG_LEVEL=.*$/DEFAULT_MSG_LEVEL=\"$CONFIG_MSG_LEVEL\"/" "$CONFIG_ABS_FILE"
sed -i -E "s/^(#?\s?)?DEFAULT_EMAIL=.*$/DEFAULT_EMAIL=\"$CONFIG_EMAIL\"/" "$CONFIG_ABS_FILE"
sed -i -E "s/^(#?\s?)?DEFAULT_MAIL_PROGRAM=.*$/DEFAULT_MAIL_PROGRAM=\"$CONFIG_MAIL_PROGRAM\"/" "$CONFIG_ABS_FILE"
local f=$(sed 's_/_\\/_g' <<< "$CONFIG_BACKUPPATH")
sed -i -E "s/^(#?\s?)?DEFAULT_BACKUPPATH=.*$/DEFAULT_BACKUPPATH=\"$f\"/" "$CONFIG_ABS_FILE"
local pline sline
if [[ "$CONFIG_STOPSERVICES" != "$IGNORE_START_STOP_CHAR" && -n "$CONFIG_STOPSERVICES" ]]; then
getStartStopCommands "$CONFIG_STOPSERVICES" "pline" "sline"
pline=$(sed 's/\&/\\\&/g' <<< "$pline")
sline=$(sed 's/\&/\\\&/g' <<< "$sline")
else
pline="$IGNORE_START_STOP_CHAR"
sline="$IGNORE_START_STOP_CHAR"
fi
logItem "pline: $pline"
logItem "sline: $sline"
sed -i -E "s/^(#?\s?)?DEFAULT_STOPSERVICES=.*$/DEFAULT_STOPSERVICES=\"$pline\"/" "$CONFIG_ABS_FILE"
sed -i -E "s/^(#?\s?)?DEFAULT_STARTSERVICES=.*$/DEFAULT_STARTSERVICES=\"$sline\"/" "$CONFIG_ABS_FILE"
logExit
}
function cron_update_execute() {
logEntry
writeToConsole $MSG_UPDATING_CRON "$CRON_ABS_FILE"
logItem "cron: $CONFIG_CRON_DAY $CONFIG_CRON_HOUR $CONFIG_CRON_MINUTE"
local l="$(tail -n 1 < $CRON_ABS_FILE)"
local disabled=""
if ! isCrontabEnabled; then
disabled="#"
fi
local cron_day="$(daynum_to_config_string "$CONFIG_CRON_DAY")"
local v=$(awk -v disabled=$disabled -v minute=$CONFIG_CRON_MINUTE -v hour=$CONFIG_CRON_HOUR -v day=$cron_day ' {print disabled minute, hour, $3, $4, day, $6, $7, $8}' <<< "$l")
logItem "cron update: $v"
local t=$(mktemp)
head -n -1 "$CRON_ABS_FILE" > $t
echo "$v" >> $t
mv $t $CRON_ABS_FILE
rm $t 2>/dev/null
logExit
}
function systemd_timer_execute() {
logEntry
logItem "Reload systemd daemon"
systemctl daemon-reload &>>$LOG_FILE
local enable=""
if isSystemdEnabled; then
enable="enable"
logItem "Starting $SYSTEMD_TIMER_FILE_NAME"
systemctl start $SYSTEMD_TIMER_FILE_NAME &>>$LOG_FILE
writeToConsole $MSG_SYSTEMD_ENABLED
else
enable="disable"
logItem "Stoping $SYSTEMD_TIMER_FILE_NAME"
systemctl stop $SYSTEMD_TIMER_FILE_NAME &>>$LOG_FILE
writeToConsole $MSG_SYSTEMD_DISABLED
fi
logItem "$enable $SYSTEMD_TIMER_FILE_NAME"
systemctl $enable $SYSTEMD_TIMER_FILE_NAME &>>$LOG_FILE
systemctl status $SYSTEMD_TIMER_FILE_NAME &>>$LOG_FILE
logExit
}
function systemd_update_execute() {
logEntry
writeToConsole $MSG_UPDATING_SYSTEMD "$SYSTEMD_TIMER_ABS_FILE"
logItem "systemd: $CONFIG_SYSTEMD_DAY $CONFIG_SYSTEMD_HOUR $CONFIG_SYSTEMD_MINUTE"
# OnCalendar=Sun *-*-* 05:00:42 # on sunday
# OnCalendar=*-*-* 05:00:42 # daily
local l="$(grep "^OnCalendar" $SYSTEMD_TIMER_ABS_FILE)"
local systemd_day="$(daynum_to_config_string "$CONFIG_SYSTEMD_DAY")"
logItem "Day: $systemd_day"
local v=$(awk -v minute=$CONFIG_SYSTEMD_MINUTE -v hour=$CONFIG_SYSTEMD_HOUR -v day=$systemd_day ' { print "OnCalendar="day "*-*-*", hour":"minute":42" }' <<< "$l")
logItem "systemd update: $v"
sed -i "/^OnCalendar/c$v" "$SYSTEMD_TIMER_ABS_FILE"
logItem "$(cat $SYSTEMD_TIMER_ABS_FILE)"
logExit
}
function cron_install_execute() {
logEntry
writeToConsole $MSG_INSTALLING_CRON_TEMPLATE "$CRON_ABS_FILE"
echo "$CRON_CONTENTS" >"$CRON_ABS_FILE"
if ! chmod 644 $CRON_ABS_FILE &>>$LOG_FILE; then
unrecoverableError $MSG_CHMOD_FAILED "$CRON_ABS_FILE"
logExit
return
fi
CRON_INSTALLED=1
if (( $MODE_FORCE_TIMER )); then
systemd_uninstall_execute
fi
logExit
}
function systemd_install_execute() {
logEntry
writeToConsole $MSG_INSTALLING_SYSTEMD_TEMPLATE "$SYSTEMD_SERVICE_ABS_FILE"
echo "$SYSTEMD_SERVICE" >"$SYSTEMD_SERVICE_ABS_FILE"
if ! chmod 755 $SYSTEMD_SERVICE_ABS_FILE &>>$LOG_FILE; then
unrecoverableError $MSG_CHMOD_FAILED "$SYSTEMD_SERVICE_ABS_FILE"
logExit
return
fi
writeToConsole $MSG_INSTALLING_SYSTEMD_TEMPLATE "$SYSTEMD_TIMER_ABS_FILE"
echo "$SYSTEMD_TIMER" >"$SYSTEMD_TIMER_ABS_FILE"
if ! chmod 755 $SYSTEMD_TIMER_ABS_FILE &>>$LOG_FILE; then
unrecoverableError $MSG_CHMOD_FAILED "$SYSTEMD_TIMER_ABS_FILE"
logExit
return
fi
SYSTEMD_INSTALLED=1
systemctl disable $SYSTEMD_TIMER_FILE_NAME &>>$LOG_FILE
systemctl status $SYSTEMD_TIMER_FILE_NAME &>>$LOG_FILE
if (( $MODE_FORCE_TIMER )); then
cron_uninstall_execute
fi
logExit
}
function timer_uninstall_execute() {
logEntry
cron_uninstall_execute
systemd_uninstall_execute
logExit
}
function cron_uninstall_execute() {
logEntry
if [[ -e "$CRON_ABS_FILE" ]]; then
writeToConsole $MSG_UNINSTALLING_CRON_TEMPLATE "$CRON_ABS_FILE"
if ! rm -f "$CRON_ABS_FILE" 2>>"$LOG_FILE"; then
unrecoverableError $MSG_UNINSTALL_FAILED "$CRON_ABS_FILE"
return
fi
fi
CRON_INSTALLED=0
logExit
}
function systemd_uninstall_execute() {
logEntry
local foundConfig
if [[ -e "$SYSTEMD_SERVICE_ABS_FILE" ]]; then
foundConfig=1
writeToConsole $MSG_UNINSTALLING_SYSTEMD_TEMPLATE "$SYSTEMD_SERVICE_ABS_FILE"
if ! rm -f "$SYSTEMD_SERVICE_ABS_FILE" 2>>"$LOG_FILE"; then
unrecoverableError $MSG_UNINSTALL_FAILED "$SYSTEMD_SERVICE_ABS_FILE"
return
fi
fi
if [[ -e "$SYSTEMD_TIMER_ABS_FILE" ]]; then
foundConfig=1
writeToConsole $MSG_UNINSTALLING_SYSTEMD_TEMPLATE "$SYSTEMD_TIMER_ABS_FILE"
if ! rm -f "$SYSTEMD_TIMER_ABS_FILE" 2>>"$LOG_FILE"; then
unrecoverableError $MSG_UNINSTALL_FAILED "$SYSTEMD_TIMER_ABS_FILE"
return
fi
fi
if (( $foundConfig )); then
if isSystemdEnabled; then
writeToConsole $MSG_SYSTEMD_DISABLED
logItem "Stopping $FILE_TO_INSTALL"
systemctl stop $FILE_TO_INSTALL &>>$LOG_FILE
logItem "Disable $FILE_TO_INSTALL"
systemctl disable $FILE_TO_INSTALL &>>$LOG_FILE
logItem "Relaod systemd daemon"
systemctl daemon-reload &>>$LOG_FILE
fi
fi
SYSTEMD_INSTALLED_INSTALLED=0
logExit
}
function config_uninstall_execute() {
logEntry
# all config files starting with raspiBackup
local pre=${CONFIG_ABS_FILE%%.*}
if ls $pre* &>/dev/null; then
writeToConsole $MSG_DELETE_FILE "$pre*"
if ! rm -f $pre* &>>"$LOG_FILE"; then
unrecoverableError $MSG_UNINSTALL_FAILED "$pre*"
return
fi
fi
logExit
}
function misc_uninstall_execute() {
logEntry
# tmp files
if ls /tmp/$RASPIBACKUP_NAME* &>/dev/null; then
writeToConsole $MSG_DELETE_FILE "/tmp/$RASPIBACKUP_NAME*"
if ! rm -f /tmp/$RASPIBACKUP_NAME* &>>"$LOG_FILE"; then
unrecoverableError $MSG_UNINSTALL_FAILED "/tmp/$RASPIBACKUP_NAME*"
return
fi
fi
# reminder status file
if ls $VAR_LIB_DIRECTORY/* &>/dev/null; then
writeToConsole $MSG_DELETE_FILE "$VAR_LIB_DIRECTORY/*"
if ! rm -f $VAR_LIB_DIRECTORY/* &>>"$LOG_FILE"; then
unrecoverableError $MSG_UNINSTALL_FAILED "$VAR_LIB_DIRECTORY/*"
return
fi
if [[ -d $VAR_LIB_DIRECTORY ]]; then
writeToConsole $MSG_DELETE_FILE "$VAR_LIB_DIRECTORY"
if ! rmdir $VAR_LIB_DIRECTORY &>>"$LOG_FILE"; then
unrecoverableError $MSG_UNINSTALL_FAILED "$VAR_LIB_DIRECTORY"
return
fi
fi
fi
logExit
}
function uninstall_script_execute() {
logEntry
pre=${FILE_TO_INSTALL_ABS_FILE%%.*}
post=${FILE_TO_INSTALL_ABS_FILE##*.}
if ls $pre.$post* &>/dev/null; then
writeToConsole $MSG_DELETE_FILE "$pre.$post*"
if ! rm -f $pre.$post* 2>>"$LOG_FILE"; then
unrecoverableError $MSG_UNINSTALL_FAILED "$pre.$post*"
return
fi
fi
if [[ -e "$FILE_TO_INSTALL_ABS_FILE" ]]; then
writeToConsole $MSG_DELETE_FILE "$FILE_TO_INSTALL_ABS_FILE"
if ! rm -f "$FILE_TO_INSTALL_ABS_FILE" 2>>$LOG_FILE; then
unrecoverableError $MSG_UNINSTALL_FAILED "$FILE_TO_INSTALL_ABS_FILE"
return
fi
fi
deleteSymLink "$FILE_TO_INSTALL_ABS_FILE"
INSTALLATION_SUCCESSFULL=0
logExit
}
function uninstall_execute() {
logEntry
if [[ -e "$FILE_TO_INSTALL_ABS_PATH/$MYSELF" ]]; then
writeToConsole $MSG_DELETE_FILE "$FILE_TO_INSTALL_ABS_PATH/$MYSELF"
if ! rm -f "$FILE_TO_INSTALL_ABS_PATH/$MYSELF" 2>>$LOG_FILE; then
unrecoverableError $MSG_UNINSTALL_FAILED "$FILE_TO_INSTALL_ABS_PATH/$MYSELF"
return
fi
deleteSymLink "$FILE_TO_INSTALL_ABS_PATH/$MYSELF"
if [[ -f "$LATEST_TEMP_PROPERTY_FILE" ]]; then
writeToConsole $MSG_DELETE_FILE "$LATEST_TEMP_PROPERTY_FILE"
rm -f "$LATEST_TEMP_PROPERTY_FILE" 2>>$LOG_FILE
fi
rm /tmp/${RASPIBACKUP_NAME}*.* 2>>$LOG_FILE
rm /${FILE_TO_INSTALL_ABS_PATH}/${RASPIBACKUP_NAME}*.* 2>>$LOG_FILE
writeToConsole $MSG_UNINSTALL_FINISHED "$RASPIBACKUP_NAME"
else
writeToConsole $MSG_NOT_INSTALLED "$RASPIBACKUP_NAME"
fi
INSTALLATION_SUCCESSFULL=0
logExit
}
# NOTE: make sure to return just after calling this function in order to terminate when first error occurs
function unrecoverableError() { # messagenumber messageparms
logEntry "$@"
if (( $PROGRESSBAR_DO )); then
logItem "Progressbar error occured $@"
echo "$@"
return
fi
clear
calc_wt_size
logStack
local tt="$(getMessageText $TITLE_ERROR)"
local d="$(getMessageText $DESCRIPTION_ERROR)"
local id="$1"
shift
logItem "Id: $id"
logItem "Msg: $@"
if (( $MODE_UNATTENDED )); then
echo
d="$(getMessageText $id $@ )${NL}${NL}$d"
logItem "$d"
echo "$d"
else
local m="$(getMessageText $id $@ )${NL}${NL}$d"
logItem "$m"
local t=$(center $(($WINDOW_COLS * 2)) "$m")
whiptail --msgbox "$t" --title "$tt" $ROWS_MSGBOX $(($WINDOW_COLS * 2)) 1
fi
logExit
exit 1
}
function calc_wt_size() {
# NOTE: it's tempting to redirect stderr to /dev/null, so supress error
# output from tput. However in this case, tput detects neither stdout or
# stderr is a tty and so only gives default 80, 24 values
WT_HEIGHT=20
WT_WIDTH=$(tput cols)
if [ -z "$WT_WIDTH" ] || [ "$WT_WIDTH" -lt 60 ]; then
WT_WIDTH=80
fi
if [ "$WT_WIDTH" -gt 178 ]; then
WT_WIDTH=120
fi
#WT_HEIGHT=0
#WT_WIDTH=0
WT_MENU_HEIGHT=$(($WT_HEIGHT - 7))
#WT_MENU_HEIGHT=13
}
function testIfServicesExist() { # list of services
logEntry "$1"
IFS=" "
local services=( $1 )
local fails=""
for s in ${services[@]}; do
if ! systemd-analyze verify $s.service &>/dev/null; then
[[ -n "$fails" ]] && fails+=","
fails+="$s"
fi
done
echo "$fails"
logExit "$fails"
}
function extractVersionFromFile() { # fileName type (VERSION|VERSION_CONFIG)
local v="$(grep -E "^$2=" "$1" | cut -f 2 -d = | sed -e 's/[[:space:]]*#.*$//g' -e 's/\"//g')"
[[ -z "$v" ]] && v="0.0.0.0"
echo "$v"
}
function about_do() {
logEntry
if [[ -f $FILE_TO_INSTALL_ABS_FILE ]]; then
local RASPI_GIT_DATE="$(grep "^GIT_DATE=" $FILE_TO_INSTALL_ABS_FILE)"
local RASPI_GIT_DATE_ONLY="${RASPI_GIT_DATE/: /}"
local RASPI_GIT_DATE_ONLY="$(cut -f 2 -d ' ' <<< "$RASPI_GIT_DATE")"
local RASPI_GIT_TIME_ONLY="$(cut -f 3 -d ' ' <<< "$RASPI_GIT_DATE")"
local RASPI_GIT_COMMIT="$(grep "^GIT_COMMIT=" $FILE_TO_INSTALL_ABS_FILE)"
local RASPI_GIT_COMMIT_ONLY="$(cut -f 2 -d ' ' <<< "$RASPI_GIT_COMMIT" | sed 's/\$//' | sed "s/'//" )"
local RASPI_VERSION="$(extractVersionFromFile $FILE_TO_INSTALL_ABS_FILE VERSION)"
local RASPI_GIT_CODEVERSION="$FILE_TO_INSTALL $RASPI_VERSION, $RASPI_GIT_DATE_ONLY/$RASPI_GIT_TIME_ONLY - $RASPI_GIT_COMMIT_ONLY"
fi
local a="$(getMessageText $MSG_ABOUT "$RASPI_GIT_CODEVERSION")"
local t=$(center $(($WINDOW_COLS * 2)) "$a")
whiptail --msgbox "$t" --title "About" $ROWS_ABOUT $(($WINDOW_COLS * 2)) 1
logExit
}
function navigation_do() {
local a="$(getMessageText $MSG_NAVIGATION)"
local t=$(center $(($WINDOW_COLS * 2)) "$a")
whiptail --msgbox "$t" --title "Navigation" $ROWS_ABOUT $(($WINDOW_COLS * 2)) 1
}
function do_finish() {
logEntry
(( RASPIBACKUP_INSTALL_DEBUG )) && exit 0
if isRaspiBackupInstalled ; then
if ! isStartStopDefined; then
local m="$(getMessageText $MSG_QUESTION_IGNORE_MISSING_STARTSTOP)"
local y="$(getMessageText $BUTTON_YES)"
local n="$(getMessageText $BUTTON_NO)"
local t=$(center $WINDOW_COLS "$m")
local tt="$(getMessageText $TITLE_WARNING)"
if ! whiptail --yesno "$t" --title "$tt" --yes-button "$y" --no-button "$n" --defaultno $ROWS_MSGBOX $WINDOW_COLS 1 3>&1 1>&2 2>&3; then
return
fi
fi
if (( $INSTALLATION_SUCCESSFULL )); then
first_steps
fi
help
reset
fi
logExit
exit 0
}
function help() {
local a="$(getMessageText $MSG_HELP)"
local t=$(center $(($WINDOW_COLS * 2)) "$a")
local tt="$(getMessageText $TITLE_HELP)"
whiptail --msgbox "$t" --title "$tt" $ROWS_ABOUT $(($WINDOW_COLS * 2)) 1
}
function trapWithArg() { # function trap1 trap2 ... trapn
local func="$1"
shift
for sig; do
trap "$func $sig" "$sig"
done
}
function cleanup() {
logEntry
trap '' SIGINT SIGTERM EXIT
local rc=$?
local signal="$1"
logItem "Signal: $signal"
logItem "rc: $rc"
TAIL=0
if (($INSTALLATION_STARTED)); then
if ((!$INSTALLATION_SUCCESSFULL)); then
writeToConsole $MSG_CLEANUP
(($CONFIG_INSTALLED)) && rm $CONFIG_ABS_FILE &>>"$LOG_FILE" || true
(($SCRIPT_INSTALLED)) && rm $FILE_TO_INSTALL_ABS_FILE &>>"$LOG_FILE" || true
(($CRON_INSTALLED)) && rm $CRON_ABS_FILE &>>"$LOG_FILE" || true
if (($SYSTEMD_INSTALLED)); then
rm $SYSTEMD_SERVICE_ABS_FILE &>>"$LOG_FILE" || true
rm $SYSTEMD_TIMER_ABS_FILE &>>"$LOG_FILE" || true
fi
(($EXTENSIONS_INSTALLED)) && rm -f $FILE_TO_INSTALL_ABS_PATH/${RASPIBACKUP_NAME}_*.sh &>>"$LOG_FILE" || true
fi
fi
(($EXTENSIONS_INSTALLED)) && rm $SAMPLEEXTENSION_TAR_FILE &>>$LOG_FILE || true
masqueradeSensitiveInfoInLog # and masquerade sensitive details in log file
if [[ "$signal" != "EXIT" ]]; then
writeToConsole $MSG_INSTALLATION_FAILED "$RASPIBACKUP_NAME" "$LOG_FILE"
logExit
rc=127
fi
chown "$CALLING_USER:$CALLING_USER" "$LOG_FILE" &> $LOG_FILE
exit $rc
}
function config_menu() {
logEntry
if ! isConfigInstalled; then
local t=$(center $WINDOW_COLS "No $RASPIBACKUP_NAME configuration found.")
local tt="$(getMessageText $TITLE_INFORMATION)"
whiptail --msgbox "$t" --title "$tt" $ROWS_MSGBOX $WINDOW_COLS 2
logExit
return
fi
CONFIG_UPDATED=0
TIMER_UPDATED=0
if isConfigInstalled; then
parseConfig
fi
if isCrontabConfigInstalled; then
local l="$(tail -n 1 < $CRON_ABS_FILE)"
logItem "last line: $l"
local v=$(awk ' {print $1, $2, $5}' <<< "$l")
logItem "parsed $v"
CONFIG_CRON_MINUTE="$(cut -f 1 -d ' ' <<< $v)"
[[ ${CONFIG_CRON_MINUTE:0:1} == "#" ]] && CONFIG_CRON_MINUTE="${CONFIG_CRON_MINUTE:1}"
CONFIG_CRON_HOUR="$(cut -f 2 -d ' ' <<< $v)"
local day=$(cut -f 3 -d ' ' <<< $v)
CONFIG_CRON_DAY=$(daynum_from_config_string "$day")
logItem "parsed hour: $CONFIG_CRON_HOUR"
logItem "parsed minute: $CONFIG_CRON_MINUTE"
logItem "parsed day: $CONFIG_CRON_DAY"
elif isSystemdConfigInstalled; then
# OnCalendar=Sun *-*-* 05:00:00
# OnCalendar= *-*-* 05:00:00
local l="$(grep "^OnCalendar" $SYSTEMD_TIMER_ABS_FILE | cut -f 2 -d "=")" # Sun *-*-* 05:00:00 or *-*-* 05:00:00
logItem "parsed $l"
local day="$(cut -f 1 -d ' ' <<< $l)" # Sun or *-*-*
logItem "day: $day"
local t="$(cut -f 3 -d " " <<< $l)" # 05:00:00 or empty
logItem "parsed time $t"
if [[ -z "$t" ]]; then
t="$(cut -f 2 -d " " <<< $l)" # 05:00:00
day=""
fi
logItem "parsed time $t"
CONFIG_SYSTEMD_DAY="$(daynum_from_config_string "$day")"
CONFIG_SYSTEMD_HOUR="$(cut -f 1 -d ':' <<< $t)" # 05
CONFIG_SYSTEMD_MINUTE="$(cut -f 2 -d ':' <<< $t)" # 00
logItem "parsed hour: $CONFIG_SYSTEMD_HOUR"
logItem "parsed minute: $CONFIG_SYSTEMD_MINUTE"
logItem "parsed day: $CONFIG_SYSTEMD_DAY"
fi
while :; do
local b1="$(getMessageText $BUTTON_BACK)"
local sel1="$(getMessageText $BUTTON_SELECT)"
local y="$(getMessageText $BUTTON_YES)"
local n="$(getMessageText $BUTTON_NO)"
getMenuText $MENU_LANGUAGE m1
getMenuText $MENU_CONFIG_BACKUPPATH m2
getMenuText $MENU_CONFIG_BACKUPS m3
getMenuText $MENU_CONFIG_TYPE m4
getMenuText $MENU_CONFIG_MODE m5
getMenuText $MENU_CONFIG_SERVICES m6
getMenuText $MENU_CONFIG_MESSAGE m7
getMenuText $MENU_CONFIG_EMAIL m8
getMenuText $MENU_CONFIG_REGULAR m9
local p="${m1[0]}"
m1[0]="C${p:1}"
local s1="${m1[0]}"
local s2="${m2[0]}"
local s3="${m3[0]}"
local s4="${m4[0]}"
local s5="${m5[0]}"
local s6="${m6[0]}"
local s7="${m7[0]}"
local s8="${m8[0]}"
local s9="${m9[0]}"
local mx=( \
"${m1[@]}" \
"${m2[@]}" \
"${m3[@]}" \
"${m4[@]}" \
"${m5[@]}" \
"${m6[@]}" \
"${m7[@]}" \
"${m8[@]}" \
"${m9[@]}" \
)
if [[ $CONFIG_BACKUPTYPE == "dd" || $CONFIG_BACKUPTYPE == "tar" ]]; then
getMenuText $MENU_CONFIG_ZIP mcp
local scp="${mcp[0]}"
mx+=("${mcp[@]}")
else
local scp=""
fi
getMenuText $MENU_CONFIGURE tt
FUN=$(whiptail --title "${tt[1]}" --menu "" $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT --cancel-button "$b1" --ok-button "$sel1" \
"${mx[@]}" \
3>&1 1>&2 2>&3)
RET=$?
if [ $RET -eq 1 ]; then
if (($CONFIG_UPDATED)); then
local m="$(getMessageText $MSG_QUESTION_UPDATE_CONFIG)"
local t=$(center $WINDOW_COLS "$m")
local ttm="$(getMessageText $TITLE_CONFIRM)"
if whiptail --yesno "$t" --title "$ttm" --yes-button "$y" --no-button "$n" --defaultno $ROWS_MSGBOX $WINDOW_COLS 1 3>&1 1>&2 2>&3; then
config_update_do
fi
fi
if (($TIMER_UPDATED)); then
local m
if isCrontabConfigInstalled; then
m="$(getMessageText $MSG_QUESTION_UPDATE_CRON)"
else
m="$(getMessageText $MSG_QUESTION_UPDATE_SYSTEMD)"
fi
local t=$(center $WINDOW_COLS "$m")
local ttm="$(getMessageText $TITLE_CONFIRM)"
if whiptail --yesno "$t" --title "$ttm" --yes-button "$y" --no-button "$n" --defaultno $ROWS_MSGBOX $WINDOW_COLS 1 3>&1 1>&2 2>&3; then
timer_update_do
fi
fi
logExit
return 0
elif [ $RET -eq 0 ]; then
logItem "$FUN"
case "$FUN" in
$s1) config_language_do; CONFIG_UPDATED=$(( CONFIG_UPDATED|$? )) ;;
$s2) config_backuppath_do; CONFIG_UPDATED=$(( CONFIG_UPDATED|$? )) ;;
$s3) config_keep_selection_do; CONFIG_UPDATED=$(( CONFIG_UPDATED|$? )) ;;
$s4) config_backuptype_do; CONFIG_UPDATED=$(( CONFIG_UPDATED|$? )) ;;
$s5) config_backupmode_do; CONFIG_UPDATED=$(( CONFIG_UPDATED|$? )) ;;
$s6) config_services_do; CONFIG_UPDATED=$(( CONFIG_UPDATED|$? )) ;;
$s7) config_message_detail_do; CONFIG_UPDATED=$(( CONFIG_UPDATED|$? )) ;;
$s8) config_email_do; CONFIG_UPDATED=$(( CONFIG_UPDATED|$? )) ;;
$s9) config_timer_menu; TIMER_UPDATED=$? ;;
$scp) config_compress_do; CONFIG_UPDATED=$(( CONFIG_UPDATED|$? )) ;;
\ *) : ;;
*) whiptail --msgbox "Programm error: unrecognized option $FUN" $ROWS_MENU $WINDOW_COLS 1 ;;
esac || whiptail --msgbox "There was an error running option $FUN" $ROWS_MENU $WINDOW_COLS 1
fi
done
logExit
}
function config_keep_selection_do() {
logEntry "$CONFIG_SMART_RECYCLE"
local smart_mode=off
local keep_mode=off
local old="$CONFIG_SMART_RECYCLE"
local rc
case "$CONFIG_SMART_RECYCLE" in
0) keep_mode=on ;;
1) smart_mode=on ;;
*) whiptail --msgbox "Programm error, unrecognized smart mode $CONFIG_SMART_RECYCLE" $ROWS_MENU $WINDOW_COLS 2
logExit
return 1
;;
esac
getMenuText $MENU_CONFIG_MODE_KEEP m1
getMenuText $MENU_CONFIG_MODE_SMART m2
local s1="${m1[0]}"
local s2="${m2[0]}"
getMenuText $MENU_CONFIG_BACKUPS tt
local o1="$(getMessageText $BUTTON_OK)"
local c1="$(getMessageText $BUTTON_CANCEL)"
local d="$(getMessageText $DESCRIPTION_SMARTMODE)"
local updated=0
ANSWER=$(whiptail --notags --radiolist "$d" --title "${tt[1]}" --ok-button "$o1" --cancel-button "$c1" $ROWS_MENU $WINDOW_COLS 2 \
"${m1[@]}" $keep_mode \
"${m2[@]}" $smart_mode \
3>&1 1>&2 2>&3)
if [ $? -eq 0 ]; then
logItem "Answer: $ANSWER"
case "$ANSWER" in
$s1) logItem "$s1"
config_keep_do 0
updated=$?
;;
$s2) logItem "$s2"
config_keep_do 1
updated=$?
;;
*) whiptail --msgbox "Programm error, unrecognized smart mode $ANSWER" $ROWS_MENU $WINDOW_COLS 2
logExit 1
return 1
;;
esac
fi
[[ "$old" == "$CONFIG_SMART_RECYCLE" ]] && (( $updated == 0 ))
rc=$?
logExit $rc
return $rc
}
function config_keep_do() { # smartRecycle
logEntry $1
local isSmartRecycle=$1
local current
while :; do
local error=0
if (( $isSmartRecycle )); then
current="$CONFIG_SMART_RECYCLE_OPTIONS"
else
current="$CONFIG_KEEPBACKUPS"
fi
getMenuText $MENU_CONFIG_BACKUPS tt
local c1="$(getMessageText $BUTTON_CANCEL)"
local o1="$(getMessageText $BUTTON_OK)"
local d
if (( $isSmartRecycle )); then
d="$(getMessageText $DESCRIPTION_SMART)"
else
d="$(getMessageText $DESCRIPTION_KEEP)"
fi
ANSWER=$(whiptail --inputbox "$d" --title "${tt[1]}" $ROWS_MENU $WINDOW_COLS "$current" --ok-button "$o1" --cancel-button "$c1" 3>&1 1>&2 2>&3)
if [ $? -eq 0 ]; then
logItem "Answer: $ANSWER"
IFS=$DEFAULT_IFS
local srNumbers=( $ANSWER )
local srNumberCount=${#srNumbers[@]}
local n
if (( $srNumberCount == 4 || $srNumberCount == 1 )); then
for n in ${srNumbers[@]}; do
if [[ ! "$n" =~ ^[0-9]+$ ]]; then
local m
if (( $isSmartRecycle )); then
m="$(getMessageText $MSG_INVALID_SMART "$n")"
else
m="$(getMessageText $MSG_INVALID_KEEP "$n")"
fi
local t=$(center $WINDOW_COLS "$m")
local ttm="$(getMessageText $TITLE_VALIDATIONERROR)"
whiptail --msgbox "$t" --title "$ttm" $ROWS_MENU $WINDOW_COLS 2
error=1
break
fi
done
else
local m
if (( $isSmartRecycle )); then
m="$(getMessageText $MSG_INVALID_SMART_NUMBER_COUNT)"
else
m="$(getMessageText $MSG_INVALID_KEEP_NUMBER_COUNT)"
fi
local t=$(center $WINDOW_COLS "$m")
local ttm="$(getMessageText $TITLE_VALIDATIONERROR)"
whiptail --msgbox "$t" --title "$ttm" $ROWS_MENU $WINDOW_COLS 2
error=1
fi
if (( ! $error )); then
if (( $isSmartRecycle )); then # smart recycle
local old="$CONFIG_SMART_RECYCLE_OPTIONS"
CONFIG_SMART_RECYCLE_OPTIONS="$ANSWER"
CONFIG_SMART_RECYCLE_DRYRUN="0"
CONFIG_SMART_RECYCLE="1"
isSmartRecycle=1
else # normal keep
local old="$CONFIG_KEEPBACKUPS"
CONFIG_KEEPBACKUPS="$ANSWER"
CONFIG_SMART_RECYCLE_OPTIONS="$DEFAULT_CONFIG_SMART_RECYCLE_OPTIONS"
CONFIG_SMART_RECYCLE_DRYRUN="$DEFAULT_CONFIG_SMART_RECYCLE_DRYRUN"
CONFIG_SMART_RECYCLE="$DEFAULT_CONFIG_SMART_RECYCLE"
isSmartRecycle=0
fi
break
fi
else
logExit "aborted"
return 0
fi
done
logItem "isSmartRecycle: $isSmartRecycle"
logItem "CONFIG_KEEPBACKUPS: $CONFIG_KEEPBACKUPS"
logItem "CONFIG_SMART_RECYCLE_OPTIONS: $CONFIG_SMART_RECYCLE_OPTIONS"
logItem "CONFIG_SMART_RECYCLE: $CONFIG_SMART_RECYCLE"
logItem "CONFIG_SMART_RECYCLE_DRYRUN: $CONFIG_SMART_RECYCLE_DRYRUN"
( (( ! $isSmartRecycle )) && [[ "$old" == "$CONFIG_KEEPBACKUPS" ]] ) || ( (( $isSmartRecycle )) && [[ "$old" == "$CONFIG_SMART_RECYCLE_OPTIONS" ]] )
local rc=$?
if (( $isSmartRecycle )); then
logExit "$rc - $CONFIG_SMART_RECYCLE"
else
logExit "$rc - $CONFIG_KEEPBACKUPS"
fi
return $rc
}
function config_backuppath_do() {
logEntry
local current="$CONFIG_BACKUPPATH"
local old="$current"
while :; do
getMenuText $MENU_CONFIG_BACKUPPATH tt
local c1="$(getMessageText $BUTTON_CANCEL)"
local o1="$(getMessageText $BUTTON_OK)"
local d="$(getMessageText $DESCRIPTION_BACKUPPATH)"
ANSWER=$(whiptail --inputbox "$d" --title "${tt[1]}" $ROWS_MENU $WINDOW_COLS "$current" --ok-button "$o1" --cancel-button "$c1" 3>&1 1>&2 2>&3)
if [ $? -eq 0 ]; then
logItem "Answer: $ANSWER"
current="$ANSWER"
if [[ -z "$ANSWER" || ! -d "$ANSWER" ]]; then
local m="$(getMessageText $MSG_INVALID_BACKUPPATH "$ANSWER")"
local t=$(center $WINDOW_COLS "$m")
local ttm="$(getMessageText $TITLE_VALIDATIONERROR)"
whiptail --msgbox "$t" --title "$ttm" $ROWS_MENU $WINDOW_COLS 2
elif ! isPathMounted "$ANSWER"; then
local m="$(getMessageText $MSG_LOCAL_BACKUPPATH "$ANSWER")"
local t=$(center $WINDOW_COLS "$m")
local ttm="$(getMessageText $TITLE_VALIDATIONERROR)"
whiptail --msgbox "$t" --title "$ttm" $ROWS_MENU $WINDOW_COLS 2
else
CONFIG_BACKUPPATH="$ANSWER"
break
fi
else
break
fi
done
[[ "$old" == "$CONFIG_BACKUPPATH" ]]
local rc=$?
logExit "$rc -$CONFIG_BACKUPPATH"
return $rc
}
function config_time_do() {
logEntry
local rc
if (( $USE_SYSTEMD )); then
config_systemdtime_do
else
config_crontime_do
fi
rc=$?
logExit $rc
return $rc
}
function config_crontime_do() {
local old=$(printf "%02d:%02d" $CONFIG_CRON_HOUR $CONFIG_CRON_MINUTE)
current="$old"
logEntry "$old"
local b1="$(getMessageText $SELECT_TIME)"
local c1="$(getMessageText $BUTTON_CANCEL)"
local o1="$(getMessageText $BUTTON_OK)"
getMenuText $MENU_CONFIG_TIME tt
while :; do
ANSWER=$(whiptail --inputbox "$b" --title "${tt[1]}" $ROWS_MENU $WINDOW_COLS --ok-button "$o1" --cancel-button "$c1" "$current" $ROWS_MENU $WINDOW_COLS 2 3>&1 1>&2 2>&3)
if [ $? -eq 0 ]; then
logItem "Answer: $ANSWER"
current="$ANSWER"
if [[ ! "$ANSWER" =~ ^[0-9]{1,2}:[0-9]{1,2}$ ]]; then
local m="$(getMessageText $MSG_INVALID_TIME "$ANSWER")"
local t=$(center $WINDOW_COLS "$m")
local ttm="$(getMessageText $TITLE_VALIDATIONERROR)"
whiptail --msgbox "$t" --title "$ttm" $ROWS_MENU $WINDOW_COLS 2
else
CONFIG_CRON_HOUR=$(cut -f1 -d: <<< "$ANSWER")
CONFIG_CRON_MINUTE=$(cut -f2 -d: <<< "$ANSWER")
if (( CONFIG_CRON_HOUR > 23 || CONFIG_CRON_MINUTE > 59 )); then
local m="$(getMessageText $MSG_INVALID_TIME "$ANSWER")"
local t=$(center $WINDOW_COLS "$m")
local ttm="$(getMessageText $TITLE_VALIDATIONERROR)"
whiptail --msgbox "$t" --title "$ttm" $ROWS_MENU $WINDOW_COLS 2
else
logItem "hour: $CONFIG_CRON_HOUR minute: $CONFIG_CRON_MINUTE"
break
fi
fi
else
break
fi
done
[[ "$old" == "$CONFIG_CRON_HOUR:$CONFIG_CRON_MINUTE" ]]
local rc=$?
logExit "$rc - $CONFIG_CRON_HOUR:$CONFIG_CRON_MINUTE"
return $rc
}
function config_systemdtime_do() {
local old=$(printf "%02d:%02d" $CONFIG_SYSTEMD_HOUR $CONFIG_SYSTEMD_MINUTE)
current="$old"
logEntry "$old"
local b1="$(getMessageText $SELECT_TIME)"
local c1="$(getMessageText $BUTTON_CANCEL)"
local o1="$(getMessageText $BUTTON_OK)"
getMenuText $MENU_CONFIG_TIME tt
while :; do
ANSWER=$(whiptail --inputbox "$b" --title "${tt[1]}" $ROWS_MENU $WINDOW_COLS --ok-button "$o1" --cancel-button "$c1" "$current" $ROWS_MENU $WINDOW_COLS 2 3>&1 1>&2 2>&3)
if [ $? -eq 0 ]; then
logItem "Answer: $ANSWER"
current="$ANSWER"
if [[ ! "$ANSWER" =~ ^[0-9]{1,2}:[0-9]{1,2}$ ]]; then
local m="$(getMessageText $MSG_INVALID_TIME "$ANSWER")"
local t=$(center $WINDOW_COLS "$m")
local ttm="$(getMessageText $TITLE_VALIDATIONERROR)"
whiptail --msgbox "$t" --title "$ttm" $ROWS_MENU $WINDOW_COLS 2
else
CONFIG_SYSTEMD_HOUR=$(cut -f1 -d: <<< "$ANSWER")
CONFIG_SYSTEMD_MINUTE=$(cut -f2 -d: <<< "$ANSWER")
if (( CONFIG_SYSTEMD_HOUR > 23 || CONFIG_SYSTEMD_MINUTE > 59 )); then
local m="$(getMessageText $MSG_INVALID_TIME "$ANSWER")"
local t=$(center $WINDOW_COLS "$m")
local ttm="$(getMessageText $TITLE_VALIDATIONERROR)"
whiptail --msgbox "$t" --title "$ttm" $ROWS_MENU $WINDOW_COLS 2
else
logItem "hour: $CONFIG_SYSTEMD_HOUR minute: $CONFIG_SYSTEMD_MINUTE"
break
fi
fi
else
break
fi
done
[[ "$old" == "$CONFIG_SYSTEMD_HOUR:$CONFIG_SYSTEMD_MINUTE" ]]
local rc=$?
logExit "$rc - $CONFIG_SYSTEMD_HOUR:$CONFIG_SYSTEMD_MINUTE"
return $rc
}
function config_email_do() {
getMenuText $MENU_CONFIG_EMAIL tt
c1="$(getMessageText $BUTTON_CANCEL)"
o1="$(getMessageText $BUTTON_OK)"
local current="$CONFIG_EMAIL"
local oldeMail="$current"
local d="$(getMessageText $DESCRIPTION_EMAIL)"
while :; do
ANSWER=$(whiptail --inputbox "$d" --title "${tt[1]}" $ROWS_MENU $WINDOW_COLS "$current" --ok-button "$o1" --cancel-button "$c1" 3>&1 1>&2 2>&3)
if [ $? -eq 0 ]; then
logItem "Answer: $ANSWER"
current="$ANSWER"
if [[ -n "$current" ]]; then
if ! [[ "$current" =~ ^[a-zA-Z0-9_.+-]+\@[a-zA-Z0-9-]+\.[a-zA-Z0-9.-]+$ ]]; then
local m="$(getMessageText $MSG_INVALID_EMAIL "$current")"
local t=$(center $WINDOW_COLS "$m")
local ttm="$(getMessageText $TITLE_VALIDATIONERROR)"
whiptail --msgbox "$t" --title "$ttm" $ROWS_MENU $WINDOW_COLS 2
else
CONFIG_EMAIL="$ANSWER"
break
fi
else
CONFIG_EMAIL="$ANSWER"
break
fi
else
logExit
return 0
fi
done
logItem "eMail: $CONFIG_EMAIL"
if [[ -z $CONFIG_EMAIL ]]; then
[[ "$oldeMail" == "$CONFIG_EMAIL" ]]
local rc=$?
logExit "$rc"
return $rc
fi
local mail_=off
local ssmtp_=off
local msmtp_=off
local old="$CONFIG_MAIL_PROGRAM"
logEntry "$old"
getMenuText $MENU_CONFIG_MAIL_MAIL m1
getMenuText $MENU_CONFIG_MAIL_SSMTP m2
getMenuText $MENU_CONFIG_MAIL_MSMTP m3
local s1="${m1[0]}"
local s2="${m2[0]}"
local s3="${m3[0]}"
local o1="$(getMessageText $BUTTON_OK)"
local c1="$(getMessageText $BUTTON_CANCEL)"
case "$CONFIG_MAIL_PROGRAM" in
mail) mail_=on ;;
ssmtp) ssmtp_=on ;;
msmtp) msmtp_=on ;;
esac
local d="$(getMessageText $DESCRIPTION_MAIL_PROGRAM)"
ANSWER=$(whiptail --radiolist "$d" --title "${tt[1]}" --ok-button "$o1" --cancel-button "$c1" $WT_HEIGHT $WT_WIDTH 3 \
"${m1[@]}" "$mail_" \
"${m2[@]}" "$ssmtp_" \
"${m3[@]}" "$msmtp_" \
3>&1 1>&2 2>&3)
if [ $? -eq 0 ]; then
logItem "Answer: $ANSWER"
case "$ANSWER" in
$s3) CONFIG_MAIL_PROGRAM="msmtp" ;;
$s2) CONFIG_MAIL_PROGRAM="ssmtp" ;;
$s1) CONFIG_MAIL_PROGRAM="mail" ;;
*) whiptail --msgbox "Programm error, unrecognized backup type" $ROWS_MENU $WINDOW_COLS 2
logExit
return 1 ;;
esac
fi
[[ "$old" == "$CONFIG_MAIL_PROGRAM" ]] && [[ "$oldeMail" == "$CONFIG_EMAIL" ]]
local rc=$?
logExit "$rc - $old:$CONFIG_MAIL_PROGRAM $oldeMail:$CONFIG_EMAIL"
return $rc
}
function config_backuptype_do() {
local dd_=off
local tar_=off
local rsync_=off
local old="$CONFIG_BACKUPTYPE"
logEntry "$old"
getMenuText $MENU_CONFIG_TYPE_RSYNC m1
getMenuText $MENU_CONFIG_TYPE_TAR m2
getMenuText $MENU_CONFIG_TYPE_DD m3
local s1="${m1[0]}"
local s2="${m2[0]}"
local s3="${m3[0]}"
local o1="$(getMessageText $BUTTON_OK)"
local c1="$(getMessageText $BUTTON_CANCEL)"
case "$CONFIG_BACKUPTYPE" in
dd) dd_=on ;;
tar) tar_=on ;;
rsync) rsync_=on ;;
esac
getMenuText $MENU_CONFIG_TYPE tt
logItem "$b1"
logItem "$t"
local c1="$(getMessageText $BUTTON_CANCEL)"
local o1="$(getMessageText $BUTTON_OK)"
local d="$(getMessageText $DESCRIPTION_BACKUPTYPE)"
ANSWER=$(whiptail --notags --radiolist "$d" --title "${tt[1]}" --ok-button "$o1" --cancel-button "$c1" $WT_HEIGHT $WT_WIDTH 3 \
"${m1[@]}" "$rsync_" \
"${m2[@]}" "$tar_" \
"${m3[@]}" "$dd_" \
3>&1 1>&2 2>&3)
if [ $? -eq 0 ]; then
logItem "Answer: $ANSWER"
case "$ANSWER" in
$s3) CONFIG_BACKUPTYPE="dd" ;;
$s2) CONFIG_BACKUPTYPE="tar" ;;
$s1) CONFIG_BACKUPTYPE="rsync"
CONFIG_ZIP_BACKUP=0 ;;
"") : ;;
*) whiptail --msgbox "Programm error, unrecognized backup type" $ROWS_MENU $WINDOW_COLS 2
logExit
return 1 ;;
esac
fi
[[ "$old" == "$CONFIG_BACKUPTYPE" ]]
local rc=$?
logExit "$rc - $CONFIG_BACKUPTYPE"
return $rc
}
function config_services_do() {
local current="$CONFIG_STOPSERVICES"
local old="$current"
logEntry "$current"
wtv=$(whiptail -v | cut -d " " -f 3)
IFS=" "
local as=( $(getActiveServices) ) # sorted alphabetically
local state
logItem "Active services: ${as[*]}"
getMenuText $MENU_CONFIG_SERVICES tt
logItem "INCLUDE_SERVICES_REGEX: "${INCLUDE_SERVICES_REGEX[@]}""
local ci=() # list of included servcices
local cu=() # unselected services
local css=( ${CONFIG_STOPSERVICES[*]} ) # already configured services
local srvc
for srvc in ${as[@]}; do
if grep -q -i "$INCLUDE_SERVICES_REGEX" <<< "$srvc"; then # service should be included
ci+=( "$srvc" )
elif containsElement "$srvc" "${css[@]}"; then
ci+=( "$srvc" ) # service was already configured to be included
else
cu+=( "$srvc" ) # service was not included
fi
done
local oldIFS="$IFS"
IFS=$'\n' sorted=($(sort <<<"${ci[*]}")) # sort list of included services
IFS="$oldIFS"
ci+=( ${cu[@]} ) # append unselected sevices (already sorted)
# now build whiptail list, selected services first followed by unselected services
local c=()
for s in ${ci[@]}; do
if containsElement "$s" "${cu[@]}"; then
if [[ "$wtv" < "0.52.19" ]]; then # workaround for whiptail issue in 0.52.19
c+=("$s" "" "off")
else
c+=("$s" "$s" "off")
fi
else
if [[ "$wtv" < "0.52.19" ]]; then # workaround for whiptail issue in 0.52.19
c+=("$s" "" "on")
else
c+=("$s" "$s" "on")
fi
fi
done
local d="$(getMessageText $DESCRIPTION_STARTSTOP_SERVICES)"
local c1="$(getMessageText $BUTTON_CANCEL)"
local o1="$(getMessageText $BUTTON_OK)"
ANSWER=$(whiptail --notags --checklist "$d" --title "${tt[1]}" --ok-button "$o1" --cancel-button "$c1" $WT_HEIGHT $(($WT_WIDTH/2)) 7 \
"${c[@]}" \
3>&1 1>&2 2>&3)
if [ $? -eq 0 ]; then
logItem "Answer: $ANSWER"
local current=${ANSWER//\"}
CONFIG_STOPSERVICES="$current"
if [[ -n $CONFIG_STOPSERVICES ]]; then
config_service_sequence_do
[ $? -ne 0 ] && CONFIG_STOPSERVICES="$old"
else
CONFIG_STOPSERVICES="$IGNORE_START_STOP_CHAR"
fi
fi
logExit "$CONFIG_STOPSERVICES"
[[ "$old" == "$CONFIG_STOPSERVICES" ]]
return
}
function config_service_sequence_do() {
local current="$CONFIG_STOPSERVICES"
logEntry "$current"
while :; do
IFS=" "
local src=( $current )
local tgt=()
local aborted=0
while :; do
local sl=()
for s in ${src[@]}; do
if [[ "$wtv" < "0.52.19" ]]; then # workaround for whiptail issue in 0.52.19
sl+=("$s" "" "")
else
sl+=("$s" "$s" "$s")
fi
done
local d="$(getMessageText $DESCRIPTION_STARTSTOP_SEQUENCE)"
local tt="$(getMessageText $TITLE_INFORMATION)"
local c1="$(getMessageText $BUTTON_CANCEL)"
local o1="$(getMessageText $BUTTON_OK)"
ANSWER=$(whiptail --notags --radiolist "$d" --title "$tt" --ok-button "$o1" --cancel-button "$c1" $WT_HEIGHT $(($WT_WIDTH/2)) 5 \
"${sl[@]}" \
3>&1 1>&2 2>&3)
if [ $? -eq 0 ]; then
logItem "Answer: $ANSWER"
local a=${ANSWER//\"}
tgt+=( $a )
local del=( $a )
src=( ${src[@]/$del} )
(( ${#src[@]} <= 0 )) && break
else
aborted=1
break
fi
done
if (( $aborted )); then
logExit "aborted"
return 1
fi
local pline sline t
sel="${tgt[@]}"
getStartStopCommands "$sel" "pline" "sline"
pline=$(sed 's/\&/\\\&/g' <<< "$pline")
sline=$(sed 's/\&/\\\&/g' <<< "$sline")
logItem "Commands: $pline"
local tl=()
local i=1
for t in ${tgt[@]}; do
if [[ "$wtv" < "0.52.19" ]]; then # workaround for whiptail issue in 0.52.19
tl+=("$i: $t" "" on)
else
tl+=("$i: $t" "$i: $t" on)
fi
(( i++ ))
done
local m="$(getMessageText $MSG_SEQUENCE_OK)"
local t=$(center $(( $WINDOW_COLS*2 )) "$m")
local y="$(getMessageText $BUTTON_YES)"
local n="$(getMessageText $BUTTON_NO)"
local tt="$(getMessageText $TITLE_CONFIRM)"
ANSWER=$(whiptail --notags --checklist "$m" --title "$tt" --ok-button "$o1" --cancel-button "$c1" $WT_HEIGHT $(($WT_WIDTH/2)) 7 \
"${tl[@]}" \
3>&1 1>&2 2>&3)
if [ $? -eq 0 ]; then
logItem "Answer: $ANSWER"
CONFIG_STOPSERVICES="${tgt[@]}"
break
fi
done
logExit "$CONFIG_STOPSERVICES"
}
function config_partitions_do() {
local old="$CONFIG_PARTITIONS_TO_BACKUP"
logEntry "$old"
IFS="$DEFAULT_IFS"
wtv=$(whiptail -v | cut -d " " -f 3)
local rootPartition=$(findmnt / -o source -n | sed -E 's/p?[0-9]+$//') # /dev/sda or /dev/mmcblk0
logItem "Rootpartition: $rootPartition"
local done=0
while ((! $done)); do
local current="$CONFIG_PARTITIONS_TO_BACKUP"
logItem "Current: $current"
local c=($current)
# 1 256M c W95
# 2 14.3G 83 Linux
# 5 265G 83 Linux
local ps=()
local line
while IFS= read -r line; do
ps+=("$line")
done <<< "$(getPartitionNumbers $rootPartition)"
local numberOfPartitions=${#ps[@]}
logItem "Partitions: $numberOfPartitions"
local pn=()
local -A pn_desc
local state s
IFS="$DEFAULT_IFS"
for s in "${ps[@]}"; do
local n="$(cut -f1 -d " " <<< "$s")"
pn+=($n)
pn_desc[$n]="$(cut -f2- -d " " <<< "$s")"
done
getMenuText $MENU_CONFIG_MODE_PARTITION tt
local cl=()
# add all partitions in list
for s in ${pn[@]}; do
if containsElement "$s" "${c[@]}"; then
state=on
else
state=off
fi
if [[ "$wtv" < "0.52.19" ]]; then # workaround for whiptail issue in 0.52.19
cl+=("$s" "" "$state")
else
local desc="$(printf "%6s %s" $(cut -d ' ' -f 1 <<< "${pn_desc[$s]}") $(cut -d ' ' -f 2- <<< "${pn_desc[$s]}"))"
cl+=("$s" "$s: ${desc}" "$state")
fi
done
local d="$(getMessageText $DESCRIPTION_PARTITIONS)"
local c1="$(getMessageText $BUTTON_CANCEL)"
local o1="$(getMessageText $BUTTON_OK)"
ANSWER=$(whiptail --notags --checklist "$d" --title "${tt[1]}" --ok-button "$o1" --cancel-button "$c1" $WT_HEIGHT $(($WT_WIDTH/2)) 7 \
"${cl[@]}" \
3>&1 1>&2 2>&3)
if [ $? -eq 0 ]; then
logItem "Answer: $ANSWER"
local current=${ANSWER//\"}
# make sure the first two partitions are included
local orgCurrent="$current"
current="1 2 $current" # add first two partitions
current="$(tr ' ' '\n' <<< "$current" | sort -u | tr '\n' ' ' | sed 's/^[ \t]*//;s/[ \t]*$//')" # remove duplicates
CONFIG_PARTITIONS_TO_BACKUP="$current"
[[ "$orgCurrent" == "$current" ]] # check the first partitions were not deselected
done=$(( ! $? ))
if (( ! $done )); then
local m="$(getMessageText $MSG_FIRST_PARTITIONS_NOT_SELECTED)"
local t=$(center $WINDOW_COLS "$m")
local tt="$(getMessageText $TITLE_INFORMATION)"
whiptail --msgbox "$t" --title "$tt" $ROWS_MSGBOX $WINDOW_COLS 2
fi
else
CONFIG_PARTITIONS_TO_BACKUP="$old"
done=1
fi
done
[[ "$old" == "$CONFIG_PARTITIONS_TO_BACKUP" ]]
local rc=$?
logExit "$rc - $CONFIG_PARTITIONS_TO_BACKUP"
return $rc
}
function config_cronday_do() {
local old="$CONFIG_CRON_DAY"
logEntry "$old"
local days_=(off off off off off off off off)
local i
getMenuText $MENU_DAYS_SHORT s
getMenuText $MENU_DAYS_LONG l
getMenuText $MENU_CONFIG_DAY tt
days_[$CONFIG_CRON_DAY]=on # 0 = Daily, 1 = Sun, 2 = Mon ...
ANSWER=$(whiptail --notags --radiolist "" --title "${tt[1]}" $WT_HEIGHT $(($WT_WIDTH/2)) 5 \
"${s[0]}" "${l[0]}" "${days_[0]}" \
"${s[1]}" "${l[1]}" "${days_[1]}" \
"${s[2]}" "${l[2]}" "${days_[2]}" \
"${s[3]}" "${l[3]}" "${days_[3]}" \
"${s[4]}" "${l[4]}" "${days_[4]}" \
"${s[5]}" "${l[5]}" "${days_[5]}" \
"${s[6]}" "${l[6]}" "${days_[6]}" \
"${s[7]}" "${l[7]}" "${days_[7]}" \
3>&1 1>&2 2>&3)
if [ $? -eq 0 ]; then
logItem "Answer: $ANSWER"
for (( i=0; i< ${#s[@]}; i++ )); do
if [[ "${s[$i]}" == "$ANSWER" ]]; then
CONFIG_SYSTEMD_DAY=$i
break;
fi
done
CONFIG_CRON_DAY="$i"
fi
[[ "$old" == "$CONFIG_CRON_DAY" ]]
rc=$?
logExit "$rc - $CONFIG_CRON_DAY"
return $rc
}
function config_systemday_do() {
local old="$CONFIG_SYSTEMD_DAY"
logEntry "$old"
local days_=(off off off off off off off off)
local i
getMenuText $MENU_DAYS_SHORT s
getMenuText $MENU_DAYS_LONG l
getMenuText $MENU_CONFIG_DAY tt
days_[$CONFIG_SYSTEMD_DAY]=on # 0 = Daily, 1 = Sun, 2 = Mon ...
ANSWER=$(whiptail --notags --radiolist "" --title "${tt[1]}" $WT_HEIGHT $(($WT_WIDTH/2)) 5 \
"${s[0]}" "${l[0]}" "${days_[0]}" \
"${s[1]}" "${l[1]}" "${days_[1]}" \
"${s[2]}" "${l[2]}" "${days_[2]}" \
"${s[3]}" "${l[3]}" "${days_[3]}" \
"${s[4]}" "${l[4]}" "${days_[4]}" \
"${s[5]}" "${l[5]}" "${days_[5]}" \
"${s[6]}" "${l[6]}" "${days_[6]}" \
"${s[7]}" "${l[7]}" "${days_[7]}" \
3>&1 1>&2 2>&3)
if [ $? -eq 0 ]; then
logItem "Answer: $ANSWER"
for (( i=0; i< ${#s[@]}; i++ )); do
if [[ "${s[$i]}" == "$ANSWER" ]]; then
CONFIG_SYSTEMD_DAY=$i
break;
fi
done
fi
[[ "$old" == "$CONFIG_SYSTEMD_DAY" ]]
rc=$?
logExit "$rc - $CONFIG_SYSTEMD_DAY"
return $rc
}
function config_compress_do() {
logEntry "$CONFIG_ZIP_BACKUP"
local old="$CONFIG_ZIP_BACKUP"
if [ $CONFIG_BACKUPTYPE == "rsync" ]; then
local t=$(center $WINDOW_COLS "rsync backups cannot be compressed.")
local tt="$(getMessageText $TITLE_INFORMATION)"
whiptail --msgbox "$t" --title "$tt" $ROWS_MENU $WINDOW_COLS 2
else
local yes_=off
local no_=off
case "$CONFIG_ZIP_BACKUP" in
"1") yes_=on ;;
"0") no_=on ;;
*) whiptail --msgbox "Programm error, unrecognized compress mode $CONFIG_ZIP_BACKUP" $ROWS_MENU $WINDOW_COLS 2
logExit
return 1
;;
esac
local o1="$(getMessageText $BUTTON_OK)"
local c1="$(getMessageText $BUTTON_CANCEL)"
getMenuText $MENU_CONFIG_COMPRESS_ON m1
getMenuText $MENU_CONFIG_COMPRESS_OFF m2
local s1="${m1[0]}"
local s2="${m2[0]}"
local d="$(getMessageText $DESCRIPTION_COMPRESS)"
getMenuText $MENU_CONFIG_ZIP tt
ANSWER=$(whiptail --notags --radiolist "$d" --title "${tt[1]}" --ok-button "$o1" --cancel-button "$c1" $WT_HEIGHT $(($WT_WIDTH/2)) 2 \
"${m1[@]}" "$yes_" \
"${m2[@]}" "$no_" \
3>&1 1>&2 2>&3)
if [ $? -eq 0 ]; then
logItem "Answer: $ANSWER"
case "$ANSWER" in
$s1) CONFIG_ZIP_BACKUP="1" ;;
$s2) CONFIG_ZIP_BACKUP="0" ;;
*) whiptail --msgbox "Programm error, unrecognized compress mode $ANSWER" $ROWS_MENU $WINDOW_COLS 2
logExit
return 1
;;
esac
fi
fi
[[ "$old" == "$CONFIG_ZIP_BACKUP" ]]
local rc=$?
logExit "$rc - $CONFIG_ZIP_BACKUP"
return $rc
}
function progressbar_do() { #