Merge branch 'uscrontab'
This commit is contained in:
commit
39d3c37912
|
@ -71,3 +71,13 @@ etitle "Installation de /etc/init.d/kvm-stop-all" \
|
||||||
[ -n "$openvz_service" ] &&
|
[ -n "$openvz_service" ] &&
|
||||||
etitle "Installation de /etc/init.d/openvz-fix-etchosts" \
|
etitle "Installation de /etc/init.d/openvz-fix-etchosts" \
|
||||||
"$scriptdir/../init.d/install-openvz-fix-etchosts"
|
"$scriptdir/../init.d/install-openvz-fix-etchosts"
|
||||||
|
|
||||||
|
etitle "Installation des répertoires pour uscrontab"
|
||||||
|
if mkdir -p /var/uscrontab/crontabs; then
|
||||||
|
chmod 1733 /var/uscrontab/crontabs
|
||||||
|
else
|
||||||
|
eerror "Impossible de créer le répertoire /var/uscrontab/crontabs"
|
||||||
|
fi
|
||||||
|
eend
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
34
|
35
|
||||||
|
|
18
ulib/base
18
ulib/base
|
@ -38,9 +38,9 @@ function recho() {
|
||||||
if [[ "${1:0:2}" == -[eEn] ]]; then
|
if [[ "${1:0:2}" == -[eEn] ]]; then
|
||||||
echo -n -
|
echo -n -
|
||||||
local first="${1:1}"; shift
|
local first="${1:1}"; shift
|
||||||
echo "$first" "$@"
|
echo "$first$@"
|
||||||
else
|
else
|
||||||
echo "$*"
|
echo "$@"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
function recho_() {
|
function recho_() {
|
||||||
|
@ -49,9 +49,9 @@ function recho_() {
|
||||||
if [[ "${1:0:2}" == -[eEn] ]]; then
|
if [[ "${1:0:2}" == -[eEn] ]]; then
|
||||||
echo -n -
|
echo -n -
|
||||||
local first="${1:1}"; shift
|
local first="${1:1}"; shift
|
||||||
echo -n "$first" "$@"
|
echo -n "$first$@"
|
||||||
else
|
else
|
||||||
echo -n "$*"
|
echo -n "$@"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
function qval() {
|
function qval() {
|
||||||
|
@ -88,7 +88,7 @@ function qvals() {
|
||||||
[ -z "$first" ] && echo -n " "
|
[ -z "$first" ] && echo -n " "
|
||||||
if should_quote "$arg"; then
|
if should_quote "$arg"; then
|
||||||
echo -n \"
|
echo -n \"
|
||||||
qv "$arg"
|
qval "$arg"
|
||||||
echo -n \"
|
echo -n \"
|
||||||
else
|
else
|
||||||
recho_ "$arg"
|
recho_ "$arg"
|
||||||
|
@ -733,7 +733,7 @@ function array_extend_lasts() {
|
||||||
function array_xsplit() {
|
function array_xsplit() {
|
||||||
# créer le tableau $1 avec chaque élément de $2 (un ensemble d'éléments séparés
|
# créer le tableau $1 avec chaque élément de $2 (un ensemble d'éléments séparés
|
||||||
# par $3, qui vaut ':' par défaut).
|
# par $3, qui vaut ':' par défaut).
|
||||||
eval "$1=($(<<<"$2" stripnl | awkrun RS="${3:-:}" '
|
eval "$1=($(recho_ "$2" | awkrun RS="${3:-:}" '
|
||||||
{
|
{
|
||||||
gsub(/'\''/, "'\'\\\\\'\''")
|
gsub(/'\''/, "'\'\\\\\'\''")
|
||||||
print "'\''" $0 "'\''"
|
print "'\''" $0 "'\''"
|
||||||
|
@ -743,7 +743,7 @@ function array_split() {
|
||||||
# créer le tableau $1 avec chaque élément de $2 (un ensemble d'éléments séparés
|
# créer le tableau $1 avec chaque élément de $2 (un ensemble d'éléments séparés
|
||||||
# par $3, qui vaut ':' par défaut). Les éléments vides sont ignorés. par exemple
|
# par $3, qui vaut ':' par défaut). Les éléments vides sont ignorés. par exemple
|
||||||
# "a::b" est équivalent à "a:b"
|
# "a::b" est équivalent à "a:b"
|
||||||
eval "$1=($(<<<"$2" stripnl | awkrun RS="${3:-:}" '
|
eval "$1=($(recho_ "$2" | awkrun RS="${3:-:}" '
|
||||||
/^$/ { next }
|
/^$/ { next }
|
||||||
{
|
{
|
||||||
gsub(/'\''/, "'\'\\\\\'\''")
|
gsub(/'\''/, "'\'\\\\\'\''")
|
||||||
|
@ -755,7 +755,7 @@ function array_from_path() {
|
||||||
}
|
}
|
||||||
function array_from_xlines() {
|
function array_from_xlines() {
|
||||||
# créer le tableau $1 avec chaque ligne de $2.
|
# créer le tableau $1 avec chaque ligne de $2.
|
||||||
eval "$1=($(<<<"$2" _nl2lf | awk '
|
eval "$1=($(recho_ "$2" | _nl2lf | awk '
|
||||||
{
|
{
|
||||||
gsub(/'\''/, "'\'\\\\\'\''")
|
gsub(/'\''/, "'\'\\\\\'\''")
|
||||||
print "'\''" $0 "'\''"
|
print "'\''" $0 "'\''"
|
||||||
|
@ -763,7 +763,7 @@ function array_from_xlines() {
|
||||||
}
|
}
|
||||||
function array_from_lines() {
|
function array_from_lines() {
|
||||||
# créer le tableau $1 avec chaque ligne de $2. Les lignes vides sont ignorés.
|
# créer le tableau $1 avec chaque ligne de $2. Les lignes vides sont ignorés.
|
||||||
eval "$1=($(<<<"$2" _nl2lf | awk '
|
eval "$1=($(recho_ "$2" | _nl2lf | awk '
|
||||||
/^$/ { next }
|
/^$/ { next }
|
||||||
{
|
{
|
||||||
gsub(/'\''/, "'\'\\\\\'\''")
|
gsub(/'\''/, "'\'\\\\\'\''")
|
||||||
|
|
202
uscrontab
202
uscrontab
|
@ -6,13 +6,22 @@ function display_help() {
|
||||||
uecho "$scriptname: lancer une suite de commande en respectant une planification de type cron
|
uecho "$scriptname: lancer une suite de commande en respectant une planification de type cron
|
||||||
|
|
||||||
USAGE
|
USAGE
|
||||||
$scriptname [options] /path/to/crontab
|
$scriptname [options] [/path/to/crontab]
|
||||||
$scriptname -l [/path/to/crontab]
|
$scriptname -e [/path/to/crontab]
|
||||||
|
$scriptname -l
|
||||||
|
|
||||||
La première forme du script doit normalement être lancé toutes les minutes par
|
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
|
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.
|
||||||
|
|
||||||
|
Si aucun fichier n'est spécifié, fusionner s'il existe le fichier
|
||||||
|
$USCRONTAB_USERFILE
|
||||||
|
avec chacun des fichiers du répertoire
|
||||||
|
$USCRONTAB_USERDIR
|
||||||
|
puis exécuter le fichier résultat avec le nom virtuel
|
||||||
|
$USCRONTAB_USER
|
||||||
|
note: le nom virtuel est utilisé pour le verrouillage avec --lock
|
||||||
|
|
||||||
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 dans un
|
dans le fichier crontab spécifié. Ce fichier est composé de lignes dans un
|
||||||
format particulier, qui sont analysées et traitées dans l'ordre.
|
format particulier, qui sont analysées et traitées dans l'ordre.
|
||||||
|
@ -157,17 +166,29 @@ Les lignes commençant par # sont des commentaires et sont ignorées
|
||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
-A, --install
|
-A, --install
|
||||||
Installer une planification toutes les minutes de ce script dans la
|
Installer une planification toutes les minutes du script dans la crontab
|
||||||
crontab de l'utilisateur. L'argument /path/to/crontab est requis.
|
de l'utilisateur. Si l'argument /path/to/crontab n'est pas spécifié,
|
||||||
|
c'est une planification générique qui exécute les fichiers par défaut.
|
||||||
-R, --uninstall
|
-R, --uninstall
|
||||||
Désinstaller la planification toutes les minutes de ce script du crontab
|
Désinstaller la planification toutes les minutes du script du crontab de
|
||||||
de l'utilisateur. L'argument /path/to/crontab est requis, et seule cette
|
l'utilisateur. Si l'argument /path/to/crontab est spécifié, cette
|
||||||
instance est désinstallée le cas échéant.
|
instance est désinstallée. Sinon, ne désinstaller que la planification
|
||||||
|
générique.
|
||||||
|
-e, --edit
|
||||||
|
Lancer un editeur pour modifier la crontab spécifiée. Si aucun fichier
|
||||||
|
n'est spécifié, éditer $USCRONTAB_USERFILE
|
||||||
|
-r, --remove
|
||||||
|
Supprimer le fichier $USCRONTAB_USERFILE s'il existe
|
||||||
|
Si l'argument /path/to/crontab est spécifié, il est ignoré.
|
||||||
-l, --list
|
-l, --list
|
||||||
Lister les contenus des fichiers crontab dont l'exécution a été
|
Si l'argument /path/to/crontab est spécifié, afficher le contenu de ce
|
||||||
planifiée avec --install
|
fichier. Sinon, lister les contenus des fichiers crontab qui sont
|
||||||
Si /path/to/crontab est spécifié, ne lister le contenu de ce fichier que
|
exécutés avec la planification actuelle. Si une planification générique
|
||||||
si son exécution a été planifiée.
|
est installée, ou si aucune planification n'est en cours, afficher le
|
||||||
|
contenu du fichier
|
||||||
|
$USCRONTAB_USERFILE
|
||||||
|
et chacun des fichiers du répertoire
|
||||||
|
$USCRONTAB_USERDIR
|
||||||
-n, --fake
|
-n, --fake
|
||||||
Afficher au lieu de les exécuter les commandes qui doivent être lancées
|
Afficher au lieu de les exécuter les commandes qui doivent être lancées
|
||||||
|
|
||||||
|
@ -198,9 +219,23 @@ OPTIONS AVANCEES
|
||||||
le traitement."
|
le traitement."
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function set_usercrontabs() {
|
||||||
|
# initialiser le tableau $1(=usercrontabs) avec la liste suivante: le
|
||||||
|
# fichier $USCRONTAB_USERFILE s'il existe, puis la liste des fichiers dans
|
||||||
|
# le répertoire $USCRONTAB_USERDIR
|
||||||
|
local -a _userfile _userdir
|
||||||
|
[ -f "$USCRONTAB_USERFILE" ] && _userfile=("$USCRONTAB_USERFILE")
|
||||||
|
array_lsfiles _userdir "$USCRONTAB_USERDIR"
|
||||||
|
eval "${1:-usercrontabs}"'=("${_userfile[@]}" "${_userdir[@]}")'
|
||||||
|
}
|
||||||
|
|
||||||
USCRONTAB_CTLINE="* * * * * $script"
|
USCRONTAB_CTLINE="* * * * * $script"
|
||||||
USCRONTAB_LOCKDELAY=8
|
USCRONTAB_LOCKDELAY=8
|
||||||
USCRONTAB_STOPEC=101
|
USCRONTAB_STOPEC=101
|
||||||
|
USCRONTAB_BASEDIR=/var/uscrontab
|
||||||
|
USCRONTAB_USERFILE="$USCRONTAB_BASEDIR/crontabs/$USER"
|
||||||
|
USCRONTAB_USERDIR="$USCRONTAB_BASEDIR/$USER.d"
|
||||||
|
USCRONTAB_USER="$USCRONTAB_BASEDIR/$USER"
|
||||||
|
|
||||||
action=run
|
action=run
|
||||||
lockfile=auto
|
lockfile=auto
|
||||||
|
@ -217,43 +252,97 @@ parse_opts "${PRETTYOPTS[@]}" \
|
||||||
-c,--continuous continuous=1 \
|
-c,--continuous continuous=1 \
|
||||||
-k:,--stop: USCRONTAB_STOPEC= \
|
-k:,--stop: USCRONTAB_STOPEC= \
|
||||||
-l,--list action=list \
|
-l,--list action=list \
|
||||||
|
-e,--edit action=edit \
|
||||||
|
-r,--remove action=remove \
|
||||||
@ args -- "$@" && set -- "${args[@]}" || die "$args"
|
@ args -- "$@" && set -- "${args[@]}" || die "$args"
|
||||||
|
|
||||||
if [ "$action" == "list" ]; then
|
crontab="$1"; shift
|
||||||
crontab="$1"; shift
|
|
||||||
[ -n "$crontab" ] && crontab="$(abspath "$crontab")"
|
|
||||||
|
|
||||||
array_from_lines ctfiles "$(crontab -l 2>/dev/null | awkrun script="$script" '$6 == script { print $7 }')"
|
if [ "$action" == "edit" ]; then
|
||||||
found=
|
if [ -z "$crontab" ]; then
|
||||||
for ctfile in "${ctfiles[@]}"; do
|
basedir="$(dirname "$USCRONTAB_USERFILE")"
|
||||||
if [ -z "$crontab" -o "$ctfile" == "$crontab" ]; then
|
[ -d "$basedir" ] || die "$basedir: ce répertoire n'existe pas. Vérifiez l'installation de nutools"
|
||||||
found=1
|
crontab="$USCRONTAB_USERFILE"
|
||||||
etitle "$(ppath "$ctfile")"
|
fi
|
||||||
cat "$ctfile"
|
enote "Edition de $crontab"
|
||||||
eend
|
if [ ! -f "$crontab" ]; then
|
||||||
fi
|
touch "$crontab"
|
||||||
done
|
chmod 640 "$crontab"
|
||||||
if [ -n "$crontab" -a -z "$found" ]; then
|
fi
|
||||||
ewarn "$(ppath "$crontab"): non planifié"
|
"${EDITOR:-vi}" "$crontab"
|
||||||
|
exit 0
|
||||||
|
|
||||||
|
elif [ "$action" == "remove" ]; then
|
||||||
|
[ -n "$crontab" ] && ewarn "$crontab: cet argument a été ignoré"
|
||||||
|
crontab="$USCRONTAB_USERFILE"
|
||||||
|
if [ -f "$crontab" ]; then
|
||||||
|
ask_yesno "Voulez-vous supprimer le fichier $crontab?" C || die
|
||||||
|
enote "Suppression de $crontab"
|
||||||
|
rm "$crontab" || die
|
||||||
fi
|
fi
|
||||||
exit 0
|
exit 0
|
||||||
|
|
||||||
|
elif [ "$action" == "list" ]; then
|
||||||
|
if [ -n "$crontab" ]; then
|
||||||
|
crontab="$(abspath "$crontab")"
|
||||||
|
array_from_lines ctfiles "$(crontab -l 2>/dev/null | awkrun script="$script" crontab="$crontab" '$6 == script && $7 == crontab { print $7 }')"
|
||||||
|
if [ ${#ctfiles[*]} -eq 0 ]; then
|
||||||
|
ewarn "$(ppath "$crontab"): non planifié"
|
||||||
|
ctfiles=("$crontab")
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
array_from_lines ctfiles "$(crontab -l 2>/dev/null | awkrun script="$script" '$6 == script { if ($7) print $7; else print "GENERIC" }')"
|
||||||
|
if array_contains ctfiles "GENERIC"; then
|
||||||
|
# il y a une planification générique
|
||||||
|
array_del ctfiles "GENERIC"
|
||||||
|
set_usercrontabs usercrontabs
|
||||||
|
array_extend ctfiles usercrontabs
|
||||||
|
elif [ ${#ctfiles[*]} -eq 0 ]; then
|
||||||
|
einfo "aucune planification en cours"
|
||||||
|
set_usercrontabs ctfiles
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
r=1
|
||||||
|
for ctfile in "${ctfiles[@]}"; do
|
||||||
|
r=0 # il y a au moins une planification
|
||||||
|
etitle "$(ppath "$ctfile")" \
|
||||||
|
cat "$ctfile"
|
||||||
|
done
|
||||||
|
exit $r
|
||||||
fi
|
fi
|
||||||
|
|
||||||
crontab="$1"; shift
|
[ -z "$crontab" -o -f "$crontab" ] || die "$crontab: fichier introuvable"
|
||||||
[ -n "$crontab" ] || die_with "Vous devez spécifier le fichier crontab" display_help
|
[ -n "$crontab" ] && crontab="$(abspath "$crontab")"
|
||||||
[ -f "$crontab" ] || die "$crontab: fichier introuvable"
|
|
||||||
crontab="$(abspath "$crontab")"
|
|
||||||
|
|
||||||
if [ "$action" == "install" ]; then
|
if [ "$action" == "install" ]; then
|
||||||
enable_in_crontab "$USCRONTAB_CTLINE $(quoted_arg "$crontab")" && estep "add_to_crontab $USCRONTAB_CTLINE $(quoted_arg "$crontab")"
|
ctline="$USCRONTAB_CTLINE"
|
||||||
|
[ -n "$crontab" ] && ctline="$ctline $(quoted_arg "$crontab")"
|
||||||
|
enable_in_crontab "$ctline" && estep "add_to_crontab $ctline"
|
||||||
|
|
||||||
elif [ "$action" == "uninstall" ]; then
|
elif [ "$action" == "uninstall" ]; then
|
||||||
remove_from_crontab "$USCRONTAB_CTLINE $(quoted_arg "$crontab")" && estep "remove_from_crontab $USCRONTAB_CTLINE $(quoted_arg "$crontab")"
|
ctline="$USCRONTAB_CTLINE"
|
||||||
|
[ -n "$crontab" ] && ctline="$ctline $(quoted_arg "$crontab")"
|
||||||
|
remove_from_crontab "$ctline" && estep "remove_from_crontab $ctline"
|
||||||
|
|
||||||
elif [ "$action" == "run" ]; then
|
elif [ "$action" == "run" ]; then
|
||||||
|
clean_crontab=
|
||||||
|
if [ -n "$crontab" ]; then
|
||||||
|
default_lockfile="/var/run/$scriptname$crontab.lock"
|
||||||
|
else
|
||||||
|
set_usercrontabs usercrontabs
|
||||||
|
ac_set_tmpfile crontab
|
||||||
|
clean_crontab=1
|
||||||
|
for usercrontab in "${usercrontabs[@]}"; do
|
||||||
|
echo "# $usercrontab" >>"$crontab"
|
||||||
|
cat "$usercrontab" >>"$crontab"
|
||||||
|
done
|
||||||
|
default_lockfile="/var/run/$scriptname$USCRONTAB_USER.lock"
|
||||||
|
fi
|
||||||
|
|
||||||
if [ "$lockfile" == auto ]; then
|
if [ "$lockfile" == auto ]; then
|
||||||
if is_root; then
|
if is_root; then
|
||||||
lockfile="/var/run/$scriptname$crontab.lock"
|
lockfile="$default_lockfile"
|
||||||
mkdirof "$lockfile" || die
|
mkdirof "$lockfile" || die
|
||||||
else
|
else
|
||||||
lockfile=
|
lockfile=
|
||||||
|
@ -263,6 +352,8 @@ elif [ "$action" == "run" ]; then
|
||||||
|
|
||||||
if [ -n "$lockfile" ]; then
|
if [ -n "$lockfile" ]; then
|
||||||
lockwarn="${lockfile%.lock}.lockwarn"
|
lockwarn="${lockfile%.lock}.lockwarn"
|
||||||
|
autoclean "$lockwarn"
|
||||||
|
|
||||||
retry=1
|
retry=1
|
||||||
while [ -n "$retry" ]; do
|
while [ -n "$retry" ]; do
|
||||||
case "$(lf_trylock -h "$lockdelay" "$lockfile")" in
|
case "$(lf_trylock -h "$lockdelay" "$lockfile")" in
|
||||||
|
@ -285,7 +376,8 @@ elif [ "$action" == "run" ]; then
|
||||||
*) retry=;;
|
*) retry=;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
[ -f "$lockwarn" ] && rm "$lockwarn"
|
|
||||||
|
ac_clean "$lockwarn"
|
||||||
autoclean "$lockfile"
|
autoclean "$lockfile"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -314,21 +406,29 @@ elif [ "$action" == "run" ]; then
|
||||||
ec=0
|
ec=0
|
||||||
edebug "$ctscript"
|
edebug "$ctscript"
|
||||||
(
|
(
|
||||||
|
# tableau des fichiers de pid en cours. la conséquence est que ce n'est
|
||||||
|
# pas une erreur d'appeler à plusieurs reprises check_pidfile avec le
|
||||||
|
# même fichier
|
||||||
|
__USCRONTAB_PIDFILES=()
|
||||||
function check_pidfile() {
|
function check_pidfile() {
|
||||||
if [ -n "$1" ]; then
|
if [ -n "$1" ]; then
|
||||||
local status
|
local pidfile="$(abspath "$1")"
|
||||||
pidfile_set -r "$1"; status=$?
|
if ! array_contains __USCRONTAB_PIDFILES "$pidfile"; then
|
||||||
case "$status" in
|
local status
|
||||||
1)
|
pidfile_set -r "$pidfile"; status=$?
|
||||||
eerror "${2:-Une synchronisation} est en cours.
|
case "$status" in
|
||||||
Si vous pensez que c'est une erreur, veuillez vérifier le process de pid $(<"$1")
|
1)
|
||||||
puis supprimez le cas échéant le fichier $1"
|
eerror "${2:-Une synchronisation} est en cours.
|
||||||
return "$USCRONTAB_STOPEC"
|
Si vous pensez que c'est une erreur, veuillez vérifier le process de pid $(<"$pidfile")
|
||||||
;;
|
puis supprimez le cas échéant le fichier $pidfile"
|
||||||
10)
|
return "$USCRONTAB_STOPEC"
|
||||||
die "Une erreur s'est produite pendant l'écriture du fichier de pid. Impossible de continuer"
|
;;
|
||||||
;;
|
10)
|
||||||
esac
|
die "Une erreur s'est produite pendant l'écriture du fichier de pid. Impossible de continuer"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
array_add __USCRONTAB_PIDFILES "$pidfile"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
if [ -n "$3" -a -w "$(dirname "$3")" ]; then
|
if [ -n "$3" -a -w "$(dirname "$3")" ]; then
|
||||||
(set -o noclobber
|
(set -o noclobber
|
||||||
|
@ -340,12 +440,16 @@ puis supprimez le cas échéant le fichier $1"
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
function remove_pidfile() {
|
function remove_pidfile() {
|
||||||
[ -n "$1" ] && ac_clean "$1"
|
if [ -n "$1" ]; then
|
||||||
|
local pidfile="$(abspath "$1")"
|
||||||
|
ac_clean "$pidfile"
|
||||||
|
array_del __USCRONTAB_PIDFILES "$pidfile"
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
__ac_forgetall
|
__ac_forgetall
|
||||||
eval "$ctscript"
|
eval "$ctscript"
|
||||||
ac_cleanall
|
ac_cleanall
|
||||||
); ec=$?
|
); ec=$?
|
||||||
[ -f "$lockfile" ] && rm "$lockfile"
|
ac_clean "$lockfile"
|
||||||
exit "$ec"
|
exit "$ec"
|
||||||
fi
|
fi
|
||||||
|
|
Loading…
Reference in New Issue