faire un cronjob attendre la fin du travail rsync précédent

11

J'utilise rsync pour sauvegarder certaines données d'un serveur à un autre. Tout fonctionne bien, mais cela peut prendre plus de temps selon la quantité de données à transférer.

Existe-t-il un moyen garanti de s'assurer qu'une commande rsync ne démarre pas avant que la précédente ait fini d'utiliser un cronjob?

Par exemple, toutes les heures, j'exécute la commande rsync, mais il est possible que le transfert prenne plus d'une heure, de sorte que la suivante commence avant la fin de la précédente.

chovy
la source
Si le travail prend potentiellement plus d'une heure pour être terminé et que vous le planifiez plus près que la durée, vous planifiez mal le travail. Soit trouver comment réduire le temps ou augmenter l'intervalle entre les travaux. Si vous effectuez continuellement des sauvegardes à distance, vous souhaiterez peut-être envisager un nouveau plan de reprise après sinistre.
vgoff

Réponses:

11

Vous pouvez implémenter une sorte de verrouillage. Cela affichera le nombre de processus rsync toujours en cours d'exécution:

pgrep -cx rsync

Et cela exécutera le rsync uniquement si aucun autre processus rsync n'existe:

pgrep -cx rsync || rsync ...

L'utilisation -xempêchera de faire correspondre accidentellement des noms indésirables (par exemple "fooba rsync hronizator" ou "not_an_ rsync _totally" - cela fonctionne comme pgrep -c ^rsync$)

mgabriel
la source
Au cas où ce n'est pas évident. -c compte le nombre de processus qui portent le nom rsync. Si ce n'est pas 0, le shell interprète le résultat comme vrai (pas faux). Le || "ou lignes" voir le premier élément est vrai et ne prenez pas la peine d'exécuter le deuxième élément, rsync.
voler
13

Vous pouvez utiliser la commande flock pour vous aider à le faire, par exemple. Dans ce cas, flock -nc'est probablement ce que vous voulez car cela entraînera un échec immédiat de la commande s'il ne peut pas obtenir le verrou, par exemple.

30 * * * *  /usr/bin/flock -n /tmp/myRsyncJob.lck /path/to/your/rsyncScript 
user9517
la source
En général, les noms de fichiers prévisibles dans / tmp sont souvent dangereux en raison des conditions de concurrence et d'un large accès au répertoire / tmp. Est-ce sûr dans ce cas?
mc0e
Dans ce cas, un nom prévisible n'est pas seulement sûr, il est nécessaire; c'est ce qui fait que le verrou (nom) est verrouillé (verbe). En d'autres termes, l'état du verrou est basé spécifiquement et uniquement sur l'existence d'un fichier avec un nom spécifique et prévisible. Si le nom du fichier était imprévisible, ou s'il changeait dynamiquement, flock permettrait à rsync de s'exécuter sur lui-même, ce qui irait à l'encontre du but. Cependant, vous pouvez atténuer vos inquiétudes et être un peu plus "correct" en plaçant le fichier de verrouillage quelque part, comme à la /var/runplace.
Evan de la Cruz
3

Si vous êtes prêt à envisager d'autres outils, vous pouvez également consulter rdiff-backup . Il utilise librsync pour effectuer des sauvegardes et enregistre un nombre configurable de deltas / incréments. Il se verrouille également afin qu'un seul processus de sauvegarde rdiff puisse s'exécuter à un moment donné.

EdwardTeach
la source
J'utilise également rdiff-backup. Mais vous devez être prudent dans cette configuration car rdiff-backup prend plus de temps à terminer que rsync seul.
mgabriel
3

Voici ce que je ferais. Créez un script wrapper autour de rsync pour créer un fichier de verrouillage.

script 1
- create lock file
- rsync
- remove lock file

script 2 (running later then script 1)
- check if lock file is there
    - if not run
    - if it is there wait 10 minutes in a loop. break out of lopp when the lock file is gone
- continue to run script
Mike
la source
2
Assurez-vous également de supprimer également le fichier de verrouillage après un redémarrage, sinon vous pourriez vous retrouver avec un processus qui ne s'exécute plus jamais.
John Gardeniers
2

Ma réponse est un peu la même que ce que Mike a dit.

Dans le script, vous devez mettre quelque chose comme ceci:

  • créer un fichier de verrouillage
  • Vérifiez l'existence du fichier de verrouillage lors de sa prochaine exécution.

Mais il y a une chose très importante que vous devriez faire. et cela pour mettre en place un système de piège.

Donc, avec cela, ce que vous pouvez faire, c'est que même si votre script est tué ou quelqu'un l'a tué, vous pouvez intercepter ce signal et supprimer le fichier de verrouillage, de sorte que vous n'ayez pas de fichier de verrouillage périmé.

Vous pouvez lire comment implémenter cela ici .

Juste une petite chose, vous ne pouvez pas intercepter le signal 9, je veux dire si quelqu'un le fait kill -9, vous ne pouvez pas intercepter cela car ce signal interagit directement avec le noyau et il n'y a aucun moyen de l'intercepter.

En outre, comme l'a suggéré John, vous devez supprimer le fichier de verrouillage à chaque redémarrage de votre système, juste pour vous assurer qu'il ne reste plus de fichier périmé.

Vous pouvez facilement le faire en plaçant une petite rm -f <FILE>commande dans /etc/rc.local

Napster_X
la source
1

Jetez un œil à anacron (cron anachronique) avec le commutateur -s (sérialiser). Sérialiser garantit que la commande ne sera pas appelée à nouveau si la précédente est toujours en cours d'exécution.

tu-Reinstate Monica-dor duh
la source
Vous avez peut-être mal compris la question.
John Gardeniers
Je ne pense pas. La question est "Existe-t-il un moyen garanti de s'assurer qu'une commande rsync ne démarre pas avant que la précédente n'ait fini d'utiliser un cronjob?" Anacron exécute des tâches cron avec des fonctionnalités supplémentaires / différentes. Sérialiser garantit que toute commande que vous appelez ne démarre pas avant la fin de la précédente.
tu-Reinstate Monica-dor duh
Mes excuses. C'est moi qui ai mal lu la question.
John Gardeniers
0

Je n'ai pas pu faire fonctionner la solution de mgabriel sur OSX car la version OSX de pgrep ne semble pas avoir l'option -c (je suppose que c'est pour le compte). Au lieu de cela, j'ai utilisé ce qui suit:

[ $(pgrep ping | wc -l) -eq 0 ] && ping multiplay.co.uk || echo "Sorry, ping already in progress"

J'ai utilisé ping comme exemple de commande.

J'espère que cela t'aides.

kabadisha
la source