Ouais autant passer sur une version docker gérée manuellement.
Je ne le conseille pas au débutants mais ça a été mon chox
y a toujours une solution, il suffit de la connaitre
Et je n’aime pas quand ça me résiste !
Le problème avec un docker géré manuellement, c’est que j’ai encore moins de backup auto de ma config ? je ne peu plus utiliser les extensions de module HAOS classique ? ( Node REd, Cloudflared, nginx, google drive backup …
Sinon une idée de la raison des id différents ?
Oui bien sûr …
Voici les sources de HAOS : GitHub - home-assistant/operating-system: 🔰 Home Assistant Operating System
pas loin, j’en étais ici :
le plugins autoackup est dispo sous docker aussi et à toi la charge de sauvegarder les données de tes conteneurs, un bête tar dans une crontab de mon coté
Bonjour à tous et merci pour vos échanges,
J’ai trouvé ma solution et je l’ai optimisée un peu pour la rendre pratique alors je vous partages cela, certain et trouverons peut-être une solution d’autre des piste dans leur propre recherches … enfin bon si cela peut aider.
En quoi et pourquoi j’ai changé d’objectif: faire un dossier totalement en dehors des dossiers par defaut de HAOS (addon_Configs, addons, backup, media, share contenu dans /mnt/data/supervisor/) il est compliqué et fastidieux de modifier toutes les configs pour pouvoir monter un dossier non prévu et ceux à chaque mise à jour sachant que les fichier de config des conteneur de modules sont géré par HA via un fichier de config spécifique (config.yaml) et non par un fichier de config de container classic (config.v2.json).
Je rappelle mon besoin : stocker les vidéos de surveillance dans un dossier qui n’est pas sauvegarder par les sauvegardes complète… du coup en réfléchissant un peu, j’ai réalisée que le meilleur dossier à utiliser pour l’exclure des sauvegardes est le dossiers sauvegarde lui-même … et que dans le cas ou un module complémentaire ni ai pas accès il faudrait juste modifier le paramètre map de config.yaml (''map": [ …, ''backup:rw", …]).
Quoi qu’il en soit il suffit juste de le monter dans le container homeassistant pour qu’il puisse y avoir accès (car par defaut home assistant n’a pas accès au dossier backup … étonnant).
et ensuite de modifier un peu le config yaml pour donner les droit sur le dossier et aussi l’afficher dans les media.
Voici le petit script bash, à executer après chaque maj core ou os, en se connectant via SSH (en mode root). Perso j’ai mis le script dans le dossier share de home assistant comme cela je peu l’editer facilement via samba sur pc / studio code sur HA,…)
/share/mounts_BackupAndData_to_HomeAssistant_container.sh :
#!/bin/bash
# copier le script dans l'un des dossiers [addon_Configs,addons,backup,media,share]
#
#
# bash /mnt/data/supervisor/share/mounts_BackupAndData_to_HomeAssistant_container.sh
#
#
#
#==================================================
# SETTINGS:
# indiquer le dossier du script au choix : [addon_Configs,addons,backup,media,share] :
_folder="share"
#indiquer le sous dossier pour enregistrer les fichiers et logs
_subFolder="mounts"
#choississez les dossier à monter
_mountBackup=true
_mountData=true
#==================================================
# ADVANCED settings
_supervisorPath="/mnt/data/supervisor/"
_containersPath="/var/lib/docker/containers/"
_containersSecondaryPath="/mnt/data/docker/containers/"
_haContainerName="homeassistant"
_logFile="_mounts_BackupAndData.log"
_objName="MountPoints"
_objBackupName="/backup"
_objBackup='{"Source":"/mnt/data/supervisor/backup","Destination":"/backup","RW":true,"Name":"","Driver":"","Type":"bind","Propagation":"rprivate","Spec":{"Type":"bind","Source":"/mnt/data/supervisor/backup","Target":"/backup"},"SkipMountpointCreation":true}'
_objDataName="/data"
_objData='{"Source":"/mnt/data/supervisor","Destination":"/data","RW":true,"Name":"","Driver":"","Type":"bind","Relabel":"rw,slave","Propagation":"slave","Spec":{"Type":"bind","Source":"/mnt/data/supervisor","Target":"/data","BindOptions":{"Propagation":"slave"}},"SkipMountpointCreation":true}'
#
#==================================================
#==================================================
#folder creation
_destFolder="${_supervisorPath}${_folder}/${_subFolder}/"
mkdir "${_destFolder}" 2>/dev/null
#==================================================
#==================================================
clear
{
echo -e "\n\n"
echo "===================================================="
echo ">> config.v2.json add BACKUPS & DATA mount points <<"
echo "===================================================="
_date=$(date +"%Y-%m-%d_%H-%M-%S")
echo "${_date}"
#
# Verif module jq requis (jq --version) ( https://jqlang.github.io/jq/manual/ )
#
_jq=$(jq --version 2>/dev/null)
if [ -z "${_jq}" ]
then
echo -e "\n!!! jq tools not found : ABORTING...\n" && exit 0
else
echo "jq tools OK : ${_jq}"
fi
#
#recup et veif container ID
#
container="docker ps --no-trunc -aqf name=${_haContainerName}"
_id=$($container 2>/dev/null)
if [ -z "${_id}" ]
then
echo -e "\n!!! Container ID not found for homeassistant : ABORTING...\n" && exit 0
else
echo "Container ID => ${_id}"
fi
#
# copy et backup du fichier dans share
#
_srcJson="${_containersPath}$_id/config.v2.json"
echo "Source JSON path => ${_srcJson}"
_wipJson="${_destFolder}config.v2.json"
echo "WIP Json path => ${_wipJson}"
cp ${_srcJson} ${_wipJson}".backup.original_"${_date}"_.json"
cp ${_srcJson} ${_wipJson}
chmod 777 -R ${_destFolder}
echo -e "\n=> config.v2.json and backup create in ${_folder}/${_subFolder} folder\n"
#
# check json et presence object mount
#
_mountObject=$(cat ${_wipJson} | jq ".${_objName}")
if [ "${_mountObject}" == "null" ]
then
echo -e "\n!!! ${_objName} not found in json : ABORTING...\n"
exit 0
else
echo "=> ${_objName} OK ..."
fi
#
echo -e "\nSTARTING update ...\n"
#
# Verif et ajout BACKUP obj to json ---------------------------------------------------------------------------------------------------------------------------
#
echo "------ BACKUP: ------"
if [ "${_mountBackup}" == true ]
then
_bkpObj=$(cat ${_wipJson} | jq ".${_objName}.[\"${_objBackupName}\"]")
tmp=$(mktemp)
if [ "${_bkpObj}" == "null" ]
then
echo ">> ${_objName}.[\"${_objBackupName}\"] not found in json : CREATING..."
#---creation et verif
_jqCreate=$(jq ".${_objName} += {\"${_objBackupName}\":${_objBackup}}" ${_wipJson} > "$tmp" && mv "$tmp" ${_wipJson} ) || _jqCreate="jq_ERROR"
if [ "${_jqCreate}" == "jq_ERROR" ]
then
echo -e "\n!!! > creation ERROR : ABORTING...\n" && exit 1
else
echo " > creation OK"
fi
#-----
else
echo ">> ${_objName}.[\"${_objBackupName}\"] in json : UPDATING..."
#---update et verif
_jqUpdate=$(jq ".${_objName}.[\"${_objBackupName}\"] = ${_objBackup}" ${_wipJson} > "$tmp" && mv "$tmp" ${_wipJson} ) || _jqUpdate="jq_ERROR"
if [ "${_jqUpdate}" == "jq_ERROR" ]
then
echo -e "\n!!! > update ERROR : ABORTING...\n" && exit 1
else
echo " > update OK"
fi
#-----
fi
else
echo "(!) Mount of ${_objName}.[\"${_objBackupName}\"] diseabled by user > skipping"
fi
#
#
# Verif et ajout DATA obj to json ---------------------------------------------------------------------------------------------------------------------------
#
echo -e "\n------ DATA: ------"
if [ "${_mountData}" == true ]
then
_dataObj=$(cat ${_wipJson} | jq ".${_objName}.[\"${_objDataName}\"]")
tmpB=$(mktemp)
if [ "${_dataObj}" == "null" ]
then
echo ">> ${_objName}.[\"${_objDataName}\"] not found in json : CREATING..."
#gerer creation ici
_jqCreate=$(jq ".${_objName} += {\"${_objDataName}\":${_objData}}" ${_wipJson} > "$tmpB" && mv "$tmpB" ${_wipJson} ) || _jqCreate="jq_ERROR"
if [ "${_jqCreate}" == "jq_ERROR" ]
then
echo -e "\n!!! > creation ERROR : ABORTING...\n" && exit 1
else
echo " > creation OK"
fi
#-----
else
echo ">> ${_objName}.[\"${_objDataName}\"] in json : UPDATING..."
#gérer update ici
_jqUpdate=$(jq ".${_objName}.[\"${_objDataName}\"] = ${_objData}" ${_wipJson} > "$tmpB" && mv "$tmpB" ${_wipJson} ) || _jqUpdate="jq_ERROR"
if [ "${_jqUpdate}" == "jq_ERROR" ]
then
echo -e "\n!!! > update ERROR : ABORTING...\n" && exit 1
else
echo " > update OK"
fi
#-----
fi
else
echo "(!) Mount of ${_objName}.[\"${_objDataName}\"] diseabled by user > skipping"
fi
#
#---------------------------------------------------------------------------------------------------------------------------
#
# Minify JSON
#
echo -e "\n>> Update COMPLETED\n>> JSon Minification"
tmpC=$(mktemp)
jq -r tostring ${_wipJson} > "$tmpC" && mv "$tmpC" ${_wipJson}
#
# JSON validation
#
echo ">> Validating JSON..."
jsonString=$(jq -r tostring ${_wipJson})
if jq empty ${_wipJson}
then
echo " > JSON is valid !"
else
echo -e "\n (!) JSON is invalid > ABORTING...\n" && exit 1
fi
#
# Query user for final operation
#
echo ""
while true; do
read -p "Do you wish to override original HA container config with new one ? " yn
case $yn in
[Yy]* ) break;;
[Nn]* ) echo -e "\n(!) Process CANCELED by user ...\n" && exit;;
* ) echo "Please answer (y)yes or (n)no.";;
esac
done
echo -e "\nApply updated config...\n"
echo "3..."
docker stop ${_id}
echo "2..."
cp ${_wipJson} ${_srcJson}
_secondSrcJson="${_containersSecondaryPath}$_id/config.v2.json"
echo "1..."
cp ${_wipJson} ${_secondSrcJson}
sleep 3
while true; do
read -p "original HA container config file overrided , REBOOT ? " yn
case $yn in
[Yy]* ) reboot; break;;
[Nn]* ) echo -e "\n(!) Reboot CANCELED by user ...\n" && exit;;
* ) echo "Please answer (y)yes or (n)no.";;
esac
done
#
} 2>&1 | tee -a ${_destFolder}${_logFile}
pour le lancer il faudra donc exécuter en ssh (vrai ssh en mode root pas l’extension) :
bash /mnt/data/supervisor/share/mounts_BackupAndData_to_HomeAssistant_container.sh
Il est plus ou moins configurable, testé en l’état. Il monte /backup et /data dans homeassistant mais vous pouvez les activer séparément et même rajouter des dossier autres … Il est écrit pour valider les modif et ne rien copier avant validation du json et encore moins sans votre confirmation final en fin de process. De plus il créer un log et un backup du fichier d’origine dans un sous dossier /share/mounts/.
Et ensuite il faut juste créer un dossier dans backup , perso j’ai opté pour /backup/not_saved_area/ et un sous dossier /backup/not_saved_area/ _CamVideoRecords
et les intégrer dans le configuration.yaml:
homeassistant:
# chemin authorisés :
allowlist_external_dirs:
- /backup/
- /backup/_not_saved_area_/
- /backup/_not_saved_area_/_CamVideoRecords/
#additionnal media directories
media_dirs:
local: /media #pour conserver le dossier original
video_records: /backup/_not_saved_area_/_CamVideoRecords/
Seul point important il faut commenter les lignes avant la mise à jour et les décommenter après sinon HA redémarrera en safe_mode tant que le script de montage de dossier n’a pas été executé
homeassistant:
# chemin authorisés :
allowlist_external_dirs:
#- /backup/
#- /backup/_not_saved_area_/
#- /backup/_not_saved_area_/_CamVideoRecords/
#additionnal media directories
media_dirs:
local: /media #pour conserver le dossier original
#video_records: /backup/_not_saved_area_/_CamVideoRecords/
Perso j’utilise un script python (via l’extension pyscript) avec 2 petit boutons avant /après :
type: horizontal-stack
cards:
- show_name: true
show_icon: true
type: button
tap_action:
action: perform-action
perform_action: pyscript.manage_configuration_yaml_for_update
data:
new_state: true
target: {}
name: Prepare Config.YAML BEFORE update
icon_height: 50px
icon: mdi:pound-box
card_mod:
style: |
ha-card {
font-size: 1em !important;
padding: 0.5% !important;
}
span {
margin-top: 0 !important;
}
- show_name: true
show_icon: true
type: button
tap_action:
action: perform-action
perform_action: pyscript.manage_configuration_yaml_for_update
data:
new_state: true
target: {}
icon_height: 50px
icon: mdi:pound-box
name: Restore Config.YAML changes AFTER update
card_mod:
style: |
ha-card {
font-size: 1em !important;
padding: 0.5% !important;
}
span {
margin-top: 0 !important;
}
et le script python qui va avec : ( j’ai enlevé la fonction de log car lié à d’autre scripts)
il génère un backup du fichier configuration.yaml avant modif
# script python pour modifier le fichier configuration.yaml
# et désactiver les dossiers faisant appel à /backup ou autre
#
#exemple :
#action: pyscript.prepare_configuration_yaml_for_update
#data:
# new_state: True
#
# True desactive les dossiers montés // False les réactives
import sys
if "/config/pyscript_modules" not in sys.path:
sys.path.append("/config/pyscript_modules")
import yaml
import os
import string
import datetime
from random import randrange
@service
def manage_configuration_yaml_for_update (new_state=None):
# Set du fichier à traiter
config_file = '/config/configuration.yaml'
# préparation des règles à commenter [0] > [1] pour desactiver et [1] > [0] pour réactiver
modifE = [' - /backup/','#- /backup/']
modifF = [' - /backup/_not_saved_area_/','#- /backup/_not_saved_area_/']
modifG = [' - /backup/_not_saved_area_/_CamVideoRecords/','#- /backup/_not_saved_area_/_CamVideoRecords/']
modifH = [' video_records: /backup/_not_saved_area_/_CamVideoRecords/','#video_records: /backup/_not_saved_area_/_CamVideoRecords/']
toSet = [modifE,modifF,modifG,modifH]
# prepa nom de backup
modifiedTime = os.path.getmtime(config_file)
timeStamp = datetime.datetime.fromtimestamp(modifiedTime).strftime("%Y-%m-%d_%Hh%Mm%S")
fileNameExt = os.path.splitext(config_file)
backupName = fileNameExt[0]+'_BACKUP_'+timeStamp+fileNameExt[1]
if new_state == None:
logger.warning("===== comment boolean required in data to proceed...")
else:
# backup
os.system('cp '+config_file+' '+backupName )
# Load the configuration file and get content as string
fileDesc = os.open(config_file, os.O_RDONLY)
f_size = os.path.getsize(config_file)
f_str = os.read(fileDesc, f_size)
os.close( fileDesc )
# modification du content (du string)
n_str = f_str
for _updt in toSet:
if new_state == True:
n_str = n_str.replace(_updt[0].encode(), _updt[1].encode())
else:
n_str = n_str.replace(_updt[1].encode(), _updt[0].encode())
# clear file content
fileClear = os.open(config_file, os.O_TRUNC )
os.close(fileClear)
# reecriture dans fichier de la config modifiée
fileDescB = os.open(config_file, os.O_WRONLY )
os.write(fileDescB, n_str)
os.close(fileDescB)
En espérant que cela puisse apporter des piste ou soluce à qu’un d’autre
Pas étonnant, avec une faille, tu pourrais mettre HA en vrac et en plus supprimer les backups. Il faudrait pouvoir y accéder depuis HA uniquement en read-only mais bon c’est certainement plus simple de bloquer l’accès.
Hello,
Bien vu, je ne l’avais pas envisagé ce risque du coup voici le script revue pour monter un sous dossier dans le dossier backup :
(le nouveaux script contient toujours les commandes pour monter backup et data, mais elles sont désactivées)
résultats :
- les module ayant accès à /backup on accès à ce sous-dossier
- ce sous dossier est naturellement exclu des sauvegardes pour les data encombrantes ou superflu
- HA (les utilisateurs) ne peuvent pas remonter dans /backup
en plus un script pour restaurer un config.v2.json modifié
ADD_mountPoints.sh
#!/bin/bash
#
# Script automatisant la montée d'un dossier (mount point) dans le fichier config.v2.json
# de configuration du container (docker) home assistant
#
# copier le script dans l'un des dossiers [addon_Configs,addons,backup,media,share]
#
#
# bash /mnt/data/supervisor/share/mounts_BackupAndData_to_HomeAssistant_container.sh
#
# mounts_BackupAndData_to_HomeAssistant_container.sh change to ADD_mountPoints.sh
# >> bash /mnt/data/supervisor/share/ADD_mountPoints.sh
#
#==================================================
# SETTINGS:
# indiquer le dossier du script au choix : [addon_Configs,addons,backup,media,share] :
_folder="share"
#indiquer le sous dossier pour enregistrer les fichiers et logs
_subFolder="mounts"
#choississez les dossiers à monter :
_mountBackup=false #/backup
_mountData=false #/data
_mountSubBackup=true #/backup/_not_saved_area_/
#==================================================
# ADVANCED settings
_supervisorPath="/mnt/data/supervisor/"
_containersPath="/var/lib/docker/containers/"
_containersSecondaryPath="/mnt/data/docker/containers/"
_haContainerName="homeassistant"
_logFile="_mounts_BackupAndData.log"
_objName="MountPoints"
_objBackupName="/backup"
_objBackup='{"Source":"/mnt/data/supervisor/backup","Destination":"/backup","RW":true,"Name":"","Driver":"","Type":"bind","Propagation":"rprivate","Spec":{"Type":"bind","Source":"/mnt/data/supervisor/backup","Target":"/backup"},"SkipMountpointCreation":true}'
_objDataName="/data"
_objData='{"Source":"/mnt/data/supervisor","Destination":"/data","RW":true,"Name":"","Driver":"","Type":"bind","Relabel":"rw,slave","Propagation":"slave","Spec":{"Type":"bind","Source":"/mnt/data/supervisor","Target":"/data","BindOptions":{"Propagation":"slave"}},"SkipMountpointCreation":true}'
_objSubBackupName="/_not_saved_area_"
_objSubBackup='{"Source":"/mnt/data/supervisor/backup/_not_saved_area_","Destination":"/_not_saved_area_","RW":true,"Name":"","Driver":"","Type":"bind","Propagation":"rprivate","Spec":{"Type":"bind","Source":"/mnt/data/supervisor/backup/_not_saved_area_","Target":"/_not_saved_area_"},"SkipMountpointCreation":false}'
#
#==================================================
#==================================================
#folder creation
_destFolder="${_supervisorPath}${_folder}/${_subFolder}/"
mkdir "${_destFolder}" 2>/dev/null
#==================================================
#==================================================
clear
{
echo -e "\n\n"
echo "================================================================="
echo ">> HA container config.v2.json add BACKUPS & DATA mount points <<"
echo "================================================================="
_date=$(date +"%Y-%m-%d_%H-%M-%S")
echo "${_date}"
#
# Verif module jq requis (jq --version) ( https://jqlang.github.io/jq/manual/ )
#
_jq=$(jq --version 2>/dev/null)
if [ -z "${_jq}" ]
then
echo -e "\n!!! jq tools not found : ABORTING...\n" && exit 0
else
echo "jq tools OK : ${_jq}"
fi
#
#recup et verif container ID
#
container="docker ps --no-trunc -aqf name=${_haContainerName}"
_id=$($container 2>/dev/null)
if [ -z "${_id}" ]
then
echo -e "\n!!! Container ID not found for homeassistant : ABORTING...\n" && exit 0
else
echo "Container ID => ${_id}"
fi
#
# copy et backup du fichier dans share
#
_srcJson="${_containersPath}$_id/config.v2.json"
echo "Source JSON path => ${_srcJson}"
_wipJson="${_destFolder}config.v2.json"
echo "WIP Json path => ${_wipJson}"
cp ${_srcJson} ${_wipJson}".backup.original_"${_date}"_.json"
cp ${_srcJson} ${_wipJson}
chmod 777 -R ${_destFolder}
echo -e "\n=> config.v2.json and backup create in ${_folder}/${_subFolder} folder\n"
#
# check json et presence object mount
#
_mountObject=$(cat ${_wipJson} | jq ".${_objName}")
if [ "${_mountObject}" == "null" ]
then
echo -e "\n!!! ${_objName} not found in json : ABORTING...\n"
exit 0
else
echo "=> ${_objName} OK ..."
fi
#
echo -e "\nSTARTING update ...\n"
#
# Verif et ajout BACKUP obj to json ---------------------------------------------------------------------------------------------------------------------------
#
echo "------ BACKUP: ------"
if [ "${_mountBackup}" == true ]
then
_bkpObj=$(cat ${_wipJson} | jq ".${_objName}.[\"${_objBackupName}\"]")
tmp=$(mktemp)
if [ "${_bkpObj}" == "null" ]
then
echo ">> ${_objName}.[\"${_objBackupName}\"] not found in json : CREATING..."
#---creation et verif
_jqCreate=$(jq ".${_objName} += {\"${_objBackupName}\":${_objBackup}}" ${_wipJson} > "$tmp" && mv "$tmp" ${_wipJson} ) || _jqCreate="jq_ERROR"
if [ "${_jqCreate}" == "jq_ERROR" ]
then
echo -e "\n!!! > creation ERROR : ABORTING...\n" && exit 1
else
echo " > creation OK"
fi
#-----
else
echo ">> ${_objName}.[\"${_objBackupName}\"] in json : UPDATING..."
#---update et verif
_jqUpdate=$(jq ".${_objName}.[\"${_objBackupName}\"] = ${_objBackup}" ${_wipJson} > "$tmp" && mv "$tmp" ${_wipJson} ) || _jqUpdate="jq_ERROR"
if [ "${_jqUpdate}" == "jq_ERROR" ]
then
echo -e "\n!!! > update ERROR : ABORTING...\n" && exit 1
else
echo " > update OK"
fi
#-----
fi
else
echo "(!) Mount of ${_objName}.[\"${_objBackupName}\"] diseabled by user > skipping"
fi
#
# Verif et ajout SubBACKUP () obj to json ---------------------------------------------------------------------------------------------------------------------------
#
echo -e "\n------ SubBACKUP (/backup/_not_saved_area_): ------"
if [ "${_mountSubBackup}" == true ]
then
mkdir /mnt/data/supervisor/backup/_not_saved_area_
_subBkpObj=$(cat ${_wipJson} | jq ".${_objName}.[\"${_objSubBackupName}\"]")
tmp=$(mktemp)
if [ "${_subBkpObj}" == "null" ]
then
echo ">> ${_objName}.[\"${_objSubBackupName}\"] not found in json : CREATING..."
#---creation et verif
_jqCreate=$(jq ".${_objName} += {\"${_objSubBackupName}\":${_objSubBackup}}" ${_wipJson} > "$tmp" && mv "$tmp" ${_wipJson} ) || _jqCreate="jq_ERROR"
if [ "${_jqCreate}" == "jq_ERROR" ]
then
echo -e "\n!!! > creation ERROR : ABORTING...\n" && exit 1
else
echo " > creation OK"
fi
#-----
else
echo ">> ${_objName}.[\"${_objSubBackupName}\"] in json : UPDATING..."
#---update et verif
_jqUpdate=$(jq ".${_objName}.[\"${_objSubBackupName}\"] = ${_objSubBackup}" ${_wipJson} > "$tmp" && mv "$tmp" ${_wipJson} ) || _jqUpdate="jq_ERROR"
if [ "${_jqUpdate}" == "jq_ERROR" ]
then
echo -e "\n!!! > update ERROR : ABORTING...\n" && exit 1
else
echo " > update OK"
fi
#-----
fi
else
echo "(!) Mount of ${_objName}.[\"${_objSubBackupName}\"] diseabled by user > skipping"
fi
#
#
# Verif et ajout DATA obj to json ---------------------------------------------------------------------------------------------------------------------------
#
echo -e "\n------ DATA: ------"
if [ "${_mountData}" == true ]
then
_dataObj=$(cat ${_wipJson} | jq ".${_objName}.[\"${_objDataName}\"]")
tmpB=$(mktemp)
if [ "${_dataObj}" == "null" ]
then
echo ">> ${_objName}.[\"${_objDataName}\"] not found in json : CREATING..."
#gerer creation ici
_jqCreate=$(jq ".${_objName} += {\"${_objDataName}\":${_objData}}" ${_wipJson} > "$tmpB" && mv "$tmpB" ${_wipJson} ) || _jqCreate="jq_ERROR"
if [ "${_jqCreate}" == "jq_ERROR" ]
then
echo -e "\n!!! > creation ERROR : ABORTING...\n" && exit 1
else
echo " > creation OK"
fi
#-----
else
echo ">> ${_objName}.[\"${_objDataName}\"] in json : UPDATING..."
#gérer update ici
_jqUpdate=$(jq ".${_objName}.[\"${_objDataName}\"] = ${_objData}" ${_wipJson} > "$tmpB" && mv "$tmpB" ${_wipJson} ) || _jqUpdate="jq_ERROR"
if [ "${_jqUpdate}" == "jq_ERROR" ]
then
echo -e "\n!!! > update ERROR : ABORTING...\n" && exit 1
else
echo " > update OK"
fi
#-----
fi
else
echo "(!) Mount of ${_objName}.[\"${_objDataName}\"] diseabled by user > skipping"
fi
#
#---------------------------------------------------------------------------------------------------------------------------
#
# Minify JSON
#
echo -e "\n>> Update COMPLETED\n>> JSon Minification"
tmpC=$(mktemp)
jq -r tostring ${_wipJson} > "$tmpC" && mv "$tmpC" ${_wipJson}
#
# JSON validation
#
echo ">> Validating JSON..."
jsonString=$(jq -r tostring ${_wipJson})
if jq empty ${_wipJson}
then
echo " > JSON is valid !"
else
echo -e "\n (!) JSON is invalid > ABORTING...\n" && exit 1
fi
#
# Query user for final operation
#
echo ""
while true; do
read -p "Do you wish to override original HA container config with new one ? " yn
case $yn in
[Yy]* ) break;;
[Nn]* ) echo -e "\n(!) Process CANCELED by user ...\n" && exit;;
* ) echo "Please answer (y)yes or (n)no.";;
esac
done
echo -e "\nApply updated config...\n"
echo "Stopping HA Container ..."
docker stop ${_id}
echo "HA Container stopped"
cp ${_wipJson} ${_srcJson}
_secondSrcJson="${_containersSecondaryPath}$_id/config.v2.json"
echo "Config File restored"
cp ${_wipJson} ${_secondSrcJson}
sleep 1
while true; do
read -p "original HA container config file overrided , REBOOT ? " yn
case $yn in
[Yy]* ) reboot; break;;
[Nn]* ) echo -e "\n(!) Reboot CANCELED by user ...\n" && exit;;
* ) echo "Please answer (y)yes or (n)no.";;
esac
done
#
} 2>&1 | tee -a ${_destFolder}${_logFile}
RESTORE_mountPoints.sh
#!/bin/bash
# copier le script dans l'un des dossiers [addon_Configs,addons,backup,media,share]
#
#
# Script permettant de restaurer un fichier de configuration généré
# par le script ADD_mountPoints.sh
#
#
# >> bash /mnt/data/supervisor/share/RESTORE_mountPoints.sh
#
#==================================================
# SETTINGS:
# indiquer le dossier du script au choix : [addon_Configs,addons,backup,media,share] :
_folder="share"
#indiquer le sous dossier pour enregistrer les fichiers et logs
_subFolder="mounts"
#==================================================
# ADVANCED settings
_supervisorPath="/mnt/data/supervisor/"
_containersPath="/var/lib/docker/containers/"
_containersSecondaryPath="/mnt/data/docker/containers/"
_haContainerName="homeassistant"
_logFile="_mounts_BackupAndData.log"
#
#==================================================
#==================================================
#folder creation
_destFolder="${_supervisorPath}${_folder}/${_subFolder}/"
#mkdir "${_destFolder}" 2>/dev/null
#==================================================
#==================================================
clear
{
echo -e "\n\n"
echo "=========================================="
echo ">> RESTORE HA Container config.v2.json <<"
echo "=========================================="
_date=$(date +"%Y-%m-%d_%H-%M-%S")
echo "${_date}"
# Verif existance dossier de backup
if [ ! -d "${_destFolder}" ]
then
echo -e "config backup folder not found > aborting restore process...\n(${_destFolder})"&& exit 0
else
echo -e "config backup folder OK > start scanning files...\n(${_destFolder})\n"
fi
#
#recup des fichier de backup (https://unix.stackexchange.com/questions/511127/bash-list-possible-files-and-select-one)
# + selection utilisateur
#
_backupBaseName="config.v2.json.backup.original_"
_backupsFiles="${_destFolder}${_backupBaseName}*.json"
for img in ${_backupsFiles}
do
n=$((n+1))
_basename=$(basename "$img")
printf "[%s] %s\n" "$n" "$_basename"
eval "img${n}=\$img"
done
if [ "$n" -eq 0 ]
then
echo >&2 "No ${_backupBaseName}*.json found > aborting restore process... "
exit
fi
printf '\nEnter File Index ID (1 to %s) (0 to cancel): ' "$n"
read -r num
num=$(printf '%s\n' "$num" | tr -dc '[:digit:]')
if [ "$num" -le 0 ] || [ "$num" -gt "$n" ] || [ "$num" -eq 0 ]
then
#echo >&2 Wrong selection.
# wrong select
if [ "$num" -eq 0 ]
then
#abort by user
echo -e "(!) Process CANCELED by user ...\n";exit 0
else
#bad answer restart script
exec "/mnt/data/supervisor/share/RESTORE_mountPoints.sh"
fi
else
eval "_selectedFile=\$img${num}"
_selectedFileName=$(basename "$_selectedFile")
echo "Selected image is: ${_selectedFileName}"
fi
#
# Confirmation
#
echo -e "\nContinuer avec ce fichier ?\n (y)(n)(c) : yes / no / change"
while true; do
read -p " >> " ync
case $ync in
[Yy]* ) break;;
[Nn]* ) echo -e "\n(!) Process CANCELED by user ...\n" && exit;;
[Cc]* ) exec "/mnt/data/supervisor/share/RESTORE_mountPoints.sh";;
* ) echo -e "Please answer (y)yes or (n)no or (c)change.\n";;
esac
done
#
#
#recup et verif container ID ( même si off)
#
container="docker ps -a --no-trunc -aqf name=${_haContainerName}"
_id=$($container 2>/dev/null)
if [ -z "${_id}" ]
then
echo -e "\n!!! Container ID not found for homeassistant : ABORTING...\n" && exit 0
else
echo "Container ID found => ${_id}"
fi
#
# copy et backup du fichier dans share
#
_srcJson="${_containersPath}$_id/config.v2.json"
_secondSrcJson="${_containersSecondaryPath}$_id/config.v2.json"
echo "JSON to replace A => ${_srcJson}"
echo "JSON to replace B => ${_secondSrcJson}"
cp ${_srcJson} "${_destFolder}config.v2.json.backup.original_"${_date}"_BeforeRestore.json"
chmod 777 -R ${_destFolder}
echo -e "\n=> current config.v2.json backuped in ${_folder}/${_subFolder} folder\n"
#
# Query user to process
#
while true; do
read -p "Ok to restore file and reboot ? " yn
case $yn in
[Yy]* ) break;;
[Nn]* ) echo -e "\n(!) CANCELED by user ...\n" && exit;;
* ) echo "Please answer (y)yes or (n)no.";;
esac
done
#
# Process
#
echo "Stopping HA Container ..."
docker stop ${_id}
echo "HA Container stopped"
sleep 1
cp ${_selectedFile} ${_srcJson}
cp ${_selectedFile} ${_secondSrcJson}
echo "Config File restored"
echo "rebooting..."
sleep 1
reboot
} 2>&1 | tee -a ${_destFolder}${_logFile}
Bonne soirée