Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 06/12/2015, à 20:03

Hizoka

[abandonné] Modifier Backup Manager

Bonsoir,

j'utilise backup manager pour faire des sauvegarde incrémentielles, il marche parfaitement.

Mais il y a un truc chiant, les sauvegardes complètes ont lieux 1 fois par mois ou par semaine.
Impossible de lui indiquer un nombre de jour entre les sauvegardes.

Je me suis donc penché sur les fichiers du bash du logiciel et j'ai fait les modifications suivantes :

/usr/share/backup-manager/backup-methods.sh

function __get_master_day()
{
    debug "__get_master_day ()"

    if [[ -z "$BM_TARBALLINC_MASTERDATETYPE" ]]; then
        error "No frequency given, set BM_TARBALLINC_MASTERDATETYPE."
    fi
    
    case $BM_TARBALLINC_MASTERDATETYPE in
    weekly)
        master_day=$(date +'%w')
    ;;
    monthly)
        master_day=$(date +'%-d')
    ;;
    *)
        error "Unknown frequency: \$BM_TARBALLINC_MASTERDATETYPE"
    ;;
    esac
}

=>

function __get_master_day()
{
    debug "__get_master_day ()"

    if [[ -z "$BM_TARBALLINC_MASTERDATETYPE" ]]; then
        error "No frequency given, set BM_TARBALLINC_MASTERDATETYPE."
    fi
    
    case $BM_TARBALLINC_MASTERDATETYPE in
    weekly)
        master_day=$(date +'%w')
    ;;
    monthly)
        master_day=$(date +'%-d')
    ;;
    custom)
        master_day=$(($(date +'%s')/86400))
    ;;
    *)
        error "Unknown frequency: \$BM_TARBALLINC_MASTERDATETYPE"
    ;;
    esac
}
function __get_flags_tar_incremental()
{
    dir_name="$1"
    debug "__get_flags_tar_incremental ($dir_name)"

    incremental_list="$BM_REPOSITORY_ROOT/$BM_ARCHIVE_PREFIX$dir_name.incremental.bin"
    bm_pending_incremental_list="$incremental_list"
    if [[ -e "${incremental_list}" ]]; then
        debug "cp $incremental_list ${incremental_list}.orig"
        cp $incremental_list "${incremental_list}.orig"
    fi

    incremental=""
    __get_master_day
    __init_masterdatevalue

    # if master day, we have to purge the incremental list if exists
    # so we'll generate a new one (and then, a full backup).
    if [[ "$master_day" -eq "$BM_TARBALLINC_MASTERDATEVALUE" ]];  then
        info "Building master backup for target: \"\$dir_name\"."
        rm -f "$incremental_list"
    fi
    if [[ -e "$incremental_list" ]]; then
        master=""
    fi
    incremental="--listed-incremental $incremental_list"
}

=>

function __get_flags_tar_incremental()
{
    dir_name="$1"
    debug "__get_flags_tar_incremental ($dir_name)"

    incremental_list="$BM_REPOSITORY_ROOT/$BM_ARCHIVE_PREFIX$dir_name.incremental.bin"
    bm_pending_incremental_list="$incremental_list"
    if [[ -e "${incremental_list}" ]]; then
        debug "cp $incremental_list ${incremental_list}.orig"
        cp $incremental_list "${incremental_list}.orig"
    fi

    incremental=""
    __get_master_day
    __init_masterdatevalue

    # if master day, we have to purge the incremental list if exists
    # so we'll generate a new one (and then, a full backup).    
    if [[ "$BM_TARBALLINC_MASTERDATETYPE" == "custom" ]]; then
        if [[ $(($master_day % $BM_TARBALLINC_MASTERDATEVALUE)) -eq 0 ]]; then
            info "Building master backup for target: \"\$dir_name\"."
            rm -f "$incremental_list"
        fi
    else
        if [[ "$master_day" -eq "$BM_TARBALLINC_MASTERDATEVALUE" ]];  then
            info "Building master backup for target: \"\$dir_name\"."
            rm -f "$incremental_list"
        fi
    fi
    if [[ -e "$incremental_list" ]]; then
        master=""
    fi
    incremental="--listed-incremental $incremental_list"
}

fichier backup-manager.conf

# Which frequency to use for the master tarball?
# possible values: weekly, monthly
export BM_TARBALLINC_MASTERDATETYPE="weekly"

# Number of the day, in the BM_TARBALLINC_MASTERDATETYPE frequency
# when master tarballs should be made
export BM_TARBALLINC_MASTERDATEVALUE="1"

=>

# Which frequency to use for the master tarball?
# possible values: weekly, monthly or custom
export BM_TARBALLINC_MASTERDATETYPE="custom"

# Number of the day, in the BM_TARBALLINC_MASTERDATETYPE frequency
# when master tarballs should be made, for the custom mode, number of days between master backups
export BM_TARBALLINC_MASTERDATEVALUE="14"

Donc mon principe est le suivant :
1) Indiquer custom dans les config à la place de weekly ou monthly
2) Indiquer le nombre de jours entre les sauvegardes complètes dans le fichier de config
3) Si custom est utilisé, il regarde le nombre de seconde passée depuis 1970, le change en nombre de jour
4) Il regarde le reste de la division entre le nombre de jour depuis 1970 et la fréquence de sauvegarde
5) Si le résultat est 0, c'est que le jour est un multiple de la fréquence de sauvegarde et il faut donc faire une sauvegarde complete.

Alors tout se base par rapport a 00:00:00 1970-01-01 UTC mais normalement ça devrait le faire non ?
Pas de problème lors du changement d'année.

A votre avis cela est-il fonctionnel ? Mon raisonnement est-il bon ?

D'après quelques tests logiques, cela semble ok mais bon...

interval=5
test=$(date +'%s')
nb_jour=$((${test} / 86400))
multiple=$((${nb_jour} % ${interval}))
=> 0 , il faut faire la sauvegarde complete car nous sommes un multiple de 5 depuis 1970

# Si je teste dans 3 jours
interval=5
test=$(($(date +'%s') + 259200))
nb_jour=$((${test} / 86400))
multiple=$((${nb_jour} % ${interval}))
=> 3, ce n'est pas un multiple de 5 donc pas de sauvegarde

# Si je teste dans 5 jours
interval=5
test=$(($(date +'%s') + 432000))
nb_jour=$((${test} / 86400))
multiple=$((${nb_jour} % ${interval}))
=> 0 , il faut faire la sauvegarde complete car nous sommes un multiple de 5 depuis 1970

Merci à vous smile
Bonne soirée.

Dernière modification par Hizoka (Le 08/05/2016, à 14:20)


KDE Neon 64bits
Tous mes softs (MKVExtractorQt, HizoSelect, HizoProgress, Qtesseract, Keneric, Services menus...) sont sur github

Hors ligne

#2 Le 07/12/2015, à 20:38

Hizoka

Re : [abandonné] Modifier Backup Manager

Un petit up pour avoir vos retours d'experts sur la méthode que je propose smile

Merci à vous


KDE Neon 64bits
Tous mes softs (MKVExtractorQt, HizoSelect, HizoProgress, Qtesseract, Keneric, Services menus...) sont sur github

Hors ligne

#3 Le 10/12/2015, à 21:47

Hizoka

Re : [abandonné] Modifier Backup Manager

Je viens de tester en utilisant 45j
et j'ai l'erreur :

BM_TARBALLINC_MASTERDATEVALUE ne doit pas être supérieur à 31, retour à la valeur 1

mais je ne trouve pas où a lieu cette vérification...


KDE Neon 64bits
Tous mes softs (MKVExtractorQt, HizoSelect, HizoProgress, Qtesseract, Keneric, Services menus...) sont sur github

Hors ligne

#4 Le 11/12/2015, à 14:48

pingouinux

Re : [abandonné] Modifier Backup Manager

Bonjour Hizoka,

mais je ne trouve pas où a lieu cette vérification...

Ce n'est apparemment pas dans un des scripts que tu montres.

Hors ligne

#5 Le 11/12/2015, à 15:45

soshy

Re : [abandonné] Modifier Backup Manager

Salut,
en regardant le code depuis le depot github je trouve
fichier backup-manager

# Sanitize will try to find deprecated vartiables,
debug "Sanitizing the configuration file."
source $libdir/sanitize.sh

fichier lib/sanitize.sh

            if [[ "$BM_TARBALLINC_MASTERDATEVALUE" -gt "31" ]]; then
                warning "BM_TARBALLINC_MASTERDATEVALUE should not be greater than 31, falling back to 1    "
                export BM_TARBALLINC_MASTERDATEVALUE="1"
            fi

C'est de la que ca vient.

Il me semble que le controle est mauvais dans le fichier sanitize.sh. Il semble que ce soit un :
si "weekly" alors
sinon
// on considere qu'on est en "monthly"
fin si.

De fait, la possibilite custom est ignoree et c'est le controle monthly qui est applique. Tu peux meme remonter le bug si il n'existe pas deja je pense :-)

Dernière modification par soshy (Le 11/12/2015, à 16:02)

Hors ligne

#6 Le 13/12/2015, à 13:11

Hizoka

Re : [abandonné] Modifier Backup Manager

arf...

grep "BM_TARBALLINC_MASTERDATEVALUE" *
backup-manager.conf.tpl:export BM_TARBALLINC_MASTERDATEVALUE="1"
backup-manager.conf.tpl:# BM_TARBALLINC_MASTERDATEVALUE="5"
backup-manager.conf.tpl:# BM_TARBALLINC_MASTERDATEVALUE="1"
backup-methods.sh:    if [[ -z "$BM_TARBALLINC_MASTERDATEVALUE" ]]; then
backup-methods.sh:        BM_TARBALLINC_MASTERDATEVALUE="1"
backup-methods.sh:    if [[ "$master_day" -eq "$BM_TARBALLINC_MASTERDATEVALUE" ]];  then
backup-methods.sh:    if [[ "$master_day" != "$BM_TARBALLINC_MASTERDATEVALUE" ]] ; then
grep: contrib: est un dossier
Fichier binaire sanitize.sh correspondant

=> J'avais pas vu la derniere ligne...

soshy => Ce n'est pas un bug, c'est moi qui veut ajouter une fonction smile

merci à vous, je m'en vais tester tout ca


KDE Neon 64bits
Tous mes softs (MKVExtractorQt, HizoSelect, HizoProgress, Qtesseract, Keneric, Services menus...) sont sur github

Hors ligne

#7 Le 08/05/2016, à 14:19

Hizoka

Re : [abandonné] Modifier Backup Manager

Bon n'arrivant pas à ce que je voulais, je suis reparti de 0, et après plusieurs mois de tests, je poste ma version si ça peut servir...

### Couleurs
FUSHIA="\033[1;35m"
RAZ="\e[m"
BLEUFONCE="\033[1;34m"
VERT="\033[0;32m"
ROUGE="\033[1;31m"




function multiselect
{
# valeur de retour numérique : ${multinum[@]}
# valeur de retour de texte : ${multitxt[@]}
# ${@} : les arguments servant de liste
# PS3 : message à afficher avant le listing
# @@ : élément séparateur, partie de gauche valeur texte et à gauche description ( valeur@@description )
# argument : -[0-9] : limite le nombre de reponse possible

# ATTENTION : La liste commence au chiffre 1 mais les tableaux retournés commencent, eux, à 0 (comme tout tableau)

# Remise au propre des variables
unset multinum multitxt limite num x

# Recherche l'option du nombre de reponse
[[ "${1}" == -[0-9]* ]] && limite="${1/#-}"

# Message informatif apparaissant avant la liste
if [[ ${PS3} && ${limite} ]]
then
    if [[ ${limite} = 1 ]]
    then
        echo -e "${FUSHIA}${PS3}${RAZ} ( ${BLEUFONCE}1 seul choix possible.${RAZ} )\n"
    else
        echo -e "${FUSHIA}${PS3}${RAZ} ( ${BLEUFONCE}${limite} choix possibles.${RAZ} )\n"
    fi

elif [[ ${PS3} && -z ${limite} ]]
then
     echo -e "${FUSHIA}${PS3}${RAZ}\n"

else
    echo
fi

# Affichage de la liste des choix
for x in "${@}"
do
    # En cas de limite, on saute la 1ere valeure qui est le chiffre donné
    if [[ ${limite} && -z ${num} ]]
    then
        num=0

    else
        # Incrémentation du numéro pour la prochaine ligne
        ((num++))

        # recherche le signe servant de séparateur entre la valeur et la description
        if [[ "${x}" =~ "@@" ]]
        then
            # Si séparateur présent : affichage du numéro, de la valeur du texte et de la description
            echo -e "${FUSHIA}${num}${RAZ}) ${BLEUFONCE}${x%%@@*}${RAZ} : ${VERT}${x##*@@}${RAZ}"

        else
            # Si pas de séparateur : affichage du numéro et de la valeur du texte
            echo -e "${FUSHIA}${num}${RAZ}) ${BLEUFONCE}${x}${RAZ}"
        fi
    fi
done

# Envoie de la réponse dans un tableau
read -p $'\nSélection : ' -a multinum

# Création d'une liste contenant les valeurs textes choisies + Vérification des valeurs numériques
for x in "${multinum[@]}"
do
    if [[ ${x} -gt ${#@} || ! ${x} =~ ^[0-9]*$ ]]
    then
        # Message d'erreur indiquant une réponse impossible
        echo -e "\n${ROUGE}Erreur dans la sélection, vous devez rentrez des chiffres inférieurs à la valeur maximale proposée.${RAZ}"

        # Destruction des variables
        unset multinum multitxt limite

        # Arrêt de la fonction en erreur (code 1)
        return 1

    elif [[ ${limite} && ${#multinum[@]} -gt ${limite} ]]
    then
        # Message d'erreur indiquant un nombre de reponse trop élevé
        echo -e "\n${ROUGE}Nombre de séléction trop importante, la limite est de ${limite} choix.${RAZ}"

        # Destruction des variables
        unset multinum multitxt limite

        # Arrêt de la fonction en erreur (code 1)
        return 1

    else
        # Si il y a eu un argument pour militer le nombre de reponse, on ajoute 1 a x
        [[ "${1}" == -[0-9]* ]] && ((x++))

        # Ajout de la valeur traitée dans le tableau
        multitxt+=("${!x%%@@*}")
    fi
done
}


### Fonction affichant les questions dans le même style que ci dessus
function Question
{
if [[ "${1}" =~ "@@" ]]
then
    # Si séparateur présent : affichage du numéro, de la valeur du texte et le texte autre
    echo -en "\n${FUSHIA}${1%%@@*}${VERT} (${1##*@@}) ${RAZ}: ${BLEUFONCE}"

else
    # Si pas de séparateur : affichage du numéro et de la valeur du texte
    echo -en "\n${FUSHIA}${1}${RAZ} : ${BLEUFONCE}"
fi

read -p ""

echo -en "${RAZ}"
}


### Fonction recherchant les fichiers dans les fichiers créés
function Verification
{
# S'il n'y a pas d'argument, on annule
if [[ -z ${1} ]]
then
    DebugReply "Vérification : Aucun fichier tar indiqué."
    return 1
fi

# Liste le contenu du fichier
while read ligne
do
    # Arrêt de la fonction avec une erreur si un fichier a été trouvé
    if [[ ${ligne:0:1} == "-" ]]
    then
        DebugReply "Vérification : Le fichier tar contient au moins un fichier."
        return 1
    fi
done < <(tar -tvf "${1}")

# Arret de la fonction, il y a pas de fichier
DebugReply "Vérification : Le fichier tar ne contient pas de fichier, suppression du fichier ${1}"
rm -f "${1}"
return 0
}



### Fonction de création de fichier de config
function ExtractSave
{
### Choix des sauvegardes à extraire
PS3="Quelles sauvegardes faut il extraire ?" multiselect "${HOME}/.config/HizoSaveSoftware"/*.cfg "Exit"

[[ "${multitxt[0]}" == "Exit" ]] && return


### Dossier ou extraire
Question "Dans quel dossier faut il tout extraire ?@@Utilise le dossier de sauvegarde par défaut"; ExtractFolder="${REPLY}"


### Traitement de la demande
for fileCfg in "${multitxt[0]}"
do
    ## Sert pour recupérer quelques variables
    source "${fileCfg}"

    ## Création du dossier de sortie si besoin
    [[ ! -d "${ExtractFolder:-${FolderOfSave}}" ]] && mkdir -p "${ExtractFolder:-${FolderOfSave}}"

    ## Commande en fonction de l'extension
    case "${CompressType}" in
        gz)
            for file in "${FolderOfSave/%/}/${SaveName}"*.tar.gz
            do
                echo -e "\n${BLEUFONCE}Extraction du du fichier ${FUSHIA}${file}${RAZ}."
                tar xzf "${file}" -C "${ExtractFolder:-${FolderOfSave}}"
            done ;;


        xz)
            for file in "${FolderOfSave/%/}/${SaveName}"*.tar.xz
            do
                echo -e "\n${BLEUFONCE}Extraction du du fichier ${FUSHIA}${file}${RAZ}."
                tar xvJf "${file}" -C "${ExtractFolder:-${FolderOfSave}}"
            done ;;

        bz)
            for file in "${FolderOfSave/%/}/${SaveName}"*.tar.bz
            do
                echo -e "\n${BLEUFONCE}Extraction du du fichier ${FUSHIA}${file}${RAZ}."
                tar xjf "${file}" -C "${ExtractFolder:-${FolderOfSave}}"
            done ;;

        *)
            for file in "${FolderOfSave/%/}/${SaveName}"*.tar
            do
                echo -e "\n${BLEUFONCE}Extraction du du fichier ${FUSHIA}${file}${RAZ}."
                tar xf "${file}" -C "${ExtractFolder:-${FolderOfSave}}"
            done ;;

    esac
done
}



### Fonction de suppression de fichier de config
function ConfigRemove
{
### Vérifie qu'il y a bien des fichiers de configs
if [[ -z $(ls "${HOME}/.config/HizoSaveSoftware"/*.cfg) ]]
then
    echo -e "${ROUGE}Il n'y a aucun fichier de confi dans le dossier '${HOME}/.config/HizoSaveSoftware'${RAZ}"
    return
fi


### Liste les fichiers de config
PS3="Selectionner les fichiers de config à effacer ?" multiselect "${HOME}/.config/HizoSaveSoftware"/*.cfg "Tout nettoyer" "Exit"


### Traitement de la demande
for fileCfg in "${multitxt[0]}"
do
    case "${fileCfg}" in
        "Tout nettoyer") [[ $(ls "${HOME}/.config/HizoSaveSoftware"/*.cfg) ]] && rm "${HOME}/.config/HizoSaveSoftware"/*.cfg ;;
        "Exit") return ;;
        *) [[ -e "${fileCfg}" ]] && rm "${fileCfg}" ;;
    esac
done
}


### Fonction de création de fichier de config
function ConfigCreate
{
### Choix de l'action
PS3="Quel type de sauvegarde voulez-vous faire ?" multiselect -1 "Dump de MySQL" "Sauvegarde d'un dossier" "Exit"


### Traitement de l'action
case "${multitxt[0]}" in
    "Dump de MySQL")
        ## Récupération des infos
        Question "Nom de la sauvegarde"; SaveName="${REPLY}"

        echo
        PS3="Choix de la compression :" multiselect -1 "gz@@@Bon compromis entre vitesse et compression, valeur par défaut" "xz@@@Plus lent mais meilleure compression" "bz" "Aucune@@@Très rapide mais aucune compression"
        CompressType=${multitxt}

        Question "Priorité du travail@@19 par défaut"; NiceValue="${REPLY}"
        Question "Adresse complète du dossier où stocker les sauvegardes"; FolderOfSave="${REPLY}"
        Question "Nombre de jour entre les sauvegardes, le système se base sur la 1ere date connue 01/01/1970@@1 jour par défaut"; DayBetweenSave="${REPLY}"
        Question "Durée de vie des sauvegardes en jour. Cette valeur doit être supérieure à la valeur précédente@@0 = pas de limite et 30 jours par défaut"; AgeMax="${REPLY}"
        Question "Faut-il limiter les sauvegardes à 1 par jour ?@@True ou False avec True par défaut"; OneSaveByDay="${REPLY}"
        Question "Faut-il utiliser le debug mode qui envoie des infos dans un fichier texte ?@@True ou False avec True par défaut"; DebugMode="${REPLY}"
        Question "User MySQL à utiliser"; MysqlUser="${REPLY}"
        Question "Host MySQL à utiliser@@par défaut localhost"; MysqlHost="${REPLY}"
        Question "Mot de passe MySQL à utiliser"; MysqlPass="${REPLY}"
        Question "Tables à sauvegarder à espacer d'espace ou All pour toutes les sauvegarder@@par défaut All"; MysqlTable="${REPLY}"


        ## Vérification de valeurs
        if [[ -z "${SaveName}" ]]
        then
            echo -e "\n${ROUGE}La sauvegarde doit obligatoirement avoir un nom, dernière chance !${RAZ}"
            Question "Nom de la sauvegarde"; SaveName="${REPLY}"

            [[ -z "${SaveName}" ]] && return
        fi

        if [[ -z "${FolderOfSave}" ]]
        then
            echo -e "\n${ROUGE}Il faut un dossier de sortie, sinon que fera-t-on des fichiers ?! Dernière chance !${RAZ}"
            Question "Adresse complète du dossier où stocker les sauvegardes"; FolderOfSave="${REPLY}"

            [[ -z "${FolderOfSave}" ]] && return
        fi

        if [[ -z "${MysqlUser}" ]]
        then
            echo -e "\n${ROUGE}Il faut définir l'utilisateur à utiliser, dernière chance !${RAZ}"
            Question "User MySQL à utiliser"; MysqlUser="${REPLY}"

            [[ -z "${MysqlUser}" ]] && return
        fi

        if [[ -z "${MysqlPass}" ]]
        then
            echo -e "\n${ROUGE}Il faut définir le mot de passe à utiliser, dernière chance !${RAZ}"
            Question "Mot de passe MySQL à utiliser"; MysqlPass="${REPLY}"

            [[ -z "${MysqlPass}" ]] && return
        fi


        ## Création du fichier de config
        echo "# Nom de la sauvegarde
SaveName=\"${SaveName}\"

# Choix du format de compression : none, gz, xz, bz
CompressType="${CompressType:-bz}"

# Valeur du nice
NiceValue=\"${NiceValue:-19}\"

# Dossier des sauvegardes
FolderOfSave=\"${FolderOfSave}\"

# Nombre de jour entre les sauvegardes
DayBetweenSave=\"${DayBetweenSave:-1}\"

# Nombre de jour maximum avant la suppression des fichiers
AgeMax=\"${AgeMax:-30}\"

# Limite le nombre de save à une par jour
OneSaveByDay=\"${OneSaveByDay:-True}\"

# Mode debug et adresse du fichier de retour d'info
DebugMode=\"${DebugMode:-True}\"

# Dump de mysql
MysqlUser=\"${MysqlUser}\" # Nom de l'user
MysqlHost=\"${MysqlHost:-localhost}\" # nom de l'host
MysqlPass=\"${MysqlPass}\" # Mot de passe du compte
MysqlTable=(\"${MysqlTable:-All}\") # Tables à sauvegarder à espacer d'espace ou All pour toutes les sauvegarder" > "${HOME}/.config/HizoSaveSoftware/${SaveName}.cfg"

        ;;


    "Sauvegarde d'un dossier")
        ## Récupération des infos
        Question "Nom de la sauvegarde"; SaveName="${REPLY}"

        echo
        PS3="Choix de la compression :" multiselect -1 "gz@@@Bon compromis entre vitesse et compression, valeur par défaut" "xz@@@Plus lent mais meilleure compression" "bz" "Aucune@@@Très rapide mais aucune compression"
        CompressType=${multitxt}

        Question "Priorité du travail@@19 par défaut"; NiceValue="${REPLY}"
        Question "Adresse complète du dossier à sauvegarder"; FolderToSave="${REPLY}"
        Question "Adresse complète du dossier où stocker les sauvegardes"; FolderOfSave="${REPLY}"
        Question "Faut-il activer la récursion sur ce dossier ?@@True ou False avec True par défaut"; Recursion="${REPLY}"
        Question "Faut-il exclure du traitement les fichiers de verrouillage et de sauvegarde ?@@True ou False avec True par défaut"; ExcludeBackups="${REPLY}"
        Question "Nombre de jour entre les sauvegardes complètes, le système se base sur la 1ere date connue 01/01/1970@@30 jours par défaut"; DayBetweenMaster="${REPLY}"
        Question "Durée de vie des sauvegardes en jour. Cette valeur doit être supérieure à la valeur précédente@@0 = pas de limite et 60 jours par défaut"; AgeMax="${REPLY}"
        Question "Faut-il limiter les sauvegardes à 1 par jour ?@@True ou False avec True par défaut"; OneSaveByDay="${REPLY}"
        Question "Faut-il utiliser le debug mode qui envoie des infos dans un fichier texte ?@@True ou False avec True par défaut"; DebugMode="${REPLY}"
        Question "Items à exclure de la sauvegarde à séparer par des espaces et à encadrer de \""; ItemsToExclude="${REPLY}"


        ## Vérification de valeurs
        if [[ -z "${SaveName}" ]]
        then
            echo -e "\n${ROUGE}La sauvegarde doit obligatoirement avoir un nom, dernière chance !${RAZ}"
            Question "Nom de la sauvegarde"; SaveName="${REPLY}"

            [[ -z "${SaveName}" ]] && return
        fi

        if [[ -z "${FolderOfSave}" ]]
        then
            echo -e "\n${ROUGE}Il faut un dossier de sortie, sinon que fera-t-on des fichiers ?! Dernière chance !${RAZ}"
            Question "Adresse complète du dossier où stocker les sauvegardes"; FolderOfSave="${REPLY}"

            [[ -z "${FolderOfSave}" ]] && return
        fi

        if [[ -z "${FolderToSave}" ]]
        then
            echo -e "\n${ROUGE}Pour sauvegarder un dossier, il faut le connaître... Dernière chance !${RAZ}"
            Question "Adresse complète du dossier à sauvegarder"; FolderToSave="${REPLY}"

            [[ -z "${FolderToSave}" ]] && return
        fi


        ## Création du fichier de config
        echo "# Nom de la sauvegarde
SaveName=\"${SaveName}\"

# Choix du format de compression : none, gz, xz, bz
CompressType="${CompressType:-bz}"

# Valeur du nice
NiceValue=\"${NiceValue:-19}\"

# Dossier à sauvegarder
FolderToSave=\"${FolderToSave}\"

# Mode recursif
Recursion=\"${Recursion:-True}\"

# Exclut du traitement les fichiers de verrouillage et de sauvegarde
ExcludeBackups="\"${ExcludeBackups:-True}"\"

# Dossier des sauvegardes
FolderOfSave=\"${FolderOfSave}\"

# Nombre de jour entre les sauvegardes complètes
DayBetweenMaster=\"${DayBetweenMaster:-30}\"

# Nombre de jour maximum avant la suppression des fichiers
AgeMax=\"${AgeMax:-60}\"

# Limite le nombre de save à une par jour
OneSaveByDay=\"${OneSaveByDay:-True}\"

# Mode debug et adresse du fichier de retour d'info
DebugMode=\"${DebugMode:-True}\"

# Items à exclure de la sauvegarde à séparer par des espaces et à encadrer de \"
ItemsToExclude=(${ItemsToExclude})" > "${HOME}/.config/HizoSaveSoftware/${SaveName}.cfg"
        ;;


    *) return ;;
esac


### Création du dossier de sortie si besoin
[[ ! -d "${FolderOfSave}" ]] && mkdir -p "${FolderOfSave}"


echo -e "${ROUGE}\nCréation du fichier de configuration términée.\n${RAZ}"

}


### Fonction de retour d'info
function DebugReply
{
[[ "${DebugMode}" == "True" && -n "${@}" ]] && echo -e "${@}" >> "${FolderOfSave/%\/}/${SaveName} - debug.txt"
}


### Fonction de création d'un dump de mysql
function DumpOfMysql
{
# Suppression des fichiers dump trop agés
if [[ ${AgeMax} -gt 0 && $(find "${FolderOfSave/%\/}" -type f -mtime +${AgeMax} -iname "${SaveName}*.tar*") ]]
then
    # Retour d'infos
    DebugReply "Suppression des anciens dump"
    DebugReply "$(find "${FolderOfSave/%\/}" -type f -mtime +${AgeMax} -iname "${SaveName}*.tar*")"

    # Suppression des masters anciens
    find "${FolderOfSave/%\/}" -type f -mtime +${AgeMax} -iname "${SaveName}*.tar*" -delete
fi

if [[ $((${DayToDay} % ${DayBetweenSave})) -eq 0 ]]
then
    if [[ "${OneSaveByDay}" == "True" && -n $(find "${FolderOfSave/%\/}" -iname "${SaveName}*$(date +'%Y-%m-%d')*.${ext}") ]]
    then
        DebugReply "Une sauvegarde du jour existe déjà."
        return
    fi

    DebugReply "Sauvegarde du ou des tables MySQL"

    # Dump des tables
    for Table in "${MysqlTable[@]}"
    do
        # Si c'est All on les sauvegarde toutes et on arrete là la boucle
        if [[ "${Table}" == "All" ]]
        then
            # Retour d'infos
            DebugReply "Dump des bases de donnée MySql"

            # Adresse de sorti du fichier dumpé
            MysqlFile="${FolderOfSave/%\/}/${SaveName} - $(date +'%Y-%m-%d').sql"
            FilePath="${FolderOfSave/%\/}/${SaveName} - $(date +'%Y-%m-%d').${ext}"

            nice -n ${NiceValue} mysqldump -h "${MysqlHost}" -u "${MysqlUser}" -p"${MysqlPass}" -A > "${MysqlFile}"

            # Comrpession du fichier dumpé
            nice -n ${NiceValue} tar zcvf "${FilePath}" "${MysqlFile}"

            # Suppression du fichier dumpé
            nice -n ${NiceValue} rm "${MysqlFile}"

            break

        # Sinon on les sauvegardes une à une
        else
            # Retour d'infos
            DebugReply "Dump de la base de donnée MySql ${Table}"

            # Adresse de sorti du fichier dumpé
            MysqlFile="${FolderOfSave/%\/}/${SaveName}-${Table} - $(date +'%Y-%m-%d').sql"
            FilePath="${FolderOfSave/%\/}/${SaveName}-${Table} - $(date +'%Y-%m-%d').${ext}"

            nice -n ${NiceValue} mysqldump -h "${MysqlHost}" -u "${MysqlUser}" -p"${MysqlPass}" "${Table}" > "${MysqlFile}"

            # Comrpession du fichier dumpé
            nice -n ${NiceValue} tar zcvf "${FilePath}" "${MysqlFile}"

            # Suppression du fichier dumpé
            nice -n ${NiceValue} rm "${MysqlFile}"
        fi
    done

else
    DebugReply "Pas de sauvegarde des tables ce jour"
fi
}


### Fonction de création du code tar
function TarCommand
{
# -p, --preserve-permissions, --same-permissions
# -c, : Crée une nouvelle archive.
# -f ARCHIVE : Utilise le fichier d'archive ou le périphérique ARCHIVE.
# -g FICHIER : Gère les sauvegardes incrémentielles dans le nouveau format GNU.
# -z : gz
# -j : bzip2
# -J : xz
# --exclude-backups : Exclut du traitement les fichiers de verrouillage et de sauvegarde.
# --atime-preserve : Conserve la date d'accès des fichiers archivés.


cmd="nice -n ${NiceValue} /bin/tar -g \"${FileBin}\" -p -c "

case "${CompressType}" in
    gz) cmd+="-z " ;;
    xz) cmd+="-J " ;;
    bz) cmd+="-j " ;;
esac

cmd+="-f \"${FilePath}\" --full-time "

[[ "${Recursion}" == "False" ]] && cmd+="--no-recursion "

[[ "${ExcludeBackups}" == "True" ]] && cmd+="--exclude-backups "

[[ -e "${FileTemp}" ]] && cmd+="--exclude-from \"${FileTemp}\" "

cmd+="\"${FolderToSave/%\/}\""

DebugReply "${cmd}"
eval "${cmd}"


# Retour d'infos
Size=$(du -c -BM "${FilePath}" | sed -n '$s/\([0-9]*\)M.*/\1/p')
DebugReply "Le fichier tar fait ${Size} mo"

# Suppression du fichier s'il ne contient de fichier
Verification "${FilePath}"
}


### Fonction de suppression de fichiers masters
function MasterRemove
{
### Vérifie qu'il y a bien des fichiers de configs
if [[ -z $(ls "${HOME}/.config/HizoSaveSoftware"/*.cfg) ]]
then
    echo -e "${ROUGE}Il n'y a aucun fichier de config dans le dossier '${HOME}/.config/HizoSaveSoftware'${RAZ}"
    return
fi


### Liste les fichiers de config
PS3="Selectionner la config dans laquelle il faut faire du menage :" multiselect -1 "${HOME}/.config/HizoSaveSoftware"/*.cfg "Exit"

[[ "${multitxt[0]}" == "Exit" ]] && exit


## Import du fichier de config
source "${multitxt[0]}"


# Ext du fichier
case "${CompressType}" in
    gz) ext="tar.gz" ;;
    xz) ext="tar.xz" ;;
    bz) ext="tar.bz" ;;
    *) ext="tar" ;;
esac


# ### Liste les fichiers master de la config
PS3="Selectionner le/les master à supprimer (avec ses mises à jour) :" multiselect "${FolderOfSave}${SaveName}"*".master.${ext}" "Exit"

[[ "${multitxt[0]}" == "Exit" ]] && exit

### Traitement de la demande
for File in "${multitxt[@]}"
do
    ## Examine chaque fichier tar du dossier de sauvegarde
    while read Fifile
    do
        # Si le fichier est le master à supprimer
        if [[ "${Fifile}" == "${File}" ]]
        then
            # Variable indiquant qu'on peut effacer les fichiers maj
            GoDelete="True"

            # Retour d'infos
            DebugReply "Suppression du fichier master ${File} et de ses mises à jour"

            # Suppression du fichier master
            rm -f "${File}"

        # Si le fichier est un master
        elif [[ "${Fifile}" =~ ".master.${ext}" ]]
        then
            # Et qu'on supprimait les maj
            if [[ "${GoDelete}" == "True" ]]
            then
                # On arrete la suppression des fichiers maj
                GoDelete="False"
                break

            # Sinon on saute ce fichier (dans le cas où on est pas encore arrivé au master voulu)
            else
                continue
            fi

        # Si on peut supprimer les fichiers maj, on le fait
        elif [[ "${GoDelete}" == "True" ]]
        then
            rm -f "${Fifile}"
        fi
    done < <(find "${FolderOfSave}" -iname "${SaveName}*.${ext}" | sort)
done

exit
}



### Fonction de création d'un fichier master
function MasterCreate
{
# Nom du nouveau fichier
case "${CompressType}" in
    gz) FileName="${SaveName} - Save of $(date +'%Y-%m-%d-%Hh%M').master.tar.gz" ;;
    xz) FileName="${SaveName} - Save of $(date +'%Y-%m-%d-%Hh%M').master.tar.xz" ;;
    bz) FileName="${SaveName} - Save of $(date +'%Y-%m-%d-%Hh%M').master.tar.bz" ;;
    *) FileName="${SaveName} - Save of $(date +'%Y-%m-%d-%Hh%M').master.tar" ;;
esac

# Adresse du fichier de sortie
FilePath="${FolderOfSave/%\/}/${FileName}"


if [[ -e "${FilePath}" ]]
then
    # Retour d'infos
    DebugReply "Le fichier ${FilePath} existe déjà"
    return
fi


# Vérifie que le fichier n'existe pas déjà
if [[ -n $(find "${FolderOfSave/%\/}" -iname "${SaveName}*$(date +'%Y-%m-%d')*.master.${ext}") ]]
then
    if [[ "${OneSaveByDay}" == "True" ]]
    then
        # Retour d'infos
        DebugReply "Une sauvegarde du jour existe déjà, on ne fait donc rien"
        return
    fi

    # Retour d'infos
    DebugReply "le fichier master du $(date +'%Y-%m-%d') existe déjà."

    # Creation d'une mise à jour
    UpdateCreate

else
    # Suppression du fichier bin pour remise à 0
    [[ -e "${FileBin}" ]] && rm "${FileBin}"

    # Retour d'infos
    DebugReply "création du master : ${FileName}"

    # Création d'un master
    TarCommand
fi
}


### Fonction de mise à jour
function UpdateCreate
{
# Nom du nouveau fichier
case "${CompressType}" in
    gz) FileName="${SaveName} - Save of $(date +'%Y-%m-%d-%Hh%M').tar.gz" ;;
    xz) FileName="${SaveName} - Save of $(date +'%Y-%m-%d-%Hh%M').tar.xz" ;;
    bz) FileName="${SaveName} - Save of $(date +'%Y-%m-%d-%Hh%M').tar.bz" ;;
    *) FileName="${SaveName} - Save of $(date +'%Y-%m-%d-%Hh%M').tar" ;;
esac

# Adresse du fichier de sortie
FilePath="${FolderOfSave/%\/}/${FileName}"


if [[ -e "${FilePath}" ]]
then
    # Retour d'infos
    DebugReply "Le fichier ${FilePath} existe déjà"
    return
fi

if [[ -n $(find "${FolderOfSave/%\/}" -iname "${SaveName}*$(date +'%Y-%m-%d')*.${ext}") && "${OneSaveByDay}" == "True" ]]
then
    # Retour d'infos
    DebugReply "Une sauvegarde du jour existe déjà"
    return
fi

# Retour d'infos
[[ ! -e "${FileBin}" ]] && DebugReply "Le fichier bin n'existe pas ! cela va donc créé une maj comme un master"
DebugReply "Creation d'un fichier mise à jour : ${FileName}"


# Création d'une mise à jour
TarCommand
}


### Fonction de base
function Start
{
# Retour d'infos
DebugReply "*-= ${SaveName} =-*"


# Suppression des fichiers master trop agés
# Utilisation de *.master.tar* car en cas de changement d'extension ça ne marche plus
if [[ ${AgeMax} -gt 0 && $(find "${FolderOfSave/%\/}" -type f -mtime +${AgeMax} -iname "${SaveName}*.master.tar*") ]]
then
    # Retour d'infos
    DebugReply "Suppression des anciens masters"
    DebugReply "$(find "${FolderOfSave/%\/}" -type f -mtime +${AgeMax} -iname "${SaveName}*.master.tar*")"

    # Suppression des masters anciens
    find "${FolderOfSave/%\/}" -type f -mtime +${AgeMax} -iname "${SaveName}*.master.tar*" -delete


    # Recherche du master le plus ancien pour supprimer les fichiers non master plus vieux
    OldMaster=$(find "${FolderOfSave/%\/}" -iname "${SaveName}*.master.tar*" | sort | head -1)

    # Retour d'infos
    DebugReply "Suppression des anciens fichiers"

    # Suppression des fichiers plus vieux que le master le plus ancien (\! -newer "${OldMaster}") sans prendre compte le fichier lui meme (\! -samefile "${OldMaster}")
    DebugReply $(find "${FolderOfSave/%\/}" -maxdepth 1 -iname "${SaveName}*.tar*" \! -newer "${OldMaster}" \! -samefile "${OldMaster}")
    find "${FolderOfSave/%\/}" -maxdepth 1 -iname "${SaveName} - *.tar*" \! -newer "${OldMaster}" \! -samefile "${OldMaster}" -delete
fi



# Verifie que le fichier bin n'est pas vide
[[ ! -s "${FileBin}" && -e "${FileBin}" ]] && rm "${FileBin}"


# Recherche des masters, ici car le dossier peut ne pas exister
Masters=$(find "${FolderOfSave/%\/}" -iname "${SaveName}*.master.tar*" | sort)
OldMaster=$(head -1 <<< "${Masters}")
NewMaster=$(tail -1 <<< "${Masters}")

# Regarde si ce jour est un multiple de la frequence de sauvegarde complète
if [[ $((${DayToDay} % ${DayBetweenMaster})) -eq 0 ]]
then
    # Retour d'infos
    DebugReply "Création d'un master car aujourd'hui est un multiple du diviseur : ${DayToDay} % ${DayBetweenMaster} = $((${DayToDay} % ${DayBetweenMaster}))"

    # Création d'un fichier master
    MasterCreate


# Regarde de quand date le dernier master
elif [[ -n "${NewMaster}" && $(date -d "$(stat "${NewMaster}" -c '%y')" +'%Y-%m-%d') < $(date -d "-${DayBetweenMaster} days" +'%Y-%m-%d') ]]
then
    # Retour d'infos
    DebugReply "Le dernier fichier est ${NewMaster}"
    DebugReply "Création d'un master car le dernier à plus de ${DayBetweenMaster} jour"

    # Création d'un fichier master
    MasterCreate


# Si on est bon au niveau des dates
else
    # Vérifie que le fichier
    if [[ -e "${FileBin}" ]]
    then
        # Création d'une mise à jour
        UpdateCreate

    else
        # Retour d'infos
        DebugReply "Création d'un master car pas de fichier bin"

        # Création d'un fichier master
        MasterCreate
    fi
fi
}


### Début du script
# Crée le dossier de config si besoin
[[ ! -d "${HOME}/.config/HizoSaveSoftware" ]] && mkdir -p "${HOME}/.config/HizoSaveSoftware"


# Récupération du nombre de jour depuis 1900
DayToDay=$(($(date +'%s' -d "$(date +'%D')")/86400))


### Arguments
while getopts ":-:" O "${@}"
do
    if [[ ${O} == "-" ]]
    then
        case ${OPTARG,,} in
            new|create) ConfigCreate ;;
            config-remove) ConfigRemove ;;
            master-remove) MasterRemove ;;
            extract) ExtractSave ;;
            forcemaster) ForceMaster="True" ;;
            view) ViewFiles="True" ;;
            fullview|viewfull) ViewFiles="True"; ViewFilesComplete="True" ;;
            lastview|viewlast) ViewFiles="True"; ViewLast="True" ;;
            help|*) echo -e "${FUSHIA}${OPTARG}${ROUGE} n'est pas un argument valide !${RAZ}\n
Voici la liste des arguments possibles :
${FUSHIA}--new ou --create${RAZ}:${BLEUFONCE} Permet de créer un fichier de config.
${FUSHIA}--config-remove ${RAZ}:${BLEUFONCE} Permet de supprimer des fichiers de config.
${FUSHIA}--master-remove ${RAZ}:${BLEUFONCE} Permet de supprimer des fichiers MasterRemove.
${FUSHIA}--extract ${RAZ}:${BLEUFONCE} Permet d'extraire un master et toutes ses mise à jours.
${FUSHIA}--forcemaster ${RAZ}:${BLEUFONCE} Force la création de master (supprime les fichiers bin).
${FUSHIA}--view ${RAZ}:${BLEUFONCE} Permet de lister le nombre de sauvegarde et la taille totale.
${FUSHIA}--fullview ${RAZ}:${BLEUFONCE} Permet de lister le nombre de sauvegarde et la taille totale avec le détail des fichiers.
${FUSHIA}--fulllast ${RAZ}:${BLEUFONCE} Permet de lister le nombre de sauvegarde et la taille totale avec le détail des derniers fichiers.
${FUSHIA}--help ${RAZ}:${BLEUFONCE} Permet d'afficher cette aide.\n"

                    exit ;;
        esac
    fi
done

# Gestion des arguments et commandes
shift $(($OPTIND-1))


# Création d'un fichier de config si besoin
if [[ -z $(find "${HOME}/.config/HizoSaveSoftware" -type f) ]]
then
    PS3="Aucun fichier de config trouvé, voulez vous en créer un ?" multiselect -1 "Oui" "Non" "Exit"

    [[ "${multitxt[0]}" == "Oui" ]] && ConfigCreate || exit
fi


# Traitement des fichiers de configs un à un
while read File
do
    # Chargement des configs
    source "${File}"


    # Extension du fichier
    case "${CompressType}" in
        gz) ext="tar.gz" ;;
        xz) ext="tar.xz" ;;
        bz) ext="tar.bz" ;;
        *) ext="tar" ;;
    esac


    # Dans le cas d'une demande de listage
    if [[ "${ViewFiles}" == "True" ]]
    then
        Size=$(du -c -BM "${FolderOfSave/%\/}/${SaveName}"*.${ext} | sed -n '$s/\([0-9]*\)M.*/\1/p')
        NbFile=$(ls -l "${FolderOfSave/%\/}/${SaveName}"*.${ext} | wc -l)

        # Dans le cas ou ce n'est pas un dump mysql
        if [[ -z "${MysqlUser}" ]]
        then
            NbMaster=$(ls -l "${FolderOfSave/%\/}/${SaveName}"*.master.${ext} | wc -l)

            echo -e "\n${FUSHIA}${SaveName}${RAZ} :
\t└> Un fichier master doit être créé tous les ${BLEUFONCE}${DayBetweenMaster}${RAZ} jours et les sauvegardes ont une durée de vie de ${BLEUFONCE}${AgeMax}${RAZ} jours.
\t└> Il y a ${BLEUFONCE}${NbFile}${RAZ} fichier(s) dont ${BLEUFONCE}${NbMaster}${RAZ} master pour un poids total de ${BLEUFONCE}${Size}${RAZ} MegaOctet(s)."

        else
            echo -e "\n${FUSHIA}${SaveName}${RAZ} :
\t└> Les sauvegardes ont une durée de vie de ${BLEUFONCE}${AgeMax}${RAZ} jours.
\t└> Il y a ${BLEUFONCE}${NbFile}${RAZ} fichier(s) pour un poids total de ${BLEUFONCE}${Size}${RAZ} MegaOctet(s)."
        fi


        # Dans le cas d'une demande de listage complete
        if [[ "${ViewFilesComplete}" == "True" ]]
        then
            while read TarFile
            do
                LittleSize=$(du -BM "${TarFile}" | sed 's/\([0-9]*\)M.*/\1/')
                echo -e "\t└> ${TarFile##*/} : ${BLEUFONCE}${LittleSize}${RAZ} Mo"
            done < <(ls -1 "${FolderOfSave/%\/}/${SaveName}"*.${ext})

        elif [[ "${ViewLast}" == "True" ]]
        then
            TarFile=$(ls -1 "${FolderOfSave/%\/}/${SaveName}"*.${ext} | tail -1)
            LittleSize=$(du -BM "${TarFile}" | sed 's/\([0-9]*\)M.*/\1/')
            echo -e "\t└> ${TarFile##*/} : ${BLEUFONCE}${LittleSize}${RAZ} Mo"

        fi

        continue
    fi


    # Si le dossier de sortie n'existe pas, on le crée
    [[ ! -d "${FolderOfSave}" ]] && mkdir "${FolderOfSave}"


    # Envoie de la date au fichier de retour d'infos
    DebugReply "\n$(date +'%Y-%m-%d-%Hh%M')"


    # Lancement du dump de mysql
    if [[ -n "${MysqlUser}" ]]
    then
        DumpOfMysql


    # Lancement de la sauvegarde
    else
        # Verification logique
        if [[ ${DayBetweenMaster} -gt ${AgeMax} ]]
        then
            DebugReply "${SaveName} : Il est impossible que le nombre de jour entre les sauvegardes soit supérieur à la durée de vie des master."
            continue
        fi


        FileBin="${FolderOfSave/%\/}/${SaveName} - FileList.incremental.bin" # Adresse du fichier bin de sauvegarde


        # En cas de forcage de master
        [[ "${ForceMaster}" == "True" && -e "${FileBin}" ]] && rm "${FileBin}"


        # Création du fichier temporaire
        FileTemp=$(mktemp)


        # Création du fichier listant les items à ne pas sauvegarder, les dossiers ne doivent pas se terminer avec /
        for Folder in "${ItemsToExclude[@]}"
        do
            echo "${Folder/%\/}" >> "${FileTemp}"
        done


        # Lance le traitement du dossier à sauvegarder
        echo -e "Traitement de la sauvegarde ${BLEUFONCE}${SaveName}${RAZ}."
        Start "${FolderToSave/%\/}"


        # Suppression du fichier temporaire
        [[ -e "${FileTemp}" ]] && rm "${FileTemp}"
    fi


    # Suppression des variables
    unset SaveName NiceValue FolderToSave Recursion FolderOfSave DayBetweenMaster AgeMax OneSaveByDay DebugMode ItemsToExclude DayBetweenSave MysqlUser MysqlHost MysqlPass MysqlTable
done < <(find "${HOME}/.config/HizoSaveSoftware" -type f -iname "*.cfg")

Il permet de donc de choisir le nombre de jours entre les sauvegardes incrémentielles, entre les grosses sauvegardes et fonctionne avec mysql.

Dernière modification par Hizoka (Le 13/04/2017, à 18:09)


KDE Neon 64bits
Tous mes softs (MKVExtractorQt, HizoSelect, HizoProgress, Qtesseract, Keneric, Services menus...) sont sur github

Hors ligne