nutools/ulib/crontab

283 lines
7.7 KiB
Bash

##@cooked comments # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
## Gestion du fichier crontab
##@cooked nocomments
##@require base
uprovide crontab
urequire base
# Ajouter la ligne $1 au crontab de l'utilisateur $2
# Le code de retour est 123 si la ligne est déjà présente
function add_to_crontab() {
local -a crontab=(crontab ${2:+-u "$2"})
local current="$("${crontab[@]}" -l 2>/dev/null)"
local tmpfile
ac_set_tmpfile tmpfile
if [ -n "$current" ]; then
echo "$current" >"$tmpfile"
fi
local NL=$'\n'
if quietgrep -xF "$1$NL#$1" "$tmpfile"; then
ac_clean "$tmpfile"
return 123
else
echo "$1" >>"$tmpfile"
"${crontab[@]}" "$tmpfile"
ac_clean "$tmpfile"
fi
}
# Supprimer la ligne $1 du crontab de l'utilisateur $2
# Le code de retour est 123 si la ligne a déjà été supprimée
function remove_from_crontab() {
local -a crontab=(crontab ${2:+-u "$2"})
local current="$("${crontab[@]}" -l 2>/dev/null)"
local tmpfile
ac_set_tmpfile tmpfile
if [ -n "$current" ]; then
echo "$current" >"$tmpfile"
fi
local NL=$'\n'
if ! quietgrep -xF "$1$NL#$1" "$tmpfile"; then
ac_clean "$tmpfile"
return 123
else
grep -vxF "$1$NL#$1" "$tmpfile" | "${crontab[@]}" -
ac_clean "$tmpfile"
fi
}
# Désactiver la ligne $1 du crontab de l'utilisateur $2 en mettant '#' devant. Si
# la ligne n'existe pas, elle est ajoutée mais commentée.
# Le code de retour est 123 si la ligne est déjà désactivée
function disable_in_crontab() {
local -a crontab=(crontab ${2:+-u "$2"})
local current="$("${crontab[@]}" -l 2>/dev/null)"
local tmpfile
ac_set_tmpfile tmpfile
if [ -n "$current" ]; then
echo "$current" >"$tmpfile"
fi
local NL=$'\n'
if ! quietgrep -xF "$1$NL#$1" "$tmpfile"; then
echo "#$1" >>"$tmpfile"
"${crontab[@]}" "$tmpfile"
elif quietgrep -xF "#$1" "$tmpfile"; then
ac_clean "$tmpfile"
return 123
else
<"$tmpfile" awkrun line="$1" '$0 == line { $0 = "#" $0 } { print }' | "${crontab[@]}" -
ac_clean "$tmpfile"
fi
}
# Activer la ligne $1 du crontab de l'utilisateur $2 en enlevant '#' devant. Si
# la ligne n'existe pas, elle est ajoutée.
# Le code de retour est 123 si la ligne est déjà activée
function enable_in_crontab() {
local -a crontab=(crontab ${2:+-u "$2"})
local current="$("${crontab[@]}" -l 2>/dev/null)"
local tmpfile
ac_set_tmpfile tmpfile
if [ -n "$current" ]; then
echo "$current" >"$tmpfile"
fi
local NL=$'\n'
if ! quietgrep -xF "$1$NL#$1" "$tmpfile"; then
echo "$1" >>"$tmpfile"
"${crontab[@]}" "$tmpfile"
elif quietgrep -xF "$1" "$tmpfile"; then
ac_clean "$tmpfile"
return 123
else
<"$tmpfile" awkrun line="$1" '$0 == "#" line { sub(/^#/, "") } { print }' | "${crontab[@]}" -
ac_clean "$tmpfile"
fi
}
# Afficher la spécification crontab correspondant à l'heure courante
function ctnow() {
date +"%-M %-H %-d %-m %u"
}
# Analyser STDIN qui contient des lignes au format crontab, et afficher des
# commandes pour les lignes correspondant à la date courante.
# Les commandes sont de la forme "export var=value" pour la définition d'une
# variable, "__ctexec 'cmd'" pour exécuter la commande correspondante ou
# "__cterror 'msg'" en cas d'erreur de syntaxe sur une ligne. Il faut bien
# entendu définir les function __ctexec et __cterror.
# Cette fonction s'utilise de cette manière:
# function __ctexec() { eval "$*"; }
# function __cterror() { die "$*"; }
# eval "$(ctresolve <crontab)"
function ctresolve() {
local -a ctnow
eval "ctnow=($(ctnow))"
filter_conf | awkrun -f ctnow[@] '
function ctmatch(ctval, ref, parts, part, i, j, start, end, step, ok) {
ok = 0
split(ctval, parts, /,/)
for(i = 1; i <= length(parts); i++) {
part = parts[i]
start = -1; end = -1; step = 1
# extraire /step
pos = index(part, "/")
if (pos != 0) {
step = substr(part, pos + 1) + 0
part = substr(part, 1, pos - 1)
}
# traiter start-end
pos = index(part, "-")
if (pos != 0) {
start = substr(part, 1, pos - 1) + 0
end = substr(part, pos + 1) + 0
} else {
start = part + 0
end = start
}
# tester si ça matche
#print "start=" start ", end=" end ", step=" step", ref=" ref #DEBUG
for (j = start; j <= end; j += step) {
if (j == ref) {
ok = 1
break
}
}
if (ok) break
}
return ok
}
BEGIN {
refM = ctnow[1]; refH = ctnow[2]; refdom = ctnow[3]; refmon = ctnow[4]; refdow = ctnow[5]
ctref = refM " " refH " " refdom " " refmon " " refdow
print "##now: " ctref
match_ctline = 0
match_indented = 0
}
/^(export[ \t]+)?[a-zA-Z_][a-zA-Z0-9_]*[-+%#?]=/ {
# manipulation de variables de type PATH
match($0, /^(export[ \t]+)?([a-zA-Z_][a-zA-Z0-9_]*)([-+%#?])=(.*)$/, parts)
name = parts[2]
type = parts[3]
value = parts[4]
if (type == "+" || type == "%") {
print "uaddpath " value " " name
} else if (type == "#") {
print "uinspath " value " " name
} else if (type == "-") {
print "udelpath " value " " name
} else if (type == "?") {
print "[ -n \"$" name "\" ] || " name "=" value
}
print "export " name
next
}
/^(export[ \t]+)?[a-zA-Z_][a-zA-Z0-9_]*=/ {
# spécification de variable
sub(/^export[ \t]+/, "", $0)
print "export " $0
next
}
/^\$.+/ {
# exécution de commande arbitraire
if ($0 ~ /^\$\{([ \t]*(#.*)?)?$/) {
# commande sur plusieurs lignes
getline
while ($0 !~ /^\$\}([ \t]*(#.*)?)?$/) {
print
if (getline <= 0) break
}
} else {
# commande sur une seule ligne
sub(/^\$/, "", $0)
print
}
next
}
/^[ \t]*[-0-9/*,]+[ ]*[-0-9/*,]+[ ]*[-0-9/*,]+[ ]*[-0-9/*,]+[ ]*[-0-9/*,]+/ {
# ligne de planification
M = $1; H = $2; dom = $3; mon = $4; dow = $5
sub(/^[ ]*[^ ]+[ ]+[^ ]+[ ]+[^ ]+[ ]+[^ ]+[ ]+[^ ]+[ ]*/, "", $0)
if (!match_ctline) match_indented = 0
ctline = M " " H " " dom " " mon " " dow
gsub(/\*/, "0-59", M)
Mok = ctmatch(M, refM)
gsub(/\*/, "0-23", H)
Hok = ctmatch(H, refH)
gsub(/\*/, "1-31", dom)
domok = ctmatch(dom, refdom)
gsub(/\*/, "1-12", mon)
monok = ctmatch(mon, refmon)
gsub(/\*/, "1-7", dow)
dowok = ctmatch(dow, refdow)
if (Mok && Hok && monok && (domok || dowok)) {
print "##matches: " ctline
match_ctline = 1
match_indented = 1
}
if (match_ctline && $0 != "") {
print "__ctexec " quote_value($0)
match_ctline = 0
}
next
}
/^[ \t]+/ {
if (match_indented) {
# il faut matcher les commandes indentees
sub(/^[ \t]+/, "", $0)
print "__ctexec " quote_value($0)
}
next
}
{
print "__cterror " quote_value("ligne de format incorrect: " $0)
}
'
}
## Préfixes
function get_default_crontabdir_prefix() {
if check_sysinfos -s darwin; then
if check_sysinfos -d 10.6+; then
echo /var/at/tabs
else
echo /var/cron/tabs
fi
elif check_sysinfos -s linux; then
if check_sysinfos -d debianlike; then
echo /var/spool/cron/crontabs
elif check_sysinfos -d redhatlike; then
echo /var/spool/cron
fi
fi
}
__crontab_prefixes=
function __compute_crontab_prefixes() {
[ -n "$__crontab_prefixes" ] && return
CRONTABDIR="${CRONTABDIR:-$(get_default_crontabdir_prefix)}"
__crontab_prefixes=1
}
UTOOLS_PREFIXES=("${UTOOLS_PREFIXES[@]}" CRONTABDIR)
function compute_crontab_prefixes() {
__compute_crontab_prefixes
}
function recompute_crontab_prefixes() {
__crontab_prefixes=
__compute_crontab_prefixes
}
function get_CRONTABDIR_prefix() {
__compute_crontab_prefixes
echo "$CRONTABDIR"
}