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/07/2020, à 12:55

Flashneo

[Résolu] Problème crontab execution script

Bonjour,

Je viens vers vous car je bloque sur un problème d'exécution d'un script avec la crontab.

Pour vous expliquer, j'héberge un serveur minecraft sur mon raspberry et j'ai donc écris un script bash pour pouvoir lancer des sauvegardes automatique du monde.
Le script lors de son exécution doit faire les étapes suivantes :
     - Vérifie si le dossier de backup existe sinon le créer
     - Envoie un message sur le serveur exécuté dans un screen pour prévenir les joueurs
     - Archive de façon incrémental le monde à sauvegarder
     - Envoie un message sur le serveur pour prévenir que l'exécution du script est terminé + quelques infos

Mon problème est que lorsque que je lance le script avec la commande :

./backup.sh

Tout ce passe bien, les messages sont envoyé sur le serveur, la sauvegarde est créer. Si c'est la première sauvegarde la taille de l'archive parait logique et contient tout le dossier sauvegardé.

Si je relance le script une seconde fois à la main, l'archivage incremental fonctionne et l'archive créé contient bien uniquement les fichiers modifiés.

Par contre lorsque le script est lancé automatiquement avec la crontab :

0 */3 * * * /home/flashneo/minecraft/backup.sh

Le script se lance bien, le message pour prévenir qu'une sauvegarde commence est bien affiché en jeu, une archive est bien créé mais le problème est qu'elle à une taille ridiculement petite et que le message d'après ne s'affiche pas en jeu...

Je ne sais pas si c'est un problème de droit ou autre car sinon le script ne se lancerais peut-être tout simplement pas ?

Enfin voilà, je viens vers vous car je connais que très peu crontab et je n'arrive pas à solutionner mon problème malgré plusieurs recherches.

Voilà mon fichier backup.sh

#!/bin/bash

################################################################
#                                                              #
################################################################

# Configuration ###########################
BACKUP_DIRECTORY="./mnt/library/backupMinecraft"
WORLD_TO_BACKUP="./world"
SCREEN_NAME="serverMinecraft"
ADMIN_PSEUDO="Flashneo"
PREFIX="AutoBackup"
ENABLE_CHAT_MESSAGE=true
ENABLE_ADMIN_MESSAGE=true
CONSOLE_LOG=false
ENABLE_LOG_FILE=true
LOG_FILE="./backup.log"
LOG_ERROR_FILE="./backup.error.log"
###########################################

# Do not modify
DATE_FORMAT="%F_%H%M"
DATE=$(date +$DATE_FORMAT)

ARCHIVE_FILE_NAME=$DATE.tar.gz
ARCHIVE_PATH=$BACKUP_DIRECTORY/$ARCHIVE_FILE_NAME


################################################################
#      Minecraft console commands                              #
################################################################

exec_cmd () {
    local COMMAND=$1
    if [[ $SCREEN_NAME != "" ]]; then
        if screen -ls | grep -q $SCREEN_NAME; then
            screen -S $SCREEN_NAME -p 0 -X stuff "$COMMAND$(printf \\r)"
        fi
    fi
}

send_message () {
    if $ENABLE_CHAT_MESSAGE; then
        local MESSAGE=$1
        exec_cmd "tellraw @a [\"\",{\"text\":\"[\",\"color\":\"white\"},{\"text\":\"$PREFIX\",\"color\":\"dark_gray\"},{\"text\":\"] \",\"color\":\"white\"},{\"text\":\"$MESSAGE\",\"color\":\"gold\"}]"
    fi
}

send_message_to_admin () {
    if $ENABLE_ADMIN_MESSAGE; then
        local MESSAGE=$1
        exec_cmd "tellraw $ADMIN_PSEUDO [\"\",{\"text\":\"[\",\"color\":\"white\"},{\"text\":\"$PREFIX\",\"color\":\"dark_gray\"},{\"text\":\"] \",\"color\":\"white\"},{\"text\":\"$MESSAGE\",\"color\":\"gold\"}]"
    fi
}


################################################################
#      Backup world                                            #
################################################################

backup () {
    # Disable world autosaving
    exec_cmd "save-off"

    send_message "Starting backup of world"
    if $CONSOLE_LOG; then
        echo "======================================================="
        echo "$DATE"
        echo "Starting backup of $WORLD_TO_BACKUP"
    fi

    # Compress files    ##########################
    local START_TIME=$(date +"%s")

    # Compression with incremental (save more space)
    tar -z --create --file=$ARCHIVE_PATH --listed-incremental=$BACKUP_DIRECTORY/save.list $WORLD_TO_BACKUP
    sync

    local END_TIME=$(date +"%s")
    ##############################################

    # Enable world autosaving
    exec_cmd "save-on"
    # Force world save
    exec_cmd "save-all"

    # Calculates variables
    WORLD_SIZE_BYTES=$(du -b --max-depth=0 $WORLD_TO_BACKUP | awk '{print $1}')
    ARCHIVE_SIZE_BYTES=$(du -b $ARCHIVE_PATH | awk '{print $1}')

    # Display variables
    COMPRESSION_PERCENT=$(( 100 - ($ARCHIVE_SIZE_BYTES * 100 / $WORLD_SIZE_BYTES)))
    WORLD_SIZE=$(du -h --max-depth=0 $WORLD_TO_BACKUP | awk '{print $1}')
    ARCHIVE_SIZE=$(du -h $ARCHIVE_PATH | awk '{print $1}')
    BACKUP_DIRECTORY_SIZE=$(du -h --max-depth=0 $BACKUP_DIRECTORY | awk '{print $1}')
    local EXECUTION_TIME=$(($END_TIME - $START_TIME))

    # Display ending message    ###################
    if [[ "$ARCHIVE_SIZE" != "" ]]; then
        send_message "Backup finish successfuly !"
        send_message_to_admin "Backup finish in $EXECUTION_TIME s, $ARCHIVE_SIZE/$WORLD_SIZE, compression $COMPRESSION_PERCENT%"
        send_message_to_admin "Total space used in $BACKUP_DIRECTORY : $BACKUP_DIRECTORY_SIZE"
        if $CONSOLE_LOG; then
            echo "Backup finish in $EXECUTION_TIME s, $ARCHIVE_SIZE/$WORLD_SIZE, compression $COMPRESSION_PERCENT%"
            echo "Total space used in $BACKUP_DIRECTORY : $BACKUP_DIRECTORY_SIZE"
            echo "======================================================="
        fi
    else
        send_message "Error in backup process... World not save !"
        if $CONSOLE_LOG; then
            echo "Error in backup process... World not save !"
            echo "======================================================="
        fi
    fi
}


################################################################
#      Restore world                                           #
################################################################

restore () {
    local ACTION=$1

    if [[ $ACTION == 'restore' ]]; then
        echo "Starting restore of $WORLD_TO_BACKUP"
    else
        echo "Start extracting old backup..."
        cd "$BACKUP_DIRECTORY/"
    fi

    local START_TIME=$(date +"%s")
    
    # Decompress files    ##########################
    if [[ $ACTION == 'restore' ]]; then
        for backup in `ls $BACKUP_DIRECTORY | grep /*.tar`
        do
            tar --extract --listed-incremental=/dev/null --file $BACKUP_DIRECTORY/$backup
        done
    else
        for backup in `ls | grep /*.tar`
        do
            tar --extract --listed-incremental=/dev/null --file $backup
        done
    fi

    sync
    ################################################

    local END_TIME=$(date +"%s")
    local EXECUTION_TIME=$(($END_TIME - $START_TIME))

    if [[ $ACTION == 'restore' ]]; then
        echo "Ending restore of world in $EXECUTION_TIME s"
    else
        echo "Old backup extract in $EXECUTION_TIME s"
        cd ../
    fi
}


################################################################
#      Delete old backup                                       #
################################################################

# To do...

################################################################
#      Initialize script                                       #
################################################################

# Save log in file
if $ENABLE_LOG_FILE; then
    exec 1>>$LOG_FILE
    exec 2>>$LOG_ERROR_FILE
fi

# Create backup directory if not exist
if ! [[ -d $BACKUP_DIRECTORY ]]; then
    mkdir $BACKUP_DIRECTORY
fi

# Redirect function
if [[ $1 != '' && $1 == '-restore' ]]; then
    restore "restore"
else
    backup
fi

Et un screen de mon dossier backupMinecraft ou on peut voir la taille de l'archive (sachant que la première sauvegarde à été lancé manuellement et les autres automatiquement) :
https://imgshare.io/images/2020/07/06/Capture-du-2020-07-06-12-51-11.png

Edit: C'était simplement un problème dans mes variables, le chemin était relatif alors qu'il faut le chemin complet.

Dernière modification par Flashneo (Le 06/07/2020, à 17:16)

Hors ligne

#2 Le 06/07/2020, à 14:13

kerenoc

Re : [Résolu] Problème crontab execution script

Peut-être mettre "set -x" en début de backup.sh et récupérer les sorties stdout et stderr pour analyser ce qui se passe?

Hors ligne

#3 Le 06/07/2020, à 14:22

Flashneo

Re : [Résolu] Problème crontab execution script

Pour les sorties stdout et stderr est-ce que la ligne dans le script est bonne :

exec 1>>$LOG_FILE
exec 2>>$LOG_ERROR_FILE

pour le set -x, je n'ai pas de sortie lorsqu'il est exécuté par la crontab, mais j'ai une sortie quand je le lance manuellement.

Dernière modification par Flashneo (Le 06/07/2020, à 14:33)

Hors ligne

#4 Le 06/07/2020, à 15:24

kamaris

Re : [Résolu] Problème crontab execution script

Il faut mettre les chemins complets des exécutables dans le script, ou définir le path : https://doc.ubuntu-fr.org/cron#autres_considerations

Hors ligne

#5 Le 06/07/2020, à 15:48

Flashneo

Re : [Résolu] Problème crontab execution script

Je viens d'essayer en définissant le path dans ma crontab comme indiqué dans le lien, mais même après un restart du service ça ne change rien hmm

Du coup j'ai voulu essayé l'autre méthode proposé, mais je n'arrive pas à tomber sur le chemin complet de l'exécutables de "tar", y a t-il un site qui répertorie tous les chemins des commandes ?

Edit : J'ai trouvé pour tar c'est /bin/tar, du coup j'ai remplacé dans le script mais toujours pareil, l'exécution par la crontab ne donne rien

Dernière modification par Flashneo (Le 06/07/2020, à 16:06)

Hors ligne

#6 Le 06/07/2020, à 16:08

kamaris

Re : [Résolu] Problème crontab execution script

command -v tar

Tu peux remplacer tes noms de commande par

$(command -v nom-de-commande)

dans le script

Hors ligne

#7 Le 06/07/2020, à 16:14

Flashneo

Re : [Résolu] Problème crontab execution script

Je viens d'essayer et j'ai toujours le même problème

Hors ligne

#8 Le 06/07/2020, à 16:18

kamaris

Re : [Résolu] Problème crontab execution script

Bah j'ai dit une bêtise, désolé : si tu remplaces les noms de commandes par $(command -v nom-de-commande), ça ne marchera pas mieux, car command -v se base sur le PATH…
Il faut que tu indiques les chemins complets en dur.

Après, peut-être que ça n'est pas (que) ça le problème effectivement, mais c'est souvent le cas.

Hors ligne

#9 Le 06/07/2020, à 16:23

Flashneo

Re : [Résolu] Problème crontab execution script

Ce que je comprend pas c'est que ça me créer bien des archives à chaque fois mais elles sont toutes vides... Et le "exec 1>> $LOG_FILE" que j'ai mis n'est pas modifier quand c'est cron qui lance le script

J'ai pourtant essayé de mettre les chemins en dure ^^

Dernière modification par Flashneo (Le 06/07/2020, à 16:24)

Hors ligne

#10 Le 06/07/2020, à 16:27

kerenoc

Re : [Résolu] Problème crontab execution script

Vérifier quel shell est utilisé par crontab. Si c'est /bin/sh il est peut-être plus prudent de mettre une entrée de type "backup.sh 2>&1 >> mon_fichier_log"

Dernière modification par kerenoc (Le 06/07/2020, à 16:27)

Hors ligne

#11 Le 06/07/2020, à 16:33

kamaris

Re : [Résolu] Problème crontab execution script

Ah mais il y a tous tes chemins définis en relatif en entrée de script aussi, dont WORLD_TO_BACKUP="./world".
Ça ça ne peut pas marcher que lorsque tu lances le script du bon endroit, indépendamment de cron.

Hors ligne

#12 Le 06/07/2020, à 16:36

Flashneo

Re : [Résolu] Problème crontab execution script

Du coup ça veut dire que je dois mettre les chemins en dur en entrée ?

Hors ligne

#13 Le 06/07/2020, à 16:40

kamaris

Re : [Résolu] Problème crontab execution script

Pas obligé non : tu dois pouvoir définir

BASEDIR=$(/usr/bin/dirname "$0")

Puis

WORLD_TO_BACKUP="$BASEDIR/world"

À condition que le script soit lui-même au bon endroit, bien entendu !

Dernière modification par kamaris (Le 06/07/2020, à 16:44)

Hors ligne

#14 Le 06/07/2020, à 16:42

Flashneo

Re : [Résolu] Problème crontab execution script

Ok, j'ai testé avec le chemin complet partout et ça fonctionne très bien smile

à quoi sert le "$0" ?

Hors ligne

#15 Le 06/07/2020, à 16:47

kamaris

Re : [Résolu] Problème crontab execution script

C'est le premier (ou l'avant premier) paramètre positionnel, qui contient ici le nom sous lequel le script est appelé.
Cf. man bash wink

Dernière modification par kamaris (Le 06/07/2020, à 16:48)

Hors ligne

#16 Le 06/07/2020, à 16:53

Flashneo

Re : [Résolu] Problème crontab execution script

Super, merci je vais essayé ça alors !

Sinon, c'est un autre problème mais j'ai remarqué que si je lance mon script manuellement la première, puis si la seconde fois est lancé par cron l'archive est reconstruite en entier et il n'utilise pas l'incrémentation d'archive...
C'est un problème de droit ?

Hors ligne

#17 Le 06/07/2020, à 16:59

kamaris

Re : [Résolu] Problème crontab execution script

Tu peux reposter le script que tu lances par cron maintenant, après modifs ?

Hors ligne

#18 Le 06/07/2020, à 17:02

Flashneo

Re : [Résolu] Problème crontab execution script

Voilà :

#!/bin/bash

################################################################
#                                                              #
################################################################

# Configuration ###########################
BACKUP_DIRECTORY="/mnt/library/backupMinecraft"
WORLD_TO_BACKUP="/home/flashneo/minecraft/world"
SCREEN_NAME="serverMinecraft"
ADMIN_PSEUDO="Flashneo"
PREFIX="AutoBackup"
ENABLE_CHAT_MESSAGE=true
ENABLE_ADMIN_MESSAGE=true
CONSOLE_LOG=true
ENABLE_LOG_FILE=true
LOG_FILE="/home/flashneo/minecraft/backup.log"
LOG_ERROR_FILE="/home/flashneo/minecraft/backup.error.log"
###########################################

# Do not modify
DATE_FORMAT="%F_%H%M"
DATE=$(date +$DATE_FORMAT)

ARCHIVE_FILE_NAME=$DATE.tar.gz
ARCHIVE_PATH=$BACKUP_DIRECTORY/$ARCHIVE_FILE_NAME

################################################################
#      Minecraft console commands                              #
################################################################

exec_cmd () {
    local COMMAND=$1
    if [[ $SCREEN_NAME != "" ]]; then
        if screen -ls | grep -q $SCREEN_NAME; then
            screen -S $SCREEN_NAME -p 0 -X stuff "$COMMAND$(printf \\r)"
        fi
    fi
}

send_message () {
    if $ENABLE_CHAT_MESSAGE; then
        local MESSAGE=$1
        exec_cmd "tellraw @a [\"\",{\"text\":\"[\",\"color\":\"white\"},{\"text\":\"$PREFIX\",\"color\":\"dark_gray\"},{\"text\":\"] \",\"color\":\"white\"},{\"text\":\"$MESSAGE\",\"color\":\"gold\"}]"
    fi
}

send_message_to_admin () {
    if $ENABLE_ADMIN_MESSAGE; then
        local MESSAGE=$1
        exec_cmd "tellraw $ADMIN_PSEUDO [\"\",{\"text\":\"[\",\"color\":\"white\"},{\"text\":\"$PREFIX\",\"color\":\"dark_gray\"},{\"text\":\"] \",\"color\":\"white\"},{\"text\":\"$MESSAGE\",\"color\":\"gold\"}]"
    fi
}


################################################################
#      Backup world                                            #
################################################################

backup () {
    # Disable world autosaving
    exec_cmd "save-off"

    send_message "Starting backup of world"
    if $CONSOLE_LOG; then
        echo "======================================================="
        echo "$DATE"
        echo "Starting backup of $WORLD_TO_BACKUP"
    fi

    # Compress files    ##########################
    local START_TIME=$(date +"%s")

    # Compression with incremental (save more space)
    tar -z --create --file=$ARCHIVE_PATH --listed-incremental=$BACKUP_DIRECTORY/save.list $WORLD_TO_BACKUP
    sync

    local END_TIME=$(date +"%s")
    ##############################################

    # Enable world autosaving
    exec_cmd "save-on"
    # Force world save
    exec_cmd "save-all"

    # Calcul variables
    WORLD_SIZE_BYTES=$(du -b --max-depth=0 $WORLD_TO_BACKUP | awk '{print $1}')
    ARCHIVE_SIZE_BYTES=$(du -b $ARCHIVE_PATH | awk '{print $1}')

    # Display variables
    COMPRESSION_PERCENT=$(( 100 - ($ARCHIVE_SIZE_BYTES * 100 / $WORLD_SIZE_BYTES)))
    WORLD_SIZE=$(du -h --max-depth=0 $WORLD_TO_BACKUP | awk '{print $1}')
    ARCHIVE_SIZE=$(du -h $ARCHIVE_PATH | awk '{print $1}')
    BACKUP_DIRECTORY_SIZE=$(du -h --max-depth=0 $BACKUP_DIRECTORY | awk '{print $1}')
    local EXECUTION_TIME=$(($END_TIME - $START_TIME))

    # Display ending message    ###################
    if [[ "$ARCHIVE_SIZE" != "" ]]; then
        send_message "Backup finish successfuly !"
        send_message_to_admin "Backup finish in $EXECUTION_TIME s, $ARCHIVE_SIZE/$WORLD_SIZE, compression $COMPRESSION_PERCENT%"
        send_message_to_admin "Total space used in $BACKUP_DIRECTORY : $BACKUP_DIRECTORY_SIZE"
        if $CONSOLE_LOG; then
            echo "Backup finish in $EXECUTION_TIME s, $ARCHIVE_SIZE/$WORLD_SIZE, compression $COMPRESSION_PERCENT%"
            echo "Total space used in $BACKUP_DIRECTORY : $BACKUP_DIRECTORY_SIZE"
            echo "======================================================="
        fi
    else
        send_message "Error in backup process... World not save !"
        if $CONSOLE_LOG; then
            echo "Error in backup process... World not save !"
            echo "======================================================="
        fi
    fi
}


################################################################
#      Restore world                                           #
################################################################

restore () {
    local ACTION=$1

    if [[ $ACTION == 'restore' ]]; then
        echo "Starting restore of $WORLD_TO_BACKUP"
    else
        echo "Start extracting old backup..."
        cd "$BACKUP_DIRECTORY/"
    fi

    local START_TIME=$(date +"%s")
    
    # Decompress files    ##########################
    if [[ $ACTION == 'restore' ]]; then
        for backup in `ls $BACKUP_DIRECTORY | grep /*.tar`
        do
            tar --extract --listed-incremental=/dev/null --file $BACKUP_DIRECTORY/$backup
        done
    else
        for backup in `ls | grep /*.tar`
        do
            tar --extract --listed-incremental=/dev/null --file $backup
        done
    fi

    sync
    ################################################

    local END_TIME=$(date +"%s")
    local EXECUTION_TIME=$(($END_TIME - $START_TIME))

    if [[ $ACTION == 'restore' ]]; then
        echo "Ending restore of world in $EXECUTION_TIME s"
    else
        echo "Old backup extract in $EXECUTION_TIME s"
        cd ../
    fi
}


################################################################
#      Delete old backup                                       #
################################################################

# To do...

################################################################
#      Initialize script                                       #
################################################################

# Save log in file
if $ENABLE_LOG_FILE; then
    exec 1>>$LOG_FILE
    exec 2>>$LOG_ERROR_FILE
fi

# Create backup directory if not exist
if ! [[ -d $BACKUP_DIRECTORY ]]; then
    mkdir $BACKUP_DIRECTORY
fi

# Redirect function
if [[ $1 != '' && $1 == '-restore' ]]; then
    restore "restore"
else
    backup
fi

J'ai pas encore eu le temps d'ajouter ce que tu m'as dit

Dernière modification par Flashneo (Le 06/07/2020, à 17:03)

Hors ligne

#19 Le 06/07/2020, à 17:08

kamaris

Re : [Résolu] Problème crontab execution script

Tu es sûr de ton BACKUP_DIRECTORY ?
En #1, c'était

BACKUP_DIRECTORY="./mnt/library/backupMinecraft"
WORLD_TO_BACKUP="./world"

Donc là, est-ce que ça ne devrait pas être

BACKUP_DIRECTORY="/home/flashneo/minecraft/mnt/library/backupMinecraft"
WORLD_TO_BACKUP="/home/flashneo/minecraft/world"

?
Car ce BACKUP_DIRECTORY est justement impliqué dans le caractère incrémental de la sauvegarde (il me semble).

Dernière modification par kamaris (Le 06/07/2020, à 17:11)

Hors ligne

#20 Le 06/07/2020, à 17:12

Flashneo

Re : [Résolu] Problème crontab execution script

Oui, le script c'est lancé et a bien sauvegarder au bon endroit, après c'est sur un disque dur externe et pour y accéder je tape

cd /mnt/library/backupMinecraft

Et ça peu importe ou je suis ^^

Et oui c'est bien là qu'est sauvegarder le fichier ".list" utiliser par le tar incremental, en plus des archives créés

Hors ligne

#21 Le 06/07/2020, à 17:15

Flashneo

Re : [Résolu] Problème crontab execution script

J'avais pas remarqué mais en #1 j'ai fait une erreur du coup en mettent le ./ au lieu de juste / devant le chemin

Hors ligne

#22 Le 06/07/2020, à 17:17

kamaris

Re : [Résolu] Problème crontab execution script

Ok, mais du coup c'est bien avec cette dernière version du script (celle postée en #18) que tu as fait le test de lancer une première sauvegarde manuelle puis une seconde par cron (comme tu dis en #16) ?

Hors ligne

#23 Le 06/07/2020, à 17:24

Flashneo

Re : [Résolu] Problème crontab execution script

Oui, c'est bien avec cette version du script

Hors ligne

#24 Le 06/07/2020, à 17:30

kamaris

Re : [Résolu] Problème crontab execution script

Bah je sais pas trop alors, j'utilise pas assez cron et les sauvegardes incrémentales pour y voir bien clair, et j'ai pas trop envie de me lancer dans ce genre de tests en ce moment ! big_smile

Hors ligne

#25 Le 06/07/2020, à 17:33

Flashneo

Re : [Résolu] Problème crontab execution script

C'est pas grave, déjà tout fonctionne et j'ai des sauvegardes régulières ça me convient parfaitement !

En tout cas merci pour l'aide, je pense que j'aurais jamais pensé à un truc si bête ^^

Bonne fin de journée !

Hors ligne