support check_pidfile() et remove_pidfile dans uscrontab
support de l'exécution de commandes arbitraires
This commit is contained in:
parent
0afd5d3660
commit
b0f00b2f34
|
@ -1 +1 @@
|
||||||
2
|
3
|
||||||
|
|
|
@ -3743,13 +3743,14 @@ function simple_menu() {
|
||||||
|
|
||||||
# autoclean: gérer une liste de fichiers temporaires à supprimer en fin de
|
# autoclean: gérer une liste de fichiers temporaires à supprimer en fin de
|
||||||
# programme
|
# programme
|
||||||
__ac_files=()
|
function __ac_forgetall() { __ac_files=(); }
|
||||||
|
__ac_forgetall
|
||||||
function __ac_trap() {
|
function __ac_trap() {
|
||||||
local file
|
local file
|
||||||
for file in "${__ac_files[@]}"; do
|
for file in "${__ac_files[@]}"; do
|
||||||
[ -e "$file" ] && rm -rf "$file" 2>/dev/null
|
[ -e "$file" ] && rm -rf "$file" 2>/dev/null
|
||||||
done
|
done
|
||||||
__ac_files=()
|
__ac_forgetall
|
||||||
}
|
}
|
||||||
trap __ac_trap 1 3 15 EXIT
|
trap __ac_trap 1 3 15 EXIT
|
||||||
function autoclean() {
|
function autoclean() {
|
||||||
|
|
22
ulib/crontab
22
ulib/crontab
|
@ -149,12 +149,12 @@ BEGIN {
|
||||||
matches = 0
|
matches = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
/^[a-zA-Z_][a-zA-Z0-9_]*[-+%#]=/ {
|
/^(export[ \t]+)?[a-zA-Z_][a-zA-Z0-9_]*[-+%#]=/ {
|
||||||
# manipulation de variables PATH
|
# manipulation de variables PATH
|
||||||
match($0, /^([a-zA-Z_][a-zA-Z0-9_]*)([-+%#])=(.*)$/, parts)
|
match($0, /^(export[ \t]+)?([a-zA-Z_][a-zA-Z0-9_]*)([-+%#])=(.*)$/, parts)
|
||||||
name = parts[1]
|
name = parts[2]
|
||||||
type = parts[2]
|
type = parts[3]
|
||||||
value = parts[3]
|
value = parts[4]
|
||||||
if (type == "+" || type == "%") {
|
if (type == "+" || type == "%") {
|
||||||
print "uaddpath " value " " name
|
print "uaddpath " value " " name
|
||||||
} else if (type == "#") {
|
} else if (type == "#") {
|
||||||
|
@ -162,14 +162,22 @@ BEGIN {
|
||||||
} else if (type == "-") {
|
} else if (type == "-") {
|
||||||
print "udelpath " value " " name
|
print "udelpath " value " " name
|
||||||
}
|
}
|
||||||
|
print "export " name
|
||||||
next
|
next
|
||||||
}
|
}
|
||||||
/^[a-zA-Z_][a-zA-Z0-9_]*=/ {
|
/^(export[ \t]+)?[a-zA-Z_][a-zA-Z0-9_]*=/ {
|
||||||
# spécification de variable
|
# spécification de variable
|
||||||
|
sub(/^export[ \t]+/, "", $0)
|
||||||
print "export " $0
|
print "export " $0
|
||||||
next
|
next
|
||||||
}
|
}
|
||||||
/^[ ]*[-0-9/*,]+[ ]*[-0-9/*,]+[ ]*[-0-9/*,]+[ ]*[-0-9/*,]+[ ]*[-0-9/*,]+/ {
|
/^\$.+/ {
|
||||||
|
# exécution de commande arbitraire
|
||||||
|
sub(/^\$/, "", $0)
|
||||||
|
print
|
||||||
|
next
|
||||||
|
}
|
||||||
|
/^[ \t]*[-0-9/*,]+[ ]*[-0-9/*,]+[ ]*[-0-9/*,]+[ ]*[-0-9/*,]+[ ]*[-0-9/*,]+/ {
|
||||||
# ligne de planification
|
# ligne de planification
|
||||||
M = $1; H = $2; dom = $3; mon = $4; dow = $5
|
M = $1; H = $2; dom = $3; mon = $4; dow = $5
|
||||||
sub(/^[ ]*[^ ]+[ ]+[^ ]+[ ]+[^ ]+[ ]+[^ ]+[ ]+[^ ]+[ ]*/, "", $0)
|
sub(/^[ ]*[^ ]+[ ]+[^ ]+[ ]+[^ ]+[ ]+[^ ]+[ ]+[^ ]+[ ]*/, "", $0)
|
||||||
|
|
185
uscrontab
185
uscrontab
|
@ -13,33 +13,118 @@ une tâche cron. Utiliser l'option --install pour ajouter automatique la ligne
|
||||||
dans la crontab de l'utilisateur.
|
dans la crontab de l'utilisateur.
|
||||||
|
|
||||||
A chaque lancement du script, il examine quels scripts doivent être exécutés
|
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
|
dans le fichier crontab spécifié. Ce fichier est composé de lignes dans un
|
||||||
formes suivantes, qui sont analysées et traitées dans l'ordre:
|
format particulier, qui sont analysées et traitées dans l'ordre.
|
||||||
|
|
||||||
# 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
|
Quelles que soient les lignes qui sont sélectionnées pour le lancement, elles
|
||||||
sont garanties de s'exécuter dans l'ordre du fichier, l'une après l'autre.
|
sont garanties de s'exécuter dans l'ordre du fichier, l'une après l'autre.
|
||||||
|
|
||||||
Certaines extensions par rapport à la syntaxe de crontab sont autorisées. Il est
|
Les lignes commençant par # sont des commentaires et sont ignorées
|
||||||
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 * * * *
|
== Définitions de variables et exécution de commandes ==
|
||||||
5 1 * * * command
|
|
||||||
|
|
||||||
De plus, il est possible de manipuler les variables de type PATH avec une
|
Les lignes de la forme suivante sont des définitions de variable:
|
||||||
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
|
[export] var=\"valeur de la variable\"
|
||||||
PATH-=/opt/rogue
|
|
||||||
|
|
||||||
|
Ces lignes sont des définitions de variable bash qui sont exécutées telles
|
||||||
|
quelles. Il n'est donc pas autorisé de mettre des espaces autour de =. Par
|
||||||
|
exemple, les lignes suivantes sont des erreurs de syntaxe:
|
||||||
|
|
||||||
|
var = bad
|
||||||
|
var=pas de quotes autour de la valeur
|
||||||
|
|
||||||
|
alors que celles-ci sont correctes:
|
||||||
|
|
||||||
|
var=ok
|
||||||
|
var=\"valeur avec des espaces\"
|
||||||
|
var='on peut utiliser des quotes aussi'
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
Bien sûr, il ne faut pas oublier de quoter les espaces:
|
||||||
|
|
||||||
|
PATH+=\"/path/to/dir with spaces\"
|
||||||
|
|
||||||
|
Les lignes de la forme suivante permettent d'exécuter une commande
|
||||||
|
quelconque:
|
||||||
|
|
||||||
|
$command-line
|
||||||
|
|
||||||
|
Ces commandes sont exécutées systématiquement et ignorent la planification.
|
||||||
|
On peut s'en servir notamment pour lire un fichier de configuration qui
|
||||||
|
définit des variables ou des fonctions:
|
||||||
|
|
||||||
|
$source path/to/file
|
||||||
|
|
||||||
|
== Planification de commandes ==
|
||||||
|
|
||||||
|
Les autres lignes doivent être au format d'une ligne de crontab:
|
||||||
|
|
||||||
|
minutes hours days months dows command-line
|
||||||
|
|
||||||
|
command-line peut être n'importe quelle ligne de commande bash, pourvu
|
||||||
|
qu'elle soit sur une seule ligne.
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
== Fonctions disponibles ==
|
||||||
|
|
||||||
|
La fonction check_pidfile() est disponible, et permet de vérifier qu'une
|
||||||
|
opération n'est pas déjà en cours. Si cette fonction est utilisée, il ne
|
||||||
|
faut pas modifier la valeur de -k. Par exemple:
|
||||||
|
|
||||||
|
0 1 * * * check_pidfile /path/to/pid [args]
|
||||||
|
0 1 * * * long-running-script
|
||||||
|
|
||||||
|
check_pidfile() doit être utilisée toute seule sur la ligne et s'utilise
|
||||||
|
avec les argument suivants:
|
||||||
|
|
||||||
|
check_pidfile PIDFILE [DESC] [BARRIER]
|
||||||
|
|
||||||
|
- PIDFILE est le fichier de PID qui est vérifié
|
||||||
|
- DESC est la description du traitement qui est effectué. La valeur par
|
||||||
|
défaut est \"Une synchronisation\". Si le fichier de PID est présent, le
|
||||||
|
message suivant est affiché:
|
||||||
|
DESC est en cours.
|
||||||
|
Si vous pensez que c'est une erreur, veuillez vérifier le process de pid PID
|
||||||
|
puis supprimez le cas échéant le fichier PIDFILE
|
||||||
|
- BARRIER est un fichier qui est créé avec le contenu 'PID' s'il n'existe
|
||||||
|
pas encore, et si la vérification du fichier de PID est faite avec succès.
|
||||||
|
La présence de ce fichier peut-être vérifiée pour empêcher par exemple la
|
||||||
|
mise à jour du code de synchronisation. Son contenu peut être examiné pour
|
||||||
|
connaître le PID du processus qui l'a créé initialement. Le fichier est
|
||||||
|
automatiquement supprimé à la fin de ce script.
|
||||||
|
Attention: ce fichier n'est pas un verrou, il peut être supprimé à tout
|
||||||
|
moment. Notamment, si deux scripts sont configurés pour créer le même
|
||||||
|
fichier barrière, le premier script supprimera le fichier barrière avant
|
||||||
|
la fin de l'exécution du second script.
|
||||||
|
|
||||||
|
La fonction remove_pidfile() permet de supprimer un fichier de pid pour
|
||||||
|
spécifier qu'une opération est terminée. Considérons l'exemple suivant:
|
||||||
|
|
||||||
|
0 1 * * * check_pidfile /path/to/pid
|
||||||
|
0 1 * * * script1
|
||||||
|
0 1 * * * script2
|
||||||
|
0 1 * * * remove_pidfile /path/to/pid
|
||||||
|
0 1 * * * script3
|
||||||
|
|
||||||
|
Dans cet exemple, il ne faut pas qu'une autre occurence de script1 tourne
|
||||||
|
pendant que script2 tourne. Par contre, plusieurs occurences de script3
|
||||||
|
peuvent tourner en parallèle.
|
||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
-A, --install
|
-A, --install
|
||||||
|
@ -61,14 +146,14 @@ OPTIONS AVANCEES
|
||||||
--lock LOCKFILE
|
--lock LOCKFILE
|
||||||
Inscrire dans le fichier spécifié des informations permettant d'éviter
|
Inscrire dans le fichier spécifié des informations permettant d'éviter
|
||||||
les invocations simultanées de ce script. Si selon ce fichier, le script
|
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é
|
tourne depuis plus de $USCRONTAB_LOCKDELAY heures, un message d'erreur est loggé
|
||||||
et un message d'avertissement est affiché au plus une fois.
|
et un message d'avertissement est affiché au plus une fois.
|
||||||
Utiliser --lock '' pour désactiver cette fonctionnalité
|
Utiliser --lock '' pour désactiver cette fonctionnalité
|
||||||
Par défaut, si ce script est lancé en root, le fichier utilisé pour le
|
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
|
verrouillage est de la forme /var/run/$scriptname/abspath/to/crontab
|
||||||
Si le script est lancé avec un compte utilisateur, aucun verrouillage
|
Si le script est lancé avec un compte utilisateur, aucun verrouillage
|
||||||
n'est effectué.
|
n'est effectué.
|
||||||
--lockdelay LOCKDELAY[=$LOCKDELAY]
|
--lockdelay LOCKDELAY[=$USCRONTAB_LOCKDELAY]
|
||||||
Changer le nombre d'heures pendant lesquelles on autorise le script a
|
Changer le nombre d'heures pendant lesquelles on autorise le script a
|
||||||
verrouiller l'exécution avant d'afficher un avertissement.
|
verrouiller l'exécution avant d'afficher un avertissement.
|
||||||
-c, --continuous
|
-c, --continuous
|
||||||
|
@ -88,15 +173,15 @@ source "$(dirname "$0")/ulib/ulib" &&
|
||||||
urequire DEFAULTS crontab ||
|
urequire DEFAULTS crontab ||
|
||||||
exit 1
|
exit 1
|
||||||
|
|
||||||
MY_CTLINE="* * * * * $script"
|
USCRONTAB_CTLINE="* * * * * $script"
|
||||||
LOCKDELAY=8
|
USCRONTAB_LOCKDELAY=8
|
||||||
|
USCRONTAB_STOPEC=101
|
||||||
|
|
||||||
action=run
|
action=run
|
||||||
lockfile=auto
|
lockfile=auto
|
||||||
lockdelay=
|
lockdelay=
|
||||||
fake=
|
fake=
|
||||||
continuous=
|
continuous=
|
||||||
stopec=101
|
|
||||||
parse_opts "${PRETTYOPTS[@]}" \
|
parse_opts "${PRETTYOPTS[@]}" \
|
||||||
--help '$exit_with display_help' \
|
--help '$exit_with display_help' \
|
||||||
-A,--add,--install action=install \
|
-A,--add,--install action=install \
|
||||||
|
@ -105,7 +190,7 @@ parse_opts "${PRETTYOPTS[@]}" \
|
||||||
--lockdelay: lockdelay= \
|
--lockdelay: lockdelay= \
|
||||||
-n,--fake fake=1 \
|
-n,--fake fake=1 \
|
||||||
-c,--continuous continuous=1 \
|
-c,--continuous continuous=1 \
|
||||||
-k:,--stop: stopec=1 \
|
-k:,--stop: USCRONTAB_STOPEC= \
|
||||||
-l,--list action=list \
|
-l,--list action=list \
|
||||||
@ args -- "$@" && set -- "${args[@]}" || die "$args"
|
@ args -- "$@" && set -- "${args[@]}" || die "$args"
|
||||||
|
|
||||||
|
@ -135,10 +220,10 @@ crontab="$1"; shift
|
||||||
crontab="$(abspath "$crontab")"
|
crontab="$(abspath "$crontab")"
|
||||||
|
|
||||||
if [ "$action" == "install" ]; then
|
if [ "$action" == "install" ]; then
|
||||||
enable_in_crontab "$MY_CTLINE $(quoted_arg "$crontab")" && estep "add_to_crontab $MY_CTLINE $(quoted_arg "$crontab")"
|
enable_in_crontab "$USCRONTAB_CTLINE $(quoted_arg "$crontab")" && estep "add_to_crontab $USCRONTAB_CTLINE $(quoted_arg "$crontab")"
|
||||||
|
|
||||||
elif [ "$action" == "uninstall" ]; then
|
elif [ "$action" == "uninstall" ]; then
|
||||||
remove_from_crontab "$MY_CTLINE $(quoted_arg "$crontab")" && estep "remove_from_crontab $MY_CTLINE $(quoted_arg "$crontab")"
|
remove_from_crontab "$USCRONTAB_CTLINE $(quoted_arg "$crontab")" && estep "remove_from_crontab $USCRONTAB_CTLINE $(quoted_arg "$crontab")"
|
||||||
|
|
||||||
elif [ "$action" == "run" ]; then
|
elif [ "$action" == "run" ]; then
|
||||||
if [ "$lockfile" == auto ]; then
|
if [ "$lockfile" == auto ]; then
|
||||||
|
@ -149,7 +234,7 @@ elif [ "$action" == "run" ]; then
|
||||||
lockfile=
|
lockfile=
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
[ -n "$lockdelay" ] || lockdelay="$LOCKDELAY"
|
[ -n "$lockdelay" ] || lockdelay="$USCRONTAB_LOCKDELAY"
|
||||||
|
|
||||||
if [ -n "$lockfile" ]; then
|
if [ -n "$lockfile" ]; then
|
||||||
lockwarn="${lockfile%.lock}.lockwarn"
|
lockwarn="${lockfile%.lock}.lockwarn"
|
||||||
|
@ -185,9 +270,15 @@ elif [ "$action" == "run" ]; then
|
||||||
echo "$*"
|
echo "$*"
|
||||||
else
|
else
|
||||||
edebug "$*"
|
edebug "$*"
|
||||||
(eval "$*"); ec=$?
|
if [ "${1#check_pidfile }" != "$1" ]; then
|
||||||
|
# cas particulier, c'est une fonction à exécuter dans le
|
||||||
|
# contexte courant, et non pas dans un sous-shell
|
||||||
|
eval "$*"; ec=$?
|
||||||
|
else
|
||||||
|
(eval "$*"); ec=$?
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
[ -n "$stopec" -a "$ec" == "$stopec" ] && exit 0
|
[ -n "$USCRONTAB_STOPEC" -a "$ec" == "$USCRONTAB_STOPEC" ] && exit 0
|
||||||
[ -z "$continuous" -a "$ec" != 0 ] && exit "$ec"
|
[ -z "$continuous" -a "$ec" != 0 ] && exit "$ec"
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
@ -197,7 +288,39 @@ elif [ "$action" == "run" ]; then
|
||||||
ctscript="$(ctresolve <"$crontab")"
|
ctscript="$(ctresolve <"$crontab")"
|
||||||
ec=0
|
ec=0
|
||||||
edebug "$ctscript"
|
edebug "$ctscript"
|
||||||
(eval "$ctscript"); ec=$?
|
(
|
||||||
|
function check_pidfile() {
|
||||||
|
if [ -n "$1" ]; then
|
||||||
|
local status
|
||||||
|
pidfile_set -r "$1"; status=$?
|
||||||
|
case "$status" in
|
||||||
|
1)
|
||||||
|
eerror "${2:-Une synchronisation} est en cours.
|
||||||
|
Si vous pensez que c'est une erreur, veuillez vérifier le process de pid $(<"$1")
|
||||||
|
puis supprimez le cas échéant le fichier $1"
|
||||||
|
return "$USCRONTAB_STOPEC"
|
||||||
|
;;
|
||||||
|
10)
|
||||||
|
die "Une erreur s'est produite pendant l'écriture du fichier de pid. Impossible de continuer"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
if [ -n "$3" -a -w "$(dirname "$3")" ]; then
|
||||||
|
(set -o noclobber
|
||||||
|
echo_ $$ >"$3" &&
|
||||||
|
chmod 755 "$3"
|
||||||
|
) 2>/dev/null &&
|
||||||
|
autoclean "$3"
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
function remove_pidfile() {
|
||||||
|
[ -n "$1" ] && ac_clean "$1"
|
||||||
|
}
|
||||||
|
__ac_forgetall
|
||||||
|
eval "$ctscript"
|
||||||
|
ac_cleanall
|
||||||
|
); ec=$?
|
||||||
[ -f "$lockfile" ] && rm "$lockfile"
|
[ -f "$lockfile" ] && rm "$lockfile"
|
||||||
exit "$ec"
|
exit "$ec"
|
||||||
fi
|
fi
|
||||||
|
|
Loading…
Reference in New Issue