From c4383dd07a6fc6e08ede862aaa0ca8d4ef34e9d7 Mon Sep 17 00:00:00 2001 From: OWarneke Date: Mon, 31 Jan 2022 11:31:03 +0100 Subject: [PATCH 1/4] Adding Option to store Containers as images. --- Backup/backupSD.sh | 56 ++++++++++++++++++++++++++++++++++------ Backup/backupSettings.sh | 5 +++- Backup/restoreBackup.sh | 26 ++++++++++++++++++- 3 files changed, 77 insertions(+), 10 deletions(-) diff --git a/Backup/backupSD.sh b/Backup/backupSD.sh index a6f4f6d..65fc9d7 100644 --- a/Backup/backupSD.sh +++ b/Backup/backupSD.sh @@ -32,6 +32,7 @@ PS3="Select your choice: " options=("Upperdir" \ "PCWE Project only" \ "Directories specified by backupSettings.sh" \ +"Containers" \ "Continue" \ "Exit") select opt in "${options[@]}" @@ -58,12 +59,7 @@ do # STORE="Everything" # echo "STORE = $STORE" # ;; - - # "Containers") - # STORE="Everything" - # echo "STORE = $STORE" - # ;; - + "Continue") if [ "$STORE" == "" ]; then echo "STORE = $STORE empty Exit Script" @@ -83,7 +79,15 @@ done echo 'Do you wish to add stored licenses and PLC device data to this backup?' PS3="Select your choice: " -options=("Don't Store Licence" "Store Licence" "Don't Store DeviceData" "Store DeviceData" "Continue" "Exit") +options=("Don't Store Licence" +"Store Licence" +"Don't Store DeviceData" +"Store DeviceData" +"Don't Store Containers" +"Store Containers" +"Continue" +"Exit" +) select opt in "${options[@]}" do case $opt in @@ -103,15 +107,29 @@ do STORE_DEVICEDATA=true echo "STORE_DEVICEDATA = $STORE_DEVICEDATA" ;; + "Store Containers") + STORE_CONTAINER=true + echo "STORE = $STORE" + ;; + "Dont Store Containers") + STORE_CONTAINER=false + echo "STORE = $STORE" + ;; "Continue") if [ "$STORE_LICENCE" == "" ]; then echo "STORE_LICENCE = $STORE_LICENCE empty. Exit Script." exit 1 fi + if [ "$STORE_DEVICEDATA" == "" ]; then echo "STORE_DEVICEDATA = $STORE_DEVICEDATA empty. Exit Script." exit 1 fi + + if [ "$STORE_CONTAINER" == "" ]; then + echo "STORE_DEVICEDATA = $STORE_CONTAINER empty. Exit Script." + exit 1 + fi break ;; "Exit") @@ -143,9 +161,11 @@ then echo "STORE = $STORE" case "$STORE" in - "Upperdir") + "Upperdir") + echo "Storing Upperdir" tar -rpf ${StoreBackupAt}/backup-${DATE}.tar -C ${DATAPATH} upperdir && echo "Done" ;; + "Changes") echo -e "Store specified folders only:" (set -o posix ; set) | grep "STORE" | grep "true" @@ -252,6 +272,26 @@ if $STORE_LICENCE; then fi fi +if $STORE_CONTAINER; then + echo "Storing Containers" + ## Get a list of all containers + CONTAINERS=($(podman container ls -aq)) + mkdir ${DATAPATH}Containers + # Export Containers and add them to the backup.tar + for CONTAINER in "${CONTAINERS[@]}" + do + echo "Storing Container:$CONTAINER" + echo "This just saves the current state of the Container as an Image!" + echo "You still need to Setup the Container again when restoring this backup" + echo "podman run -v XX -p xxx ... " + ## Need to stop continers? + $CONTAINER_ENGINE export $CONTAINER --output "${DATAPATH}/Containers/$CONTAINER.tar" + tar -rpf ${StoreBackupAt}/backup-${DATE}.tar -C ${DATAPATH} "Containers/$CONTAINER.tar" + rm "${DATAPATH}/Containers/$CONTAINER.tar" + done && echo "Done" + ;; +fi + if [ -f "${StoreBackupAt}/backup-${DATE}.tar" ]; then chown admin:plcnext ${StoreBackupAt}/backup-*.tar echo "Contents of Backup:" diff --git a/Backup/backupSettings.sh b/Backup/backupSettings.sh index ff8fda6..e56599b 100644 --- a/Backup/backupSettings.sh +++ b/Backup/backupSettings.sh @@ -50,4 +50,7 @@ STORE_ALL_CONFIG=false # Whole config directory CONFIG="upperdir/opt/plcnext/config" STORE_ALL_DATA=false # this directory holds mostly session dependend data like PIDs, FW update Status etc. -DATA="upperdir/opt/plcnext/data" \ No newline at end of file +DATA="upperdir/opt/plcnext/data" + +STORE_CONTAINER=false +CONTAINER_ENGINE=podman \ No newline at end of file diff --git a/Backup/restoreBackup.sh b/Backup/restoreBackup.sh index 46945dc..87d6407 100644 --- a/Backup/restoreBackup.sh +++ b/Backup/restoreBackup.sh @@ -9,6 +9,10 @@ CURRENT=$(pwd) TargetDirectory="$1" BackupLocation="$2" +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" +## Set the directories for the backup +. ${SCRIPT_DIR}/../Backup/backupSettings.sh + if [ "$1" == "" ]; then echo "please add backup location as argument" echo "Example: @@ -26,7 +30,12 @@ tar -tvf "${BackupLocation}" echo 'Choose all the directories you wish to restore.' PS3="Select your choice: " -options=("SD Licence" "DeviceData" "PCWE" "Upperdir" "Exit") +options=("SD Licence" \ +"DeviceData" \ +"PCWE" \ +"Upperdir" \ +"Containers" \ +"Exit") select opt in "${options[@]}" do case $opt in @@ -82,6 +91,21 @@ do tar --same-owner -xvf "${BackupLocation}" -C "$TargetDirectory" upperdir && echo "Done restoring Upperdir" ;; + "Containers") + echo "Restoring Containers" + echo "This just restores the current state of the saved Container as an Image!" + echo "You still need to Setup the Container again after restoring this backup" + echo "podman run -v XX -p xxx ... " + tar --same-owner -xvf "${BackupLocation}" -C "$TargetDirectory" Containers && echo "Done restoring Container.tar" + CONTAINERS=($(ls $TargetDirectory/Containers)) + for CONTAINER in "${CONTAINERS[@]}" + do + echo "Importing $CONTAINER" + $CONTAINER_ENGINE import $TargetDirectory/Containers/$CONTAINER + rm $TargetDirectory/Containers/$CONTAINER + done && echo "Done" + ;; + "Exit") exit 1 break From 73d9523eaf7bc9a00cfea5ce01e9de678395d82e Mon Sep 17 00:00:00 2001 From: OWarneke Date: Mon, 31 Jan 2022 14:59:21 +0100 Subject: [PATCH 2/4] draft for #4 --- Backup/backupSD.sh | 629 ++++++++++++++++++++++++--------------- Backup/backupSettings.sh | 18 +- 2 files changed, 409 insertions(+), 238 deletions(-) diff --git a/Backup/backupSD.sh b/Backup/backupSD.sh index 65fc9d7..8dbf35b 100644 --- a/Backup/backupSD.sh +++ b/Backup/backupSD.sh @@ -6,301 +6,466 @@ # * # ****************************************************************************** CURRENT=$(pwd) -DATAPATH="$1" -StoreBackupAt="$2" - -if [[ $DATAPATH == "" && $StoreBackupAt == "" ]]; then - echo "Usage: ./backupSD.sh DATAPATH StoreBackupAt"; - echo "Example: ./backupSD.sh /media/rfs/rw/ /media/rfs/rw/"; - exit 255; -fi SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" +STORAGE_MODE="" +STORE_DEVICEDATA=false +STORE_LICENCE=false +STORE_CONTAINER=false +BACKUP_NAME="Backup" +DATE=$(date -I) + +while getopts C:M:D:N:L:I:S:T: opt; +do + case "${opt}" in + C) SETTINGS_PATH="$OPTARG";; + M) SET_STORAGE_MODE="$OPTARG";; + D) SET_STORE_DEVICEDATA="$OPTARG";; + L) SET_STORE_LICENCE="$OPTARG";; + I) SET_STORE_CONTAINER="$OPTARG";; + N) BACKUP_NAME="$OPTARG";; + S) SourceLocation="$OPTARG";; + T) TargetLocation="$OPTARG";; + *) echo '#Usage: \ + #If only Storage mode is not set the Script will be started in interactive mode. \ + #Example for interactive backup: \ + # backupSD.sh -S /media/rfs/internalsd/ -T /media/rfs/externalsd \ + # \ + #Example for creating a backup of the internal storage \ + # \ + #"backupSD.sh -S /media/rfs/internalsd/ -T /media/rfs/externalsd/ -C backupSettings.sh -M PCWE -D true -L true -N "MyBackup" \ + # \ + # Options: \ + #-C Config \ + # "SettingsFile.sh or /x/x/SettingsFile.sh Default: " \ + #-M Storage Mode: \ + # "Upperdir / PCWE / SettingsFile" \ + #-D Store DeviceData \ + # "true/false" \ + #-L Store LicenseFiles \ + # "true/false" \ + #-I Store Container \ + # "true/false" \ + #-N Backup name \ + # default "Backup" will result in Backup-$DATE.tar \ + #Mandatory: \ + #-S SourceLocation \ + # /media/rfs/internalsd/ \ + #-T TargetLocation \ + # /media/rfs/externalsd/' + exit 1 + ;; + esac +done -## Set the directories for the backup -. ${SCRIPT_DIR}/../Backup/backupSettings.sh -df -ha | grep rfs -${SCRIPT_DIR}/../Diagnostic/checkActivePartition.sh if [ "$(whoami)" != "root" ]; then echo "please use ROOT to create a backup"; exit 255; fi -echo 'Choose the kind of Backup you want to create.' -PS3="Select your choice: " -options=("Upperdir" \ -"PCWE Project only" \ -"Directories specified by backupSettings.sh" \ -"Containers" \ -"Continue" \ -"Exit") -select opt in "${options[@]}" -do - case $opt in - "Upperdir") - STORE="Upperdir" - echo "STORE = $STORE" - ;; - - "PCWE Project only") - STORE="PCWE" - echo "STORE = $STORE" - ;; - - "Directories specified by backupSettings.sh") - echo "check 'backupSettings.sh' to check or change settings" - (set -o posix ; set) | grep STORE | grep true - STORE="Changes" - echo "STORE = $STORE" - ;; - # "Everything") - # STORE="Everything" - # echo "STORE = $STORE" - # ;; - - "Continue") - if [ "$STORE" == "" ]; then - echo "STORE = $STORE empty Exit Script" - exit 1 - fi - break - ;; - - "Exit") - exit 1 - break - ;; - *) echo "invalid option $REPLY";; - esac -done +## Set the root media to be backedup and the target location at which the backup will be stored. +if [[ $SourceLocation == "" && $TargetLocation == "" ]]; then + echo "Usage: ./backupSD.sh -S SourceLocation -T TargetLocation"; + echo "Example: ./backupSD.sh -S /media/rfs/rw/upperdir/ -T /media/rfs/rw/"; + exit 255; +fi -echo 'Do you wish to add stored licenses and PLC device data to this backup?' -PS3="Select your choice: " -options=("Don't Store Licence" -"Store Licence" -"Don't Store DeviceData" -"Store DeviceData" -"Don't Store Containers" -"Store Containers" -"Continue" -"Exit" -) -select opt in "${options[@]}" -do - case $opt in - "Don't Store Licence") - STORE_LICENCE=false - echo "STORE_LICENCE = $STORE_LICENCE" - ;; - "Store Licence") - STORE_LICENCE=true - echo "STORE_LICENCE = $STORE_LICENCE" - ;; - "Don't Store DeviceData") - STORE_DEVICEDATA=false - echo "STORE_DEVICEDATA = $STORE_DEVICEDATA" - ;; - "Store DeviceData") - STORE_DEVICEDATA=true - echo "STORE_DEVICEDATA = $STORE_DEVICEDATA" - ;; - "Store Containers") - STORE_CONTAINER=true - echo "STORE = $STORE" - ;; - "Dont Store Containers") - STORE_CONTAINER=false - echo "STORE = $STORE" - ;; - "Continue") - if [ "$STORE_LICENCE" == "" ]; then - echo "STORE_LICENCE = $STORE_LICENCE empty. Exit Script." - exit 1 - fi +## Set the settings and specific content locations for the backup from file. +echo SETTINGS_PATH="$SETTINGS_PATH"; +if [ -f "$SETTINGS_PATH" ]; +then +. $SETTINGS_PATH +elif [ -f "${SCRIPT_DIR}/$SETTINGS_PATH" ]; +then +. ${SCRIPT_DIR}/$SETTINGS_PATH +else +. ${SCRIPT_DIR}/../Backup/backupSettings.sh +fi - if [ "$STORE_DEVICEDATA" == "" ]; then - echo "STORE_DEVICEDATA = $STORE_DEVICEDATA empty. Exit Script." - exit 1 - fi +## +## overwrite if set on CLI +## +if [ SET_STORAGE_MODE != "" ]; then + STORAGE_MODE="$SET_STORAGE_MODE"; +fi +if [ SET_STORE_DEVICEDATA != "" ]; then + STORE_DEVICEDATA="$SET_STORE_DEVICEDATA"; +fi +if [ SET_STORE_LICENCE != "" ]; then + STORE_LICENCE="$SET_STORE_LICENCE"; +fi +if [ SET_STORE_CONTAINER != "" ]; then + STORE_CONTAINER="$SET_STORE_CONTAINER"; +fi - if [ "$STORE_CONTAINER" == "" ]; then - echo "STORE_DEVICEDATA = $STORE_CONTAINER empty. Exit Script." - exit 1 - fi - break - ;; - "Exit") - exit 1 - break +# When STORAGE_MODE is set disable the interactive mode. Commandline > SettingsFile. +if [[ "$STORAGE_MODE" == "" ]]; then + INTERACTIVE=true + echo "Interactive activated" +else + INTERACTIVE=false + echo "Interactive deactivated" +fi +### +### Start interactive settings +### +if [[ $INTERACTIVE == true ]]; +then + echo 'Choose the kind of Backup you want to create.' + PS3="Select your choice: " + options=("Upperdir" \ + "PCWE Project only" \ + "Directories specified by backupSettings.sh" \ + "Containers" \ + "Continue" \ + "Exit") + select opt in "${options[@]}" + do + case $opt in + "Upperdir") + STORAGE_MODE="Upperdir" + echo "STORAGE_MODE = $STORAGE_MODE" + ;; + + "PCWE Project only") + STORAGE_MODE="PCWE" + echo "STORAGE_MODE = $STORAGE_MODE" + ;; + + "Directories specified by backupSettings.sh") + echo "check 'backupSettings.sh' to check or change settings" + (set -o posix ; set) | grep STORAGE_MODE | grep true + STORAGE_MODE="Changes" + echo "STORAGE_MODE = $STORAGE_MODE" + ;; + + # "Everything") + # STORAGE_MODE="Everything" + # echo "STORAGE_MODE = $STORAGE_MODE" + # ;; + + "Continue") + if [ "$STORAGE_MODE" == "" ]; then + echo "STORAGE_MODE = $STORAGE_MODE empty Exit Script" + exit 1 + fi + break + ;; + + "Exit") + exit 1 + break + ;; + + *) echo "invalid option $REPLY";; + esac + done + + echo 'Do you wish to add stored licenses and PLC device data to this backup?' + PS3="Select your choice: " + options=("Don't Store Licence" + "Store Licence" + "Don't Store DeviceData" + "Store DeviceData" + "Don't Store Containers" + "Store Containers" + "Continue" + "Exit" + ) + select opt in "${options[@]}" + do + case $opt in + "Don't Store Licence") + STORE_LICENCE=false + echo "STORE_LICENCE = $STORE_LICENCE" + ;; + "Store Licence") + STORE_LICENCE=true + echo "STORE_LICENCE = $STORE_LICENCE" + ;; + "Don't Store DeviceData") + STORE_DEVICEDATA=false + echo "STORE_DEVICEDATA = $STORE_DEVICEDATA" + ;; + "Store DeviceData") + STORE_DEVICEDATA=true + echo "STORE_DEVICEDATA = $STORE_DEVICEDATA" + ;; + "Store Containers") + STORE_CONTAINER=true + echo "STORE = $STORE" + ;; + "Dont Store Containers") + STORE_CONTAINER=false + echo "STORE = $STORE" + ;; + "Continue") + if [ "$STORE_LICENCE" == "" ]; then + echo "STORE_LICENCE = $STORE_LICENCE empty. Exit Script." + exit 1 + fi + + if [ "$STORE_DEVICEDATA" == "" ]; then + echo "STORE_DEVICEDATA = $STORE_DEVICEDATA empty. Exit Script." + exit 1 + fi + + if [ "$STORE_CONTAINER" == "" ]; then + echo "STORE_DEVICEDATA = $STORE_CONTAINER empty. Exit Script." + exit 1 + fi + break + ;; + "Exit") + exit 1 + break + ;; + + *) echo "invalid option $REPLY";; + esac + done + + echo "Please check if the paths are correct." + echo "SourceLocation: '$SourceLocation' The directory you want to backup." + echo "TargetLocation: '$TargetLocation' the location you want to store your backup at." + echo "Storage Mode: '$STORAGE_MODE' is activated." + + echo ":" + read -r -p "Are you sure? [yes/No] all settings are correct + " response + if [[ "$response" =~ ^([yY][eE][sS]|[yY])$ ]] + then + exit 1; + fi +fi + +## +## Verify available diskspace +## +case $STORAGE_MODE in + "Upperdir") + var=( $(du -s ${SourceLocation}/upperdir) ) + SpaceRequired=${var[0]} ;; + "Changes") + var=( $(du -s ${SourceLocation}/upperdir/opt/plcnext) ) + SpaceRequired=${var[0]} + ;; + "PCWE") + var=( $(du -s ${SourceLocation}/upperdir/opt/plcnext/projects/PCWE) ) + SpaceRequired=${var[0]} + ;; + *) SpaceRequired=0 + ;; - *) echo "invalid option $REPLY";; - esac -done +esac +## +## Diagnostics to help verify that the backuppath matches the active partition. +## +df -ha | grep rfs +${SCRIPT_DIR}/../Diagnostic/checkActivePartition.sh +if [[ $STORE_CONTAINER == true ]]; +then + echo Add Container Size + var=0 + SpaceRequired=$(($SpaceRequired + ${var[0]})) +fi -echo "Please check if the paths are correct." -echo "DataPath: '$DATAPATH' The directory you want to backup." -echo "StoreBackupAt: '$StoreBackupAt' the location you want to store your backup at." -echo "Storage Mode: '$STORE' is activated." +if [[ $STORE_DEVICEDATA == true ]]; +then + var=( $(du -s /etc/device_data)) + SpaceRequired=$(($SpaceRequired + ${var[0]})) +fi + +if [[ $STORE_LICENCE == true ]]; +then + var=( $(du -s ${SourceLocation}/licence) ) + SpaceRequired=$(($SpaceRequired + ${var[0]})) +fi +var=( $(df --output=avail ${TargetLocation}) ) +SpaceAvailable=${var[1]} + +if [[ $SpaceRequired -gt $SpaceAvailable ]]; +then + echo "WARNING you might not have enough space for this Backup!" + echo "$SpaceRequired -gt $SpaceAvailable" +else + echo SpaceRequired: $SpaceRequired + echo SpaceAvailable: $SpaceAvailable +fi -echo ":" -read -r -p "Are you sure? [y/N] all settings are correct -" response ### -### Storage Function +### Start creating Backup ### -if [[ "$response" =~ ^([yY][eE][sS]|[yY])$ ]] -then - DATE=$(date -I) - date > ${StoreBackupAt}/DATEFILE; - tar -cvpf ${StoreBackupAt}/backup-${DATE}.tar -C ${StoreBackupAt} DATEFILE - - echo "STORE = $STORE" - case "$STORE" in +date > ${TargetLocation}/DATEFILE; +tar -cvpf ${TargetLocation}/${BACKUP_NAME}-${DATE}.tar -C ${TargetLocation} DATEFILE + +echo "STORAGE_MODE = $STORAGE_MODE" +case "$STORAGE_MODE" in "Upperdir") echo "Storing Upperdir" - tar -rpf ${StoreBackupAt}/backup-${DATE}.tar -C ${DATAPATH} upperdir && echo "Done" + tar -rpf ${TargetLocation}/${BACKUP_NAME}-${DATE}.tar -C ${SourceLocation} upperdir && echo "Done" ;; - + "Changes") echo -e "Store specified folders only:" - (set -o posix ; set) | grep "STORE" | grep "true" - read -r -p "Proceed creating backup [y/N] : " response - if [[ "$response" =~ ^([yY][eE][sS]|[yY])$ ]] - then - ## Add Folders to Tar. - if $STORE_UNIX_PASSWORD_CHANGES; then - echo "Storing UNIX_PASSWORD_CHANGES" - tar -rpf ${StoreBackupAt}/backup-${DATE}.tar -C ${DATAPATH} ${UNIX_PASSWORD_Changes[@]} && echo "Done" - fi - if $STORE_NETWORK; then - echo "Storing Network Settings" - tar -rpf ${StoreBackupAt}/backup-${DATE}.tar -C ${DATAPATH} ${NETWORK} && echo "Done" + (set -o posix ; set) | grep "STORE" | grep "true" + if [ $INTERACTIVE = true ]; + then + read -r -p "Proceed creating backup [y/N] : " response + if [[ "$response" =~ ^([yY][eE][sS]|[yY])$ ]] + then + echo "Continue:" + else + exit 1; fi + fi + ## Add Folders to Tar. + if $STORE_UNIX_PASSWORD_CHANGES; + then + echo "Storing UNIX_PASSWORD_CHANGES" + tar -rpf ${TargetLocation}/${BACKUP_NAME}-${DATE}.tar -C ${SourceLocation} ${UNIX_PASSWORD_Changes[@]} && echo "Done" + fi + if $STORE_NETWORK; + then + echo "Storing Network Settings" + tar -rpf ${TargetLocation}/${BACKUP_NAME}-${DATE}.tar -C ${SourceLocation} ${NETWORK} && echo "Done" + fi - if $STORE_SSH_KEYs; then - echo "Storing SSH Keys" - tar -rpf ${StoreBackupAt}/backup-${DATE}.tar -C ${DATAPATH} ${SSH_KEYs} && echo "Done" - fi + if $STORE_SSH_KEYs; + then + echo "Storing SSH Keys" + tar -rpf ${TargetLocation}/${BACKUP_NAME}-${DATE}.tar -C ${SourceLocation} ${SSH_KEYs} && echo "Done" + fi - if $STORE_PLCnext_PROJECTS; then - echo "Storing PROJECTS" - tar -rpf ${StoreBackupAt}/backup-${DATE}.tar -C ${DATAPATH} ${PROJECTS} && echo "Done" - fi + if $STORE_PLCnext_PROJECTS; + then + echo "Storing PROJECTS" + tar -rpf ${TargetLocation}/${BACKUP_NAME}-${DATE}.tar -C ${SourceLocation} ${PROJECTS} && echo "Done" + fi - if $STORE_PLCnext_SYSTEM_UM; then - echo "Storing SYSTEM UM Settings" - tar -rpf ${StoreBackupAt}/backup-${DATE}.tar -C ${DATAPATH} ${PLCnext_UM}&& echo "Done" - fi + if $STORE_PLCnext_SYSTEM_UM; + then + echo "Storing SYSTEM UM Settings" + tar -rpf ${TargetLocation}/${BACKUP_NAME}-${DATE}.tar -C ${SourceLocation} ${PLCnext_UM}&& echo "Done" + fi - if $STORE_PLCnext_SYSTEM_SCM; then - echo "Storing SYSTEM SCM Settings" - tar -rpf ${StoreBackupAt}/backup-${DATE}.tar -C ${DATAPATH} ${PLCnext_SCM} && echo "Done" - fi + if $STORE_PLCnext_SYSTEM_SCM; + then + echo "Storing SYSTEM SCM Settings" + tar -rpf ${TargetLocation}/${BACKUP_NAME}-${DATE}.tar -C ${SourceLocation} ${PLCnext_SCM} && echo "Done" + fi - if $STORE_PLCNext_SERVICES; then - echo "Storing SERVICE Settings" - tar -rpf ${StoreBackupAt}/backup-${DATE}.tar -C ${DATAPATH} ${SERVICES} && echo "Done" - ### If required add keys for specific services - #STORE_PLCNext_SERVICES_Ehmi - #STORE_PLCNext_SERVICES_Grpc - #STORE_PLCNext_SERVICES_LinuxSyslog - #STORE_PLCNext_SERVICES_OpcUA - #STORE_PLCNext_SERVICES_PLCnextStore - #STORE_PLCNext_SERVICES_PortAuthentication - #STORE_PLCNext_SERVICES_Spm - #STORE_PLCNext_SERVICES_SpnsProxy - #STORE_PLCNext_SERVICES_Syslog - #STORE_PLCNext_SERVICES_Wcm - fi - if $STORE_PLCnext_SECURITY; then - echo "Storing PLCnext_SECURITY directory" - tar -rpf ${StoreBackupAt}/backup-${DATE}.tar -C ${DATAPATH} ${PLCnext_SECURITY} && echo "Done" - fi - if $STORE_INSTALLED_APPS; then - echo "Storing INSTALLED_APPS" - tar -rpf ${StoreBackupAt}/backup-${DATE}.tar -C ${DATAPATH} ${INSTALLED_APPS} && echo "Done" - fi - if $STORE_ALL_CONFIG; then - echo "Storing CONFIG directory" - tar -rpf ${StoreBackupAt}/backup-${DATE}.tar -C ${DATAPATH} ${CONFIG} && echo "Done" - fi + if $STORE_PLCNext_SERVICES; + then + echo "Storing SERVICE Settings" + tar -rpf ${TargetLocation}/${BACKUP_NAME}-${DATE}.tar -C ${SourceLocation} ${SERVICES} && echo "Done" + ### If required add keys for specific services + #STORE_PLCNext_SERVICES_Ehmi + #STORE_PLCNext_SERVICES_Grpc + #STORE_PLCNext_SERVICES_LinuxSyslog + #STORE_PLCNext_SERVICES_OpcUA + #STORE_PLCNext_SERVICES_PLCnextStore + #STORE_PLCNext_SERVICES_PortAuthentication + #STORE_PLCNext_SERVICES_Spm + #STORE_PLCNext_SERVICES_SpnsProxy + #STORE_PLCNext_SERVICES_Syslog + #STORE_PLCNext_SERVICES_Wcm + fi - if $STORE_ALL_DATA; then - echo "Storing DATA directory" - tar -rpf ${StoreBackupAt}/backup-${DATE}.tar -C ${DATAPATH} ${DATA} && echo "Done" - fi + if $STORE_PLCnext_SECURITY; + then + echo "Storing PLCnext_SECURITY directory" + tar -rpf ${TargetLocation}/${BACKUP_NAME}-${DATE}.tar -C ${SourceLocation} ${PLCnext_SECURITY} && echo "Done" + fi + + if $STORE_INSTALLED_APPS; + then + echo "Storing INSTALLED_APPS" + tar -rpf ${TargetLocation}/${BACKUP_NAME}-${DATE}.tar -C ${SourceLocation} ${INSTALLED_APPS} && echo "Done" + fi - + if $STORE_ALL_CONFIG; + then + echo "Storing CONFIG directory" + tar -rpf ${TargetLocation}/${BACKUP_NAME}-${DATE}.tar -C ${SourceLocation} ${CONFIG} && echo "Done" fi + + if $STORE_ALL_DATA; + then + echo "Storing DATA directory" + tar -rpf ${TargetLocation}/${BACKUP_NAME}-${DATE}.tar -C ${SourceLocation} ${DATA} && echo "Done" + fi ;; "PCWE") echo "Storing PCWE directory" - tar -rpf ${StoreBackupAt}/backup-${DATE}.tar -C ${DATAPATH} ${PROJECTS} && echo "Done" + tar -rpf ${TargetLocation}/${BACKUP_NAME}-${DATE}.tar -C ${SourceLocation} ${PROJECTS} && echo "Done" ;; - esac -fi +esac -if $STORE_DEVICEDATA; then + +if [ $STORE_DEVICEDATA = true ]; +then echo "WATCH OUT! - Stored DeviceData are bound to the Hardware of the PLC do not use this backup for another PLC!" + Stored DeviceData are bound to the Hardware of the PLC. Do not use this backup for another PLC!" echo "Storing DEVICEDATA" - tar -rpf ${StoreBackupAt}/backup-${DATE}.tar -C "/etc" ${DEVICEDATA} && echo "Done" + tar -rpf ${TargetLocation}/${BACKUP_NAME}-${DATE}.tar -C / ${DEVICEDATA} && echo "Done" fi -if $STORE_LICENCE; then +if [[ $STORE_LICENCE == true ]]; +then echo "WATCH OUT! - Stored Licenses are bound to the Hardware ID do not use this backup for another PLC / SD" + Stored Licenses are bound to the Hardware ID. Do not use this backup for another PLC / SD" echo "WATCH OUT! - SD License is bound to this SD card do not use backup for another SD." - - read -r -p "Realy add License? [y/N] - " response - if [[ "$response" =~ ^([yY][eE][sS]|[yY])$ ]] - then - echo "Adding Licence, remember to unzip with caution!" - echo "Restoring this backup might void an SD-Cards License if overwritten." - tar -rpf ${StoreBackupAt}/backup-${DATE}.tar -C ${DATAPATH} ${INSTALLED_LICENSE_FILES} && echo "Done" - else - echo "Storing licence has been skipped" + SD License is bound to this SD card. Do not use backup for another SD." + if [[ $INTERACTIVE == true ]]; + then + read -r -p "Realy add License? [y/N] + " response + if [[ "$response" =~ ^([yY][eE][sS]|[yY])$ ]] + then + echo "Storing licence has been skipped" + else + exit 1 + fi fi + echo "Adding Licence, remember to unzip with caution!" + echo "Restoring this backup might void an SD-Cards License if overwritten." + tar -rpf ${TargetLocation}/${BACKUP_NAME}-${DATE}.tar -C ${SourceLocation} ${INSTALLED_LICENSE_FILES} && echo "Done" fi -if $STORE_CONTAINER; then +if [[ $STORE_CONTAINER == true ]]; +then echo "Storing Containers" ## Get a list of all containers - CONTAINERS=($(podman container ls -aq)) - mkdir ${DATAPATH}Containers + CONTAINERS=($($CONTAINER_ENGINE container ls -aq)) + mkdir ${SourceLocation}Containers # Export Containers and add them to the backup.tar for CONTAINER in "${CONTAINERS[@]}" do echo "Storing Container:$CONTAINER" echo "This just saves the current state of the Container as an Image!" echo "You still need to Setup the Container again when restoring this backup" - echo "podman run -v XX -p xxx ... " + echo "$CONTAINER_ENGINE run -v XX -p xxx ... " ## Need to stop continers? - $CONTAINER_ENGINE export $CONTAINER --output "${DATAPATH}/Containers/$CONTAINER.tar" - tar -rpf ${StoreBackupAt}/backup-${DATE}.tar -C ${DATAPATH} "Containers/$CONTAINER.tar" - rm "${DATAPATH}/Containers/$CONTAINER.tar" - done && echo "Done" - ;; + $CONTAINER_ENGINE export $CONTAINER --output "${SourceLocation}/Containers/$CONTAINER.tar" + tar -rpf ${TargetLocation}/${BACKUP_NAME}-${DATE}.tar -C ${SourceLocation} "Containers/$CONTAINER.tar" + rm "${SourceLocation}/Containers/$CONTAINER.tar" + done && echo "Done" fi -if [ -f "${StoreBackupAt}/backup-${DATE}.tar" ]; then - chown admin:plcnext ${StoreBackupAt}/backup-*.tar +if [ -f "${TargetLocation}/${BACKUP_NAME}-${DATE}.tar" ]; +then + chown admin:plcnext ${TargetLocation}/${BACKUP_NAME}-*.tar echo "Contents of Backup:" - tar -tvf "${StoreBackupAt}/backup-${DATE}.tar" | grep "/$" - - echo "How to restore: - ./restoreBackup.sh /media/rfs/rw/ /media/rfs/rw/backup-${DATE}.tar - " + tar -tvf "${TargetLocation}/${BACKUP_NAME}-${DATE}.tar" | grep "/$" else - echo "No backup created please fix your input data." + echo "No backup created please fix your input data." exit 1 fi \ No newline at end of file diff --git a/Backup/backupSettings.sh b/Backup/backupSettings.sh index e56599b..dadd577 100644 --- a/Backup/backupSettings.sh +++ b/Backup/backupSettings.sh @@ -5,18 +5,24 @@ # * Licensed under the MIT. See LICENSE file in the project root for full license information. # * # ****************************************************************************** - -## -## All possible options for the backup.sh script -## +STORAGE_MODE="PCWE" +### +### Located on the SD +### STORE_LICENCE=false # SD card Licenses INSTALLED_LICENSE_FILES="licence" +### +### Located on InternalStorage +### STORE_DEVICEDATA=false # Production Data of PLC. -DEVICEDATA="device_data" +DEVICEDATA="etc/device_data" +### +### Located on Upperdir +### STORE_UNIX_PASSWORD_CHANGES=true # Created root user, added groups etc. -UNIX_PASSWORD_Changes=( "upperdir/etc/shadow" "upperdir/etc/gshadow" "upperdir/etc/group" ) # created root user or admin unix pw was chaged. +UNIX_PASSWORD_Changes=( "/etc/shadow" "/etc/gshadow" "/etc/group" ) # created root user or admin unix pw was chaged. STORE_PLCnext_ETC=false # All modifications done to the /etc/plcnext directory PLCnext_ETC="upperdir/etc/plcnext" From 9130f510ca1aff49baec0f4ed3c432476beb49c6 Mon Sep 17 00:00:00 2001 From: OWarneke Date: Wed, 2 Feb 2022 17:51:26 +0100 Subject: [PATCH 3/4] -Improved Interactive mode - Added Tar.gz - Root verification only where its needed -list of Files -Checksum for all files. --- Backup/backupSD.sh | 542 +++++++++++++++++++++++++++------------ Backup/backupSettings.sh | 38 ++- 2 files changed, 415 insertions(+), 165 deletions(-) diff --git a/Backup/backupSD.sh b/Backup/backupSD.sh index 8dbf35b..4a9a242 100644 --- a/Backup/backupSD.sh +++ b/Backup/backupSD.sh @@ -5,11 +5,12 @@ # * Licensed under the MIT. See LICENSE file in the project root for full license information. # * # ****************************************************************************** + CURRENT=$(pwd) SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" STORAGE_MODE="" STORE_DEVICEDATA=false -STORE_LICENCE=false +STORE_SD_LICENCE=false STORE_CONTAINER=false BACKUP_NAME="Backup" DATE=$(date -I) @@ -20,7 +21,7 @@ do C) SETTINGS_PATH="$OPTARG";; M) SET_STORAGE_MODE="$OPTARG";; D) SET_STORE_DEVICEDATA="$OPTARG";; - L) SET_STORE_LICENCE="$OPTARG";; + L) SET_STORE_SD_LICENCE="$OPTARG";; I) SET_STORE_CONTAINER="$OPTARG";; N) BACKUP_NAME="$OPTARG";; S) SourceLocation="$OPTARG";; @@ -28,52 +29,65 @@ do *) echo '#Usage: \ #If only Storage mode is not set the Script will be started in interactive mode. \ #Example for interactive backup: \ - # backupSD.sh -S /media/rfs/internalsd/ -T /media/rfs/externalsd \ + # backupSD.sh -S /media/rfs/internalsd -T /media/rfs/externalsd \ # \ #Example for creating a backup of the internal storage \ # \ - #"backupSD.sh -S /media/rfs/internalsd/ -T /media/rfs/externalsd/ -C backupSettings.sh -M PCWE -D true -L true -N "MyBackup" \ + #"backupSD.sh -S /media/rfs/internalsd -T /media/rfs/externalsd -C backupSettings.sh -M PCWE -D false -L true -N "MyBackup" \ # \ # Options: \ #-C Config \ - # "SettingsFile.sh or /x/x/SettingsFile.sh Default: " \ + # "SettingsFile.sh or /x/x/SettingsFile.sh \ + # Default: backupSettings.sh" \ #-M Storage Mode: \ - # "Upperdir / PCWE / SettingsFile" \ + # "Upperdir / PCWE / SettingsFile / Manual" \ + # Default: "" = Manual #-D Store DeviceData \ # "true/false" \ + # Default: false #-L Store LicenseFiles \ # "true/false" \ + # Default: false #-I Store Container \ # "true/false" \ - #-N Backup name \ - # default "Backup" will result in Backup-$DATE.tar \ + # Default: false + #-N Backup name \ + # Default: "Backup" will result in "Backup-$DATE.tar" \ #Mandatory: \ #-S SourceLocation \ - # /media/rfs/internalsd/ \ + # /media/rfs/internalsd \ #-T TargetLocation \ - # /media/rfs/externalsd/' + # /media/rfs/externalsd' exit 1 ;; esac done +function Toggle(){ + if [ $1 = true ] ; then echo false; else echo true; fi +} - -if [ "$(whoami)" != "root" ]; then - echo "please use ROOT to create a backup"; - exit 255; -fi - +VerifyUser() { + if [ "$(whoami)" != "root" ]; then + echo "please use ROOT to create a backup with these options" + echo "or disable the option to add these files to your backup" + set | grep "STORE_" + exit 255; + fi +} ## Set the root media to be backedup and the target location at which the backup will be stored. if [[ $SourceLocation == "" && $TargetLocation == "" ]]; then + echo "Check Source and TargetLocation" echo "Usage: ./backupSD.sh -S SourceLocation -T TargetLocation"; echo "Example: ./backupSD.sh -S /media/rfs/rw/upperdir/ -T /media/rfs/rw/"; exit 255; fi + ## Set the settings and specific content locations for the backup from file. +echo "Initialize variables via SETTINGS_PATH" echo SETTINGS_PATH="$SETTINGS_PATH"; if [ -f "$SETTINGS_PATH" ]; then @@ -88,27 +102,48 @@ fi ## ## overwrite if set on CLI ## +echo "Overwrite variables entered via CLI" if [ SET_STORAGE_MODE != "" ]; then STORAGE_MODE="$SET_STORAGE_MODE"; fi if [ SET_STORE_DEVICEDATA != "" ]; then - STORE_DEVICEDATA="$SET_STORE_DEVICEDATA"; + STORE_DEVICEDATA=$SET_STORE_DEVICEDATA; fi -if [ SET_STORE_LICENCE != "" ]; then - STORE_LICENCE="$SET_STORE_LICENCE"; +if [ SET_STORE_SD_LICENCE != "" ]; then + STORE_SD_LICENCE=$SET_STORE_SD_LICENCE; fi if [ SET_STORE_CONTAINER != "" ]; then - STORE_CONTAINER="$SET_STORE_CONTAINER"; + STORE_CONTAINER=$SET_STORE_CONTAINER; fi +echo "Set Interactive mode" # When STORAGE_MODE is set disable the interactive mode. Commandline > SettingsFile. -if [[ "$STORAGE_MODE" == "" ]]; then +if [[ "$STORAGE_MODE" == "" || "$STORAGE_MODE" == "Manual" ]]; then INTERACTIVE=true echo "Interactive activated" else INTERACTIVE=false echo "Interactive deactivated" fi +case $STORAGE_MODE in + "Upperdir") :;; + "PCWE") :;; + "SettingsFile") :;; + "Manual") + STORAGE_MODE="Manual" + INTERACTIVE=true + ;; + "") + STORAGE_MODE="Manual" + INTERACTIVE=true;; + *) + echo "Mode: $STORAGE_MODE not supported" + exit 1 + ;; +esac + + +echo "Interactive mode ${INTERACTIVE}" ### ### Start interactive settings ### @@ -119,7 +154,7 @@ then options=("Upperdir" \ "PCWE Project only" \ "Directories specified by backupSettings.sh" \ - "Containers" \ + "Manual Selection" \ "Continue" \ "Exit") select opt in "${options[@]}" @@ -127,14 +162,15 @@ then case $opt in "Upperdir") STORAGE_MODE="Upperdir" - echo "STORAGE_MODE = $STORAGE_MODE" - ;; - + echo "STORAGE_MODE = $STORAGE_MODE" + echo "Needs Root privileges Currentuser:$(whoami)" + ;; + "PCWE Project only") STORAGE_MODE="PCWE" echo "STORAGE_MODE = $STORAGE_MODE" ;; - + "Directories specified by backupSettings.sh") echo "check 'backupSettings.sh' to check or change settings" (set -o posix ; set) | grep STORAGE_MODE | grep true @@ -142,10 +178,11 @@ then echo "STORAGE_MODE = $STORAGE_MODE" ;; - # "Everything") - # STORAGE_MODE="Everything" - # echo "STORAGE_MODE = $STORAGE_MODE" - # ;; + "Manual Selection") + STORAGE_MODE="Manual" + INTERACTIVE=true + echo "STORAGE_MODE = $STORAGE_MODE" + ;; "Continue") if [ "$STORAGE_MODE" == "" ]; then @@ -154,103 +191,194 @@ then fi break ;; - - "Exit") - exit 1 - break - ;; - - *) echo "invalid option $REPLY";; - esac - done - - echo 'Do you wish to add stored licenses and PLC device data to this backup?' - PS3="Select your choice: " - options=("Don't Store Licence" - "Store Licence" - "Don't Store DeviceData" - "Store DeviceData" - "Don't Store Containers" - "Store Containers" - "Continue" - "Exit" - ) - select opt in "${options[@]}" - do - case $opt in - "Don't Store Licence") - STORE_LICENCE=false - echo "STORE_LICENCE = $STORE_LICENCE" - ;; - "Store Licence") - STORE_LICENCE=true - echo "STORE_LICENCE = $STORE_LICENCE" - ;; - "Don't Store DeviceData") - STORE_DEVICEDATA=false - echo "STORE_DEVICEDATA = $STORE_DEVICEDATA" - ;; - "Store DeviceData") - STORE_DEVICEDATA=true - echo "STORE_DEVICEDATA = $STORE_DEVICEDATA" - ;; - "Store Containers") - STORE_CONTAINER=true - echo "STORE = $STORE" - ;; - "Dont Store Containers") - STORE_CONTAINER=false - echo "STORE = $STORE" - ;; - "Continue") - if [ "$STORE_LICENCE" == "" ]; then - echo "STORE_LICENCE = $STORE_LICENCE empty. Exit Script." - exit 1 - fi - - if [ "$STORE_DEVICEDATA" == "" ]; then - echo "STORE_DEVICEDATA = $STORE_DEVICEDATA empty. Exit Script." - exit 1 - fi - if [ "$STORE_CONTAINER" == "" ]; then - echo "STORE_DEVICEDATA = $STORE_CONTAINER empty. Exit Script." - exit 1 - fi - break - ;; "Exit") exit 1 break ;; - *) echo "invalid option $REPLY";; + *) echo "invalid option $REPLY" + ;; esac done - echo "Please check if the paths are correct." - echo "SourceLocation: '$SourceLocation' The directory you want to backup." - echo "TargetLocation: '$TargetLocation' the location you want to store your backup at." - echo "Storage Mode: '$STORAGE_MODE' is activated." - - echo ":" - read -r -p "Are you sure? [yes/No] all settings are correct - " response - if [[ "$response" =~ ^([yY][eE][sS]|[yY])$ ]] - then - exit 1; + if [ ${STORAGE_MODE} = "Manual" ]; + then + echo 'Do you wish to add stored licenses and PLC device data to this backup?' + PS3="Toggle your choice to overwrite settings loaded from config: " + options=( + "Toggle store SD_Licence" + "Toggle store PLCNEXTSTORE_Licence" + "Toggle store DeviceData" + "Toggle store Containers" + "Toggle store UNIX_PASSWORD_CHANGES" # Created root user, added groups etc. + "Toggle store PLCnext_ETC" # All modifications done to the /etc/plcnext directory + "Toggle store PLCnext_SYSTEM_UM" # Added roles and Permissions as well as Ldap Config + "Toggle store PLCnext_SYSTEM_SCM" # Service Manager changes to enable/disable System Features + "Toggle store PLCnext_SECURITY" # Certificates IdentityStores and Truststores + "Toggle store PLCnext_PROJECTS" # PCWE and other Project changes. + "Toggle store PLCNext_SERVICES" # Service Specific Settings + "Toggle store NETWORK" # Store your custom IP Configuration + "Toggle store SSH_KEYs" # Unix SSH Keys + "Toggle store INSTALLED_APPS" # + "Toggle store ALL_CONFIG" # Whole config directory + "Toggle store ALL_DATA" # this directory holds mostly session dependend data like PIDs, FW update Status etc. + "List all" + "Continue" + "Exit" + ) + select opt in "${options[@]}" + do + case $opt in + "Toggle store SD_Licence") + echo "Saving SD HW specific productiondata." + STORE_SD_LICENCE=$(Toggle ${STORE_SD_LICENCE}) + echo "STORE_SD_LICENCE = $STORE_SD_LICENCE" + ;; + + "Toggle store PLCNEXTSTORE_Licence") + echo "not implemented" + ;; + + "Toggle store DeviceData") + echo "Saving device specific productiondata." + echo "Needs Root privileges current user: $(whoami)" + STORE_DEVICEDATA=$(Toggle ${STORE_DEVICEDATA}) + echo "STORE_DEVICEDATA = $STORE_DEVICEDATA" + ;; + + "Toggle store Containers") + echo "Saving current state of $CONTAINER_ENGINE Containers" + echo "Needs Root privileges Currentuser:$(whoami)" + STORE_CONTAINER=$(Toggle ${STORE_CONTAINER}) + echo "STORE_CONTAINER = ${STORE_CONTAINER}" + ;; + "Toggle store UNIX_PASSWORD_CHANGES") + echo "Save Created root user, added groups etc." + STORE_UNIX_PASSWORD_CHANGES=$(Toggle ${STORE_UNIX_PASSWORD_CHANGES}) + echo "STORE_UNIX_PASSWORD_CHANGES = ${STORE_UNIX_PASSWORD_CHANGES}" + ;; + "Toggle store PLCnext_ETC") + echo "Save all modifications done to the /etc/plcnext directory " + echo "Needs ROOT privileges" + STORE_PLCnext_ETC=$(Toggle $STORE_PLCnext_ETC) + echo "STORE_PLCnext_ETC = $STORE_PLCnext_ETC" + ;; + + "Toggle store PLCnext_SYSTEM_UM") + echo "Save roles added via PLCnext UM, Permissions as well as Ldap Config" + STORE_PLCnext_SYSTEM_UM=$(Toggle $STORE_PLCnext_SYSTEM_UM) + echo "STORE_PLCnext_SYSTEM_UM = $STORE_PLCnext_SYSTEM_UM" + ;; + "Toggle store PLCnext_SYSTEM_SCM") + echo "Service Manager changes to enable/disable System Features" + STORE_PLCnext_SYSTEM_SCM=$(Toggle $STORE_PLCnext_SYSTEM_SCM) + echo "STORE_PLCnext_SYSTEM_SCM = $STORE_PLCnext_SYSTEM_SCM" + ;; + + "Toggle store PLCnext_SECURITY") + echo "Certificates IdentityStores and Truststores" + STORE_PLCnext_SECURITY=$(Toggle $STORE_PLCnext_SECURITY) + echo "STORE_PLCnext_SECURITY = $STORE_PLCnext_SECURITY" + ;; + "Toggle store PLCnext_PROJECTS") + echo "PLCnext Engineer Projects and other deployed ACF Components located at $PROJECTS" + STORE_PLCnext_PROJECTS=$(Toggle $STORE_PLCnext_PROJECTS) + echo "STORE_PLCnext_PROJECTS = $STORE_PLCnext_PROJECTS" + ;; + "Toggle store PLCNext_SERVICES") + echo "PLCnext Service Specific Settings" + STORE_PLCNext_SERVICES=$(Toggle $STORE_PLCNext_SERVICES) + echo "STORE_PLCNext_SERVICES = $STORE_PLCNext_SERVICES" + ;; + "Toggle store NETWORK") + echo "Store your custom IP Configuration" + STORE_NETWORK=$(Toggle $STORE_NETWORK) + echo "STORE_NETWORK = $STORE_NETWORK" + ;; + "Toggle store SSH_KEYs") + echo "Unix SSH Keys" + STORE_SSH_KEYs=$(Toggle $STORE_SSH_KEYs) + echo "STORE_SSH_KEYs = $STORE_SSH_KEYs" + ;; + "Toggle store INSTALLED_APPS") + echo "Saveapps installed via PLCnext Store or WBM" + STORE_INSTALLED_APPS=$(Toggle $STORE_INSTALLED_APPS) + echo "STORE_INSTALLED_APPS = $STORE_INSTALLED_APPS" + ;; + "Toggle store ALL_CONFIG") + echo "Whole PLCnext config directory located at $CONFIG" + STORE_ALL_CONFIG=$(Toggle $STORE_ALL_CONFIG) + echo "STORE_ALL_CONFIG = $STORE_ALL_CONFIG" + ;; + "Toggle store ALL_DATA") + echo "this directory holds mostly session dependend data like PIDs, FW update Status etc" + STORE_ALL_DATA=$(Toggle $STORE_ALL_DATA) + echo "STORE_ALL_DATA = $STORE_ALL_DATA" + ;; + "List all") + set | grep STORE + ;; + + "Continue") + set | grep STORE + read -r -p "Are you sure you wish to continue? [yes/No] all settings are correct + " response + if [[ "$response" =~ ^([yY][eE][sS]|[yY])$ ]] + then + break; + fi + ;; + "Exit") + exit 1 + break + ;; + + *) echo "invalid option $REPLY" + echo "Press Enter to recieve valid options again" + ;; + esac + done + + while true; do + echo "Please check if the paths are correct." + echo "SourceLocation: '$SourceLocation' The directory you want to backup." + echo "TargetLocation: '$TargetLocation' the location you want to store your backup at." + echo "Storage Mode: '$STORAGE_MODE' is activated." + + echo ":" + read -r -p "Are you sure? [yes/No] all settings are correct + " response + if [[ "$response" =~ ^([yY][eE][sS]|[yY])$ ]] + then + read -r -p "New SourceLocation\ + " SourceLocation + read -r -p "New TargetLocation\ + " SourceLocation + else + break + fi + done fi fi + +echo "Disk diagnostics:" +## +## Diagnostics to help verify that the backuppath matches the active partition. +df -h | grep rfs +#${SCRIPT_DIR}/../Diagnostic/checkActivePartition.sh + ## ## Verify available diskspace ## +echo "Verify available diskspace" case $STORAGE_MODE in "Upperdir") var=( $(du -s ${SourceLocation}/upperdir) ) SpaceRequired=${var[0]} ;; - "Changes") + "SettingsFile") var=( $(du -s ${SourceLocation}/upperdir/opt/plcnext) ) SpaceRequired=${var[0]} ;; @@ -259,28 +387,27 @@ case $STORAGE_MODE in SpaceRequired=${var[0]} ;; *) SpaceRequired=0 - ;; - + ;; esac -## -## Diagnostics to help verify that the backuppath matches the active partition. -## -df -ha | grep rfs -${SCRIPT_DIR}/../Diagnostic/checkActivePartition.sh + if [[ $STORE_CONTAINER == true ]]; then - echo Add Container Size + echo "Calculation of Container size not implemented" + echo "caution when multiple Containers depend on identical base layers" + echo "the resulting backup might be significantly larger then the space required on Disk" + echo "Add Container Size" var=0 SpaceRequired=$(($SpaceRequired + ${var[0]})) + VerifyUser fi if [[ $STORE_DEVICEDATA == true ]]; then - var=( $(du -s /etc/device_data)) + var=( $(du -s /etc/device_data) ) SpaceRequired=$(($SpaceRequired + ${var[0]})) + VerifyUser fi - -if [[ $STORE_LICENCE == true ]]; +if [[ $STORE_SD_LICENCE == true ]]; then var=( $(du -s ${SourceLocation}/licence) ) SpaceRequired=$(($SpaceRequired + ${var[0]})) @@ -299,20 +426,26 @@ else fi ### -### Start creating Backup +### Prepare Backup ### +echo "Prepare Backup" date > ${TargetLocation}/DATEFILE; -tar -cvpf ${TargetLocation}/${BACKUP_NAME}-${DATE}.tar -C ${TargetLocation} DATEFILE +BACKUPFILE_LIST=( "${TargetLocation}/DATEFILE" ) + +## File Delimiter to newline this is important to support filenames with whitespace. +IFS=$'\n' echo "STORAGE_MODE = $STORAGE_MODE" case "$STORAGE_MODE" in "Upperdir") - echo "Storing Upperdir" - tar -rpf ${TargetLocation}/${BACKUP_NAME}-${DATE}.tar -C ${SourceLocation} upperdir && echo "Done" + echo "Storing Upperdir this usually contains all userdata (except Containers)" + VerifyUser + BACKUPFILE_LIST+=( $(find ${SourceLocation}/upperdir)) + echo "Number of Entries:${#BACKUPFILE_LIST[@]}" ;; - "Changes") - echo -e "Store specified folders only:" + "SettingsFile") + echo -e "Store folders specified by Config file only:" (set -o posix ; set) | grep "STORE" | grep "true" if [ $INTERACTIVE = true ]; then @@ -324,47 +457,78 @@ case "$STORAGE_MODE" in exit 1; fi fi - ## Add Folders to Tar. + if $STORE_UNIX_PASSWORD_CHANGES; - then + then echo "Storing UNIX_PASSWORD_CHANGES" - tar -rpf ${TargetLocation}/${BACKUP_NAME}-${DATE}.tar -C ${SourceLocation} ${UNIX_PASSWORD_Changes[@]} && echo "Done" + VerifyUser + for Location in ${UNIX_PASSWORD_Changes[@]}; do + if [ -f ${SourceLocation}/${Location} ]; + then + BACKUPFILE_LIST+=( $(find ${SourceLocation}/${Location}) ) + fi + echo "Number of Entries:${#BACKUPFILE_LIST[@]}" + done + fi if $STORE_NETWORK; then echo "Storing Network Settings" - tar -rpf ${TargetLocation}/${BACKUP_NAME}-${DATE}.tar -C ${SourceLocation} ${NETWORK} && echo "Done" + + BACKUPFILE_LIST+=($(find ${SourceLocation}/${NETWORK}) ) + echo "Number of Entries:${#BACKUPFILE_LIST[@]}" + fi + + if $STORE_PLCnext_ETC; + then + echo "Storing upperdir/etc/plcnext" + VerifyUser + BACKUPFILE_LIST+=($(find ${SourceLocation}/${PLCnext_ETC}) ) + echo "Number of Entries:${#BACKUPFILE_LIST[@]}" fi if $STORE_SSH_KEYs; then echo "Storing SSH Keys" - tar -rpf ${TargetLocation}/${BACKUP_NAME}-${DATE}.tar -C ${SourceLocation} ${SSH_KEYs} && echo "Done" + VerifyUser + BACKUPFILE_LIST+=($(find ${SourceLocation}/${SSH_KEYs}) ) + echo "Number of Entries:${#BACKUPFILE_LIST[@]}" fi if $STORE_PLCnext_PROJECTS; then - echo "Storing PROJECTS" - tar -rpf ${TargetLocation}/${BACKUP_NAME}-${DATE}.tar -C ${SourceLocation} ${PROJECTS} && echo "Done" + echo "Storing PROJECTS" + BACKUPFILE_LIST+=( $(find ${SourceLocation}/${PROJECTS}) ) + echo "Number of Entries:${#BACKUPFILE_LIST[@]}" fi if $STORE_PLCnext_SYSTEM_UM; then - echo "Storing SYSTEM UM Settings" - tar -rpf ${TargetLocation}/${BACKUP_NAME}-${DATE}.tar -C ${SourceLocation} ${PLCnext_UM}&& echo "Done" + echo "Storing SYSTEM UM / UserManager Settings" + BACKUPFILE_LIST+=( $(find ${SourceLocation}/${PLCnext_UM}) ) + echo "Number of Entries:${#BACKUPFILE_LIST[@]}" fi if $STORE_PLCnext_SYSTEM_SCM; then echo "Storing SYSTEM SCM Settings" - tar -rpf ${TargetLocation}/${BACKUP_NAME}-${DATE}.tar -C ${SourceLocation} ${PLCnext_SCM} && echo "Done" + + if [ -d ${SourceLocation}/${PLCnext_SCM} ] ; + then + BACKUPFILE_LIST+=( $(find ${SourceLocation}/${PLCnext_SCM}) ) + echo "Number of Entries:${#BACKUPFILE_LIST[@]}" + fi fi if $STORE_PLCNext_SERVICES; then - echo "Storing SERVICE Settings" - tar -rpf ${TargetLocation}/${BACKUP_NAME}-${DATE}.tar -C ${SourceLocation} ${SERVICES} && echo "Done" - ### If required add keys for specific services + echo "Storing SERVICE Settings" + if [ -d ${SourceLocation}/${SERVICES} ]; + then + BACKUPFILE_LIST+=( $(find ${SourceLocation}/${SERVICES}) ) + echo "Number of Entries:${#BACKUPFILE_LIST[@]}" + fi + ### If required we could add keys for each specific services #STORE_PLCNext_SERVICES_Ehmi #STORE_PLCNext_SERVICES_Grpc #STORE_PLCNext_SERVICES_LinuxSyslog @@ -379,45 +543,59 @@ case "$STORAGE_MODE" in if $STORE_PLCnext_SECURITY; then - echo "Storing PLCnext_SECURITY directory" - tar -rpf ${TargetLocation}/${BACKUP_NAME}-${DATE}.tar -C ${SourceLocation} ${PLCnext_SECURITY} && echo "Done" + echo "Storing PLCnext_SECURITY directory" + if [ -d ${SourceLocation}/${PLCnext_SECURITY} ]; + then + BACKUPFILE_LIST+=($(find ${SourceLocation}/${PLCnext_SECURITY})) + echo "Number of Entries:${#BACKUPFILE_LIST[@]}" + fi fi if $STORE_INSTALLED_APPS; then echo "Storing INSTALLED_APPS" - tar -rpf ${TargetLocation}/${BACKUP_NAME}-${DATE}.tar -C ${SourceLocation} ${INSTALLED_APPS} && echo "Done" + + BACKUPFILE_LIST+=($(find ${SourceLocation}/${INSTALLED_APPS}) ) + BACKUPFILE_LIST+=( $(find ${SourceLocation}/${INSTALLED_APP_STATUS}) ) + echo "Number of Entries:${#BACKUPFILE_LIST[@]}" fi + if $STORE_ALL_CONFIG; then - echo "Storing CONFIG directory" - tar -rpf ${TargetLocation}/${BACKUP_NAME}-${DATE}.tar -C ${SourceLocation} ${CONFIG} && echo "Done" + echo "Storing PLCnext CONFIG directory" + BACKUPFILE_LIST+=( $(find ${SourceLocation}/${CONFIG}) ) + echo "Number of Entries:${#BACKUPFILE_LIST[@]}" fi if $STORE_ALL_DATA; then - echo "Storing DATA directory" - tar -rpf ${TargetLocation}/${BACKUP_NAME}-${DATE}.tar -C ${SourceLocation} ${DATA} && echo "Done" + echo "Storing PLCnext DATA directory" + BACKUPFILE_LIST+=( $(find ${SourceLocation}/${DATA}) ) + echo "Number of Entries:${#BACKUPFILE_LIST[@]}" fi ;; "PCWE") - echo "Storing PCWE directory" - tar -rpf ${TargetLocation}/${BACKUP_NAME}-${DATE}.tar -C ${SourceLocation} ${PROJECTS} && echo "Done" + echo "Storing PLCnext Engineer project directory" + BACKUPFILE_LIST+=( $(find ${SourceLocation}/${PROJECTS}) ) + echo "Number of Entries:${#BACKUPFILE_LIST[@]}" ;; esac -if [ $STORE_DEVICEDATA = true ]; +if [[ $STORE_DEVICEDATA == true ]]; then + echo "WATCH OUT! Stored DeviceData are bound to the Hardware of the PLC. Do not use this backup for another PLC!" - echo "Storing DEVICEDATA" - tar -rpf ${TargetLocation}/${BACKUP_NAME}-${DATE}.tar -C / ${DEVICEDATA} && echo "Done" + echo "Storing DEVICEDATA" + + BACKUPFILE_LIST=( "${BACKUPFILE_LIST[@]}" $(find /${DEVICEDATA}) ) + echo "Number of Entries:${#BACKUPFILE_LIST[@]}" fi -if [[ $STORE_LICENCE == true ]]; +if [[ $STORE_SD_LICENCE == true ]]; then echo "WATCH OUT! Stored Licenses are bound to the Hardware ID. Do not use this backup for another PLC / SD" @@ -437,7 +615,9 @@ then fi echo "Adding Licence, remember to unzip with caution!" echo "Restoring this backup might void an SD-Cards License if overwritten." - tar -rpf ${TargetLocation}/${BACKUP_NAME}-${DATE}.tar -C ${SourceLocation} ${INSTALLED_LICENSE_FILES} && echo "Done" + + BACKUPFILE_LIST+=( $(find ${SourceLocation}/${INSTALLED_LICENSE_FILES}) ) + echo "Number of Entries:${#BACKUPFILE_LIST[@]}" fi if [[ $STORE_CONTAINER == true ]]; @@ -445,7 +625,7 @@ then echo "Storing Containers" ## Get a list of all containers CONTAINERS=($($CONTAINER_ENGINE container ls -aq)) - mkdir ${SourceLocation}Containers + mkdir ${SourceLocation}/Containers # Export Containers and add them to the backup.tar for CONTAINER in "${CONTAINERS[@]}" do @@ -455,17 +635,65 @@ then echo "$CONTAINER_ENGINE run -v XX -p xxx ... " ## Need to stop continers? $CONTAINER_ENGINE export $CONTAINER --output "${SourceLocation}/Containers/$CONTAINER.tar" - tar -rpf ${TargetLocation}/${BACKUP_NAME}-${DATE}.tar -C ${SourceLocation} "Containers/$CONTAINER.tar" + + BACKUPFILE_LIST+=( $(find ${SourceLocation}/Containers/$CONTAINER.tar) ) + echo "Number of Entries:${#BACKUPFILE_LIST[@]}" rm "${SourceLocation}/Containers/$CONTAINER.tar" done && echo "Done" fi -if [ -f "${TargetLocation}/${BACKUP_NAME}-${DATE}.tar" ]; +echo "###" +echo "### Prepare Backup" +echo "###" +BACKUPFILE_LIST+=( "${TargetLocation}/ListOfFiles-${DATE}.txt" ) +BACKUPFILE_LIST+=( "${TargetLocation}/ListWithChecksum-${DATE}.txt" ) + +echo "Number of Folders/Files:${#BACKUPFILE_LIST[@]}" +printf "%s\n" "${BACKUPFILE_LIST[@]}" +printf "%s\n" "${BACKUPFILE_LIST[@]}" > ${TargetLocation}/ListOfFiles-${DATE}.txt +declare -a ListWithChecksum + +echo "###" +echo "### Create Checksum" +echo "###" +for file in "${BACKUPFILE_LIST[@]}"; do + if [[ -d ${file} ]]; + then + #echo "${file} : No hash its a directory" + : + elif [[ -f ${file} ]]; + then + #echo "${file} is a file" + ListWithChecksum+=( "$(openssl sha256 ${file})" ) + else + echo "${file} is not valid" + fi +done +printf "%s\n" "${ListWithChecksum[@]}" > "${TargetLocation}/Checksum-${DATE}.txt" +echo "Number of Files:${#ListWithChecksum[@]}" +cat ${TargetLocation}/Checksum-${DATE}.txt + +echo "###" +echo "### Create Backup" +echo "###" +echo "Create tar.gz" +tar cpzv --keep-directory-symlink --no-recursion -f "${TargetLocation}/${BACKUP_NAME}-${DATE}.tar.gz" -T "${TargetLocation}/ListOfFiles-${DATE}.txt" + +unset IFS +echo "###" +echo "### Validate Backup" +echo "###" + +if [ -f "${TargetLocation}/${BACKUP_NAME}-${DATE}.tar.gz" ]; then - chown admin:plcnext ${TargetLocation}/${BACKUP_NAME}-*.tar + chown admin:plcnext ${TargetLocation}/${BACKUP_NAME}-${DATE}.tar.gz echo "Contents of Backup:" - tar -tvf "${TargetLocation}/${BACKUP_NAME}-${DATE}.tar" | grep "/$" + tar tvP -f "${TargetLocation}/${BACKUP_NAME}-${DATE}.tar.gz" | grep "/$" else echo "No backup created please fix your input data." exit 1 -fi \ No newline at end of file +fi + +### +### StoreBackup Remotly +### diff --git a/Backup/backupSettings.sh b/Backup/backupSettings.sh index dadd577..eef4bfe 100644 --- a/Backup/backupSettings.sh +++ b/Backup/backupSettings.sh @@ -5,15 +5,19 @@ # * Licensed under the MIT. See LICENSE file in the project root for full license information. # * # ****************************************************************************** -STORAGE_MODE="PCWE" +STORAGE_MODE="PCWE" # ### ### Located on the SD ### -STORE_LICENCE=false # SD card Licenses +STORE_SD_LICENCE=false # SD card Licence INSTALLED_LICENSE_FILES="licence" + +STORE_PLCNEXTSTORE_LICENCE=false # PLCnext Store Licence files +INSTALLED_LICENSE_FILES="NotImplemented" + ### -### Located on InternalStorage +### Located on internal storage ### STORE_DEVICEDATA=false # Production Data of PLC. DEVICEDATA="etc/device_data" @@ -21,9 +25,11 @@ DEVICEDATA="etc/device_data" ### ### Located on Upperdir ### -STORE_UNIX_PASSWORD_CHANGES=true # Created root user, added groups etc. -UNIX_PASSWORD_Changes=( "/etc/shadow" "/etc/gshadow" "/etc/group" ) # created root user or admin unix pw was chaged. +### Needs Root privileges +STORE_UNIX_PASSWORD_CHANGES=false # Created root user, added groups etc. +UNIX_PASSWORD_Changes=( "upperdir/etc/shadow" "upperdir/etc/gshadow" "upperdir/etc/group" ) # created root user or admin unix pw was chaged. +### Needs Root privileges STORE_PLCnext_ETC=false # All modifications done to the /etc/plcnext directory PLCnext_ETC="upperdir/etc/plcnext" @@ -43,20 +49,36 @@ PROJECTS="upperdir/opt/plcnext/projects" STORE_PLCNext_SERVICES=true # Service Specific Settings SERVICES="upperdir/opt/plcnext/config/Services" +# STORE_PLCNext_SERVICES_Ehmi +# STORE_PLCNext_SERVICES_Grpc +# STORE_PLCNext_SERVICES_LinuxSyslog +# STORE_PLCNext_SERVICES_OpcUA +# STORE_PLCNext_SERVICES_PLCnextStore +# STORE_PLCNext_SERVICES_PortAuthentication +# STORE_PLCNext_SERVICES_Spm +# STORE_PLCNext_SERVICES_SpnsProxy +# STORE_PLCNext_SERVICES_Syslog +# STORE_PLCNext_SERVICES_Wcm +# STORE_PLCnext_STORE_Licenses + STORE_NETWORK=true # Store your custom IP Configuration NETWORK="upperdir/etc/network" -STORE_SSH_KEYs=true # Unix SSH Keys +### Needs Root privileges +STORE_SSH_KEYs=false # Unix SSH Keys SSH_KEYs="upperdir/etc/ssh" -STORE_INSTALLED_APPS=false # -INSTALLED_APPS="upperdir/opt/plcnext/appshome" +STORE_INSTALLED_APPS=true # +INSTALLED_APPS="upperdir/opt/plcnext/installed_apps" +INSTALLED_APP_STATUS="upperdir/opt/plcnext/appshome" +### Needs Root privileges (PnS NBHinfo, RPCState, etc..) STORE_ALL_CONFIG=false # Whole config directory CONFIG="upperdir/opt/plcnext/config" STORE_ALL_DATA=false # this directory holds mostly session dependend data like PIDs, FW update Status etc. DATA="upperdir/opt/plcnext/data" +### Needs Root privileges STORE_CONTAINER=false CONTAINER_ENGINE=podman \ No newline at end of file From 77f6b42c7e15f0842d553c96fa72d6742cdc66c3 Mon Sep 17 00:00:00 2001 From: Oliver Warneke Date: Tue, 1 Mar 2022 11:15:02 +0100 Subject: [PATCH 4/4] Add Watchdog Settings to Backup --- Backup/backupSD.sh | 16 +++++++++++++++- Backup/backupSettings.sh | 5 ++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/Backup/backupSD.sh b/Backup/backupSD.sh index 4a9a242..562a8a1 100644 --- a/Backup/backupSD.sh +++ b/Backup/backupSD.sh @@ -275,7 +275,11 @@ then STORE_PLCnext_SYSTEM_SCM=$(Toggle $STORE_PLCnext_SYSTEM_SCM) echo "STORE_PLCnext_SYSTEM_SCM = $STORE_PLCnext_SYSTEM_SCM" ;; - + "Toggle store PLCnext_SYSTEM_WATCHDOG") + echo "Behavior of PLC after Watchdog. Restart and RUN or STOP after a critical issue occured." + PLCnext_SYSTEM_WATCHDOG=$(Toggle $PLCnext_SYSTEM_WATCHDOG) + echo "PLCnext_SYSTEM_WATCHDOG = $PLCnext_SYSTEM_WATCHDOG" + ;; "Toggle store PLCnext_SECURITY") echo "Certificates IdentityStores and Truststores" STORE_PLCnext_SECURITY=$(Toggle $STORE_PLCnext_SECURITY) @@ -520,6 +524,16 @@ case "$STORAGE_MODE" in fi fi + if $STORE_PLCnext_SYSTEM_WATCHDOG; + then + echo "Storing SYSTEM Watchdog Settings" + + if [ -d ${SourceLocation}/${PLCnext_WATCHDOG} ] ; + then + BACKUPFILE_LIST+=( $(find ${SourceLocation}/${PLCnext_WATCHDOG}) ) + echo "Number of Entries:${#BACKUPFILE_LIST[@]}" + fi + fi if $STORE_PLCNext_SERVICES; then echo "Storing SERVICE Settings" diff --git a/Backup/backupSettings.sh b/Backup/backupSettings.sh index eef4bfe..b7bb310 100644 --- a/Backup/backupSettings.sh +++ b/Backup/backupSettings.sh @@ -40,6 +40,9 @@ PLCnext_UM="upperdir/opt/plcnext/config/System/Um/" STORE_PLCnext_SYSTEM_SCM=true # Service Manager changes to enable/disable System Features PLCnext_SCM="upperdir/opt/plcnext/config/System/Scm/" +STORE_PLCnext_SYSTEM_WATCHDOG=true # Service Manager changes to enable/disable System Features +PLCnext_WATCHDOG="upperdir/opt/plcnext/config/System/Watchdog/" + STORE_PLCnext_SECURITY=true # Certificates IdentityStores and Truststores PLCnext_SECURITY="upperdir/opt/plcnext/Security" @@ -58,7 +61,7 @@ SERVICES="upperdir/opt/plcnext/config/Services" # STORE_PLCNext_SERVICES_Spm # STORE_PLCNext_SERVICES_SpnsProxy # STORE_PLCNext_SERVICES_Syslog -# STORE_PLCNext_SERVICES_Wcm +# STORE_PLCNext_SERVICES_Wcm # Certificates and additional nginx location config # STORE_PLCnext_STORE_Licenses STORE_NETWORK=true # Store your custom IP Configuration