nutools/uscrontab

204 lines
7.4 KiB
Plaintext
Raw Normal View History

2013-08-27 15:14:44 +04:00
#!/bin/bash
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
function display_help() {
uecho "$scriptname: lancer une suite de commande en respectant une planification de type cron
USAGE
$scriptname [options] /path/to/crontab
2013-09-29 16:58:08 +04:00
$scriptname -l [/path/to/crontab]
2013-08-27 15:14:44 +04:00
2013-09-29 16:58:08 +04:00
La première forme du script doit normalement être lancé toutes les minutes par
une tâche cron. Utiliser l'option --install pour ajouter automatique la ligne
dans la crontab de l'utilisateur.
A chaque lancement du script, il examine quels scripts doivent être exécutés
dans le fichier crontab spécifié. Ce fichier est composé de lignes d'une des
formes suivantes, qui sont analysées et traitées dans l'ordre:
2013-08-27 15:14:44 +04:00
# commentaire ignoré
var=\"initialiser une variable\"
minutes hours days months dows command [args]
Quelles que soient les lignes qui sont sélectionnées pour le lancement, elles
2013-09-29 16:58:08 +04:00
sont garanties de s'exécuter dans l'ordre du fichier, l'une après l'autre.
2013-08-27 15:14:44 +04:00
Certaines extensions par rapport à la syntaxe de crontab sont autorisées. Il est
en particulier possible de spécifier plusieurs planifications pour une seule
commande. Par exemple, la ligne suivante permet d'exécuter 'command' toutes les
heures ET à 1h05:
0 * * * *
5 1 * * * command
De plus, il est possible de manipuler les variables de type PATH avec une
syntaxe particulière de l'opérateur d'assignation. Les opérateurs += et %=
utilisent uaddpath(), #= utilise uinspath() et -= utilise udelpath(). Par
exemple, les lignes suivantes ajoutent respectivement /usr/local/nutools puis
enlèvent /opt/rogue au PATH:
PATH+=/usr/local/nutools
PATH-=/opt/rogue
OPTIONS
2013-09-29 16:58:08 +04:00
-A, --install
2013-08-27 15:14:44 +04:00
Installer une planification toutes les minutes de ce script dans la
2013-09-29 16:58:08 +04:00
crontab de l'utilisateur. L'argument /path/to/crontab est requis.
-R, --uninstall
2013-08-27 15:14:44 +04:00
Désinstaller la planification toutes les minutes de ce script du crontab
2013-09-29 16:58:08 +04:00
de l'utilisateur. L'argument /path/to/crontab est requis, et seule cette
instance est désinstallée le cas échéant.
-l, --list
Lister les contenus des fichiers crontab dont l'exécution a été
planifiée avec --install
Si /path/to/crontab est spécifié, ne lister le contenu de ce fichier que
si et seulement si son exécution a été planifiée.
-n, --fake
Afficher au lieu de les exécuter les commandes qui doivent être lancées
OPTIONS AVANCEES
2013-08-27 15:14:44 +04:00
--lock LOCKFILE
Inscrire dans le fichier spécifié des informations permettant d'éviter
les invocations simultanées de ce script. Si selon ce fichier, le script
tourne depuis plus de $LOCKDELAY heures, un message d'erreur est loggé
et un message d'avertissement est affiché au plus une fois.
Utiliser --lock '' pour désactiver cette fonctionnalité
Par défaut, si ce script est lancé en root, le fichier utilisé pour le
verrouillage est de la forme /var/run/$scriptname/abspath/to/crontab
Si le script est lancé avec un compte utilisateur, aucun verrouillage
n'est effectué.
--lockdelay LOCKDELAY[=$LOCKDELAY]
Changer le nombre d'heures pendant lesquelles on autorise le script a
verrouiller l'exécution avant d'afficher un avertissement.
-c, --continuous
Par défaut, ce script s'arrête à la première commande qui retourne avec
une code d'erreur. Avec cette option, ce script ne s'arrête jamais, bien
qu'il retourne toujours un code d'erreur si une erreur s'est produite.
-k, --stopec EXITCODE[=101]
Spécifier un code d'erreur spécial qui arrête ce script sans erreur, ou
'' pour désactiver cette fonctionnalité. Ceci permet en début de script
de faire des tests par exemple sur l'environnement avant de lancer les
scripts planifiés. Si l'environnement ne convient pas, il suffit au
script de contrôle de retourner le code d'erreur spécifique pour arrêter
le traitement."
}
source "$(dirname "$0")/ulib/ulib" &&
urequire DEFAULTS crontab ||
exit 1
2013-09-12 14:06:14 +04:00
MY_CTLINE="* * * * * $script"
LOCKDELAY=8
2013-08-27 15:14:44 +04:00
action=run
lockfile=auto
lockdelay=
fake=
continuous=
stopec=101
parse_opts "${PRETTYOPTS[@]}" \
--help '$exit_with display_help' \
2013-09-29 16:58:08 +04:00
-A,--add,--install action=install \
-R,--remove,--uninstall action=uninstall \
2013-08-27 15:14:44 +04:00
--lock: lockfile= \
--lockdelay: lockdelay= \
-n,--fake fake=1 \
-c,--continuous continuous=1 \
-k:,--stop: stopec=1 \
2013-09-29 16:58:08 +04:00
-l,--list action=list \
2013-08-27 15:14:44 +04:00
@ args -- "$@" && set -- "${args[@]}" || die "$args"
2013-09-29 16:58:08 +04:00
if [ "$action" == "list" ]; then
crontab="$1"; shift
[ -n "$crontab" ] && crontab="$(abspath "$crontab")"
array_from_lines ctfiles "$(crontab -l 2>/dev/null | awkrun script="$script" '$6 == script { print $7 }')"
found=
for ctfile in "${ctfiles[@]}"; do
if [ -z "$crontab" -o "$ctfile" == "$crontab" ]; then
found=1
etitle "$(ppath "$ctfile")"
cat "$ctfile"
eend
fi
done
if [ -n "$crontab" -a -z "$found" ]; then
ewarn "$(ppath "$crontab"): non planifié"
fi
exit 0
fi
2013-08-27 15:14:44 +04:00
crontab="$1"; shift
[ -n "$crontab" ] || die_with "Vous devez spécifier le fichier crontab" display_help
[ -f "$crontab" ] || die "$crontab: fichier introuvable"
crontab="$(abspath "$crontab")"
if [ "$action" == "install" ]; then
enable_in_crontab "$MY_CTLINE $(quoted_arg "$crontab")" && estep "add_to_crontab $MY_CTLINE $(quoted_arg "$crontab")"
elif [ "$action" == "uninstall" ]; then
remove_from_crontab "$MY_CTLINE $(quoted_arg "$crontab")" && estep "remove_from_crontab $MY_CTLINE $(quoted_arg "$crontab")"
elif [ "$action" == "run" ]; then
if [ "$lockfile" == auto ]; then
if is_root; then
lockfile="/var/run/$scriptname$crontab.lock"
mkdirof "$lockfile" || die
else
lockfile=
fi
fi
[ -n "$lockdelay" ] || lockdelay="$LOCKDELAY"
if [ -n "$lockfile" ]; then
lockwarn="${lockfile%.lock}.lockwarn"
retry=1
while [ -n "$retry" ]; do
case "$(lf_trylock -h "$lockdelay" "$lockfile")" in
locked)
edebug "Arrêt du script parce que le verrou $lockfile est posé"
exit 0
;;
stale)
msg="Un verrou sur '$scriptname $crontab' est posé depuis plus de $lockdelay heures. Veuillez faire vos vérification et supprimer le cas échéant le fichier $lockfile"
logger -p cron.warn -t "$scriptname" -- "$msg"
if [ -f "$lockwarn" ]; then
edebug "$msg"
else
touch "$lockwarn"
ewarn "$msg"
fi
exit 1
;;
retry) :;;
*) retry=;;
esac
done
[ -f "$lockwarn" ] && rm "$lockwarn"
autoclean "$lockfile"
fi
function __ctexec() {
local ec=0
if [ -n "$fake" ]; then
echo "$*"
else
edebug "$*"
(eval "$*"); ec=$?
fi
[ -n "$stopec" -a "$ec" == "$stopec" ] && exit 0
[ -z "$continuous" -a "$ec" != 0 ] && exit "$ec"
return 0
}
function __cterror() {
die "$*"
}
ctscript="$(ctresolve <"$crontab")"
ec=0
edebug "$ctscript"
(eval "$ctscript"); ec=$?
[ -f "$lockfile" ] && rm "$lockfile"
exit "$ec"
fi