Intégration de la branche release-7.2.0

This commit is contained in:
Jephté Clain 2017-09-26 17:01:37 +04:00
commit 4b30a7815b
9 changed files with 480 additions and 37 deletions

View File

@ -1,3 +1,28 @@
## Version 7.2.0 du 26/09/2017-17:01
* `1e576da` multiconf: rajouter conf_upgrade() dans conf_auto()
* `eeef48d` Intégration de la branche update-config
* `ea45055` implémentation simplifiée avec conf_upgrade()
* `efc60b3` description des modifications
* `36eec4a` Intégration de la branche update-ufile
* `2afffef` ne pas implémenter la recherche automatique de fichier de configuration
* `6ec37f6` ufile: implémenter l'option -r
* `6e8c200` maj TODO
* `cf629e6` uscrontab: support des oneshot vars
* `a66c0c2` uscrontab: ajout des options -@, -H, -M
* `52e838e` uwatch: ajouter les options -w et -p pour attendre la disparition d'un fichier ou d'un processus
* `8ad2e4c` lftp ne supporte pas l'utilisation des guillemets
* `7fb81a0` désactiver la vérification du certificat par défaut
* `dbc3daa` multiconf: bug
* `aff1c15` multiconf: support des variables de type path et compatibilité avec bash 4.3
* `8e17fb1` Intégration de la branche add-multiconf
* `a916180` ajouter conf_install pour installer les fichiers de configuration dans un répertoire standardisé
* `0372a5c` ufile charge les fichiers de ~/etc/ufile.d/
* `7d1ec90` simplifier l'API
* `c988692` fin implémentation
* `72e0c36` maj doc
* `f472501` squelette initial
## Version 7.1.0 du 10/09/2017-19:20
* `f131e21` uwatch: ajout de l'option -r

View File

@ -1 +1 @@
7.1.0
7.2.0

13
authftp
View File

@ -28,6 +28,9 @@ OPTIONS
--tls
Indiquer que la connexion se fera en TLS. Implique --lftp puisque ncftp
ne le supporte pas.
--verify-certificate
Avec la connexion --tls, forcer la vérification du certificat, qui est
désactivée par défaut.
note: A cause d'une limitation de lftp, ce n'est pas possible de se connecter
automatiquement avec lftp si le mot de passe contient une virgule. A cause de la
@ -43,6 +46,7 @@ noproxy="$AUTHFTP_PROXY_DISABLED"
lftp=
options=()
tls=
verify_certificate=no
parse_opts "${PRETTYOPTS[@]}" \
--help '$exit_with display_help' \
-p,--proxy noproxy= \
@ -50,6 +54,7 @@ parse_opts "${PRETTYOPTS[@]}" \
-l,--lftp lftp=1 \
-o:,--option: options \
--tls tls=1 \
--verify-certificate verify_certificate=yes \
@ args -- "$@" && set -- "${args[@]}" || die "$args"
[ -n "$noproxy" -o -n "$AUTHFTP_PROXY_HOST" ] || die "AUTHFTP_PROXY_HOST doit être défini"
@ -66,9 +71,13 @@ read_value -i "Entrez le chemin" path "$4" N
if [ -n "$lftp" ]; then
if [ -n "$noproxy" ]; then
exec lftp -u "$login,$password" "${options[@]}" "ftp://$host/$path"
exec lftp "${options[@]}" -e "\
set ssl:verify-certificate $verify_certificate
open -u $login,$password ftp://$host/$path"
else
exec lftp -u "${login}@${my_login}@${host},${password}@${my_password}" "${options[@]}" "ftp://$AUTHFTP_PROXY_HOST/$path"
exec lftp "${options[@]}" -e "\
set ssl:verify-certificate $verify_certificate
open -u ${login}@${my_login}@${host},${password}@${my_password} ftp://$AUTHFTP_PROXY_HOST/$path"
fi
else
if [ -n "$noproxy" ]; then

View File

@ -1,9 +1,5 @@
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
# Fichiers externes à inclure. Chacun de ces fichiers peut contenir des
# définitions de fonctions et de la variables RULES
INCLUDES=()
# Règles pour le classement des fichiers. Chaque règle est de la forme
# pattern:destdir[:renamef]
RULES=()

View File

@ -111,7 +111,15 @@ function copy_update_ask() {
# Copier ou mettre à jour le fichier $1 vers le fichier $2.
# Si le fichier existe déjà, la différence est affichée, et une confirmation
# est demandée pour l'écrasement du fichier.
# si $1 commence par '-' alors on s'en sert comme option pour configurer le
# niveau d'interaction pour demander la confirmation. les paramètres sont
# alors décalés
# Retourner vrai si le fichier a été copié sans erreur.
local interopt=-c
if [[ "$1" == -* ]]; then
interopt="$1"
shift
fi
local src="$1" dest="$2"
[ -d "$dest" ] && dest="$dest/$(basename -- "$src")"
@ -119,10 +127,14 @@ function copy_update_ask() {
[ -f "$dest" ] || copy_replace "$src" "$dest"
if testdiff "$src" "$dest"; then
diff -u "$dest" "$src"
if ask_yesno -c "Voulez-vous remplacer $(ppath "$dest") par la nouvelle version?" C; then
check_interaction "$interopt" && diff -u "$dest" "$src"
if ask_yesno "$interopt" "Voulez-vous remplacer $(ppath "$dest") par la nouvelle version?" C; then
copy_replace "$src" "$dest" "$3"
return $?
elif ! check_interaction "$interopt"; then
ewarn "Les mises à jours suivantes sont disponibles:"
diff -u "$dest" "$src"
ewarn "Le fichier $(ppath "$dest") n'a pas été mis à jour"
fi
fi
return 1

307
lib/ulib/multiconf Normal file
View File

@ -0,0 +1,307 @@
##@cooked comments # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
## Gestion de fichiers de configuration et de répertoires de configuration
##@cooked nocomments
uprovide multiconf
urequire install
function conf_local() {
# afficher les commandes pour définir comme locales les variables utilisées
# par les fonctions conf_*
# cela permet d'utiliser ces fonctions à l'intérieur d'autres fonctions sans
# polluer l'espace de nom
echo "local -a __CONF_DESCS __CONF_ARRAY_VARS __CONF_PATH_VARS"
}
function conf_auto() {
# charger la configuration pour l'outil $1 avec les variables $2..@
# conf_init n'est appelé que si des variables sont spécifiées, ce qui permet
# d'appeler conf_init au préalable si une configuration spécifique doit être
# faite.
# Ainsi:
# conf_auto NAME VARS...
# est équivalent à:
# conf_init VARS...
# conf_auto NAME
# est équivalent à:
# conf_init VARS...
# conf_find_files __CONF_FILES ~/etc/default/NAME.conf ~/etc/NAME.d/*.conf
# conf_upgrade ~/etc/default/NAME.conf
# conf_load_files "${__CONF_FILES[@]}"
# Pour supporter les scénarii où les fichiers de configuration sont ailleurs
# que dans ~/etc/default, l'argument NAME peut être un chemin:
# conf_auto PATH/TO/NAME VARS...
# est équivalent à:
# conf_init VARS...
# conf_find_files __CONF_FILES PATH/TO/NAME.conf PATH/TO/NAME.d/*.conf
# conf_upgrade PATH/TO/NAME.conf
# conf_load_files "${__CONF_FILES[@]}"
local __name="$1"; shift
[ -n "$__name" ] || return 1
[ $# -gt 0 ] && conf_init "$@"
local -a __CONF_FILES
if [[ "$__name" == */* ]]; then
conf_find_files __CONFS_FILES "$__name.conf" "$__name.d/*.conf"
[ $# -gt 0 ] && conf_upgrade "$__name.conf"
else
conf_find_files __CONFS_FILES "$HOME/etc/default/$__name.conf" "$HOME/etc/$__name.d/*.conf"
[ $# -gt 0 ] && conf_upgrade "$HOME/etc/default/$__name.conf"
fi
conf_load_files "${__CONFS_FILES[@]}"
}
function conf_init() {
# définir les variables attendues lors du chargement des fichiers de
# configuration par conf_load_files()
# Si cette fonction n'a pas d'argument, le contenu du tableau CONFIG s'il
# est existe est utilisé
# par défaut, les variables sont en mode scalaire: la définition d'une
# variable écrase la valeur précédente. Avec l'option -a les variables sont
# en mode tableau: les nouvelles valeurs sont rajoutées à la fin du tableau.
# Avec l'option -p les variables sont en mode chemin: les nouvelles valeurs
# sont ajoutées si elles n'existe pas déjà avec le séparateur ':'
# dans l'exemple suivant:
# conf_init NAME VALUE -a SRCDIRS DESTDIRS -p LIBPATH
# NAME et VALUE sont scalaires, SRCDIRS et DESTDIRS sont des tableaux et
# LIBPATH est de type chemin
# Les variables scalaires et chemin sont initialisées à la valeur vide ou à
# la valeur spécifiée e.g.:
# conf_init VAR=value MYPATH=a:b:c
# Les variables tableaux sont toujours initialisées à la valeur vide
# L'option -s permet de revenir au mode scalaire
# Note: il est possible d'associer une description à chaque variable ainsi
# qu'un en-tête, ce qui permet de construire le fichier de configuration ou
# de mettre à jour un fichier existant avec conf_upgrade(). Par exemple, les
# commandes suivantes:
# CONFIG=(
# "# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8"
# "# configurer l'application"
# -s
# "NAME=payet//nom de l'administrateur"
# "MAIL=admin@host.tld//mail de contact"
# -a
# "HOSTS//hôtes autorisés à se connecter"
# )
# conf_init
# permettent de générer automatiquement le fichier de configuration suivant:
# # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
# # configurer l'application
#
# # nom de l'administrateur
# #NAME=payet
#
# # mail de contact
# #MAIL=admin@host.tld
#
# # hôtes autorisés à se connecter
# #HOSTS=()
__CONF_DESCS=()
__CONF_ARRAY_VARS=()
__CONF_PATH_VARS=()
local __type=scalar __initial=1 __prefix __var __desc
[ $# -eq 0 ] && is_array CONFIG && set -- "${CONFIG[@]}"
while [ $# -gt 0 ]; do
if [ -n "$__initial" ]; then
if [ "${1:0:1}" == "#" ]; then
[ ${#__prefix} -gt 0 ] && __prefix="$__prefix"$'\n'
__prefix="$__prefix$1"
shift
continue
else
[ -n "$__prefix" ] && array_add __CONF_DESCS "$__prefix"
__initial=
fi
fi
case "$1" in
-a|--array) __type=array;;
-p|--path) __type=path;;
-s|--scalar) __type=scalar;;
*)
array_add __CONF_DESCS "$1"
splitfsep "$1" // __var __desc
case "$__type" in
array)
eval "${__var%%=*}=()"
array_addu __CONF_ARRAY_VARS "${__var%%=*}"
array_del __CONF_PATH_VARS "${__var%%=*}"
;;
path)
setv "$__var"
array_addu __CONF_PATH_VARS "${__var%%=*}"
array_del __CONF_ARRAY_VARS "${__var%%=*}"
;;
scalar)
setv "$__var"
;;
esac
;;
esac
shift
done
}
function conf_load() {
# charger les fichiers de configuration spécifiés
# conf_load SPECS...
# est équivalent à:
# conf_find_files __CONF_FILES SPECS...
# conf_load_files "${__CONF_FILES[@]}"
local -a __CONF_FILES
conf_find_files __CONFS_FILES "$@"
conf_load_files "${__CONFS_FILES[@]}"
}
function conf_find_files() {
# initialiser le tableau $1 avec les fichiers de configuration correspondant
# aux arguments $2..@
# - si on spécifie un fichier, il est pris tel quel s'il existe
# - si on spécifie un répertoire, tous les fichiers *.conf de ce répertoire
# sont pris
# - si on spécifie un pattern e.g path/to/*.conf alors tous les fichiers
# correspondant au pattern sont pris
# - sinon l'argument est ignoré
local __conf_dest="$1"; shift
local -a __conf_files
local __conf_spec __conf_dir __conf_wc
array_new "$__conf_dest"
for __conf_spec in "$@"; do
if [ -f "$__conf_spec" ]; then
array_add "$__conf_dest" "$__conf_spec"
continue
elif [ -d "$__conf_spec" ]; then
__conf_spec="$__conf_spec/*.conf"
fi
splitwcs "$__conf_spec" __conf_dir __conf_wc
array_lsfiles __conf_files "${__conf_dir:-.}" "$__conf_wc"
array_extend "$__conf_dest" __conf_files
done
}
function conf_load_files() {
# sourcer les fichiers spécifiés en faisant ce qui est nécessaire pour que
# les variables de __CONF_ARRAY_VARS soient correctement traitées.
local -a __conf_backups __conf_values
local __conf_file __conf_name __conf_i __conf_backup __conf_bn __conf_bv
for __conf_file in "$@"; do
# faire une copie de sauvegarde puis supprimer les variables tableaux
__conf_backups=()
for __conf_name in "${__CONF_ARRAY_VARS[@]}" "${__CONF_PATH_VARS[@]}"; do
__conf_backup="$(declare -p "$__conf_name" 2>/dev/null)"
if [ -z "$__conf_backup" ]; then
__conf_backup="$__conf_name="
else
# faire une correction de l'expression parce que la commande
# affichée par declare -p est différente entre bash 4.3 et bash
# 4.4 pour les tableaux. soit le tableau array=(a b)
# - bash 4.3 affiche declare -a array='([0]="a" [1]="b")'
# - bash 4.4 affiche declare -a array=([0]="a" [1]="b")
__conf_backup="${__conf_backup#declare }"
__conf_bn="${__conf_backup%% *}"
__conf_bv="${__conf_backup#* }"
if [[ "$__conf_bn" == -*a* ]]; then
__conf_bn="${__conf_bv%%=*}"
__conf_bv="${__conf_bv#*=}"
if [ "${__conf_bv:0:2}" == "'(" -a "${__conf_bv: -2:2}" == ")'" ]; then
__conf_backup="$__conf_bn=$(eval "echo $__conf_bv")"
else
__conf_backup="$__conf_bn=$__conf_bv"
fi
else
__conf_backup="$__conf_bv"
fi
fi
__conf_backups=("${__conf_backups[@]}" "$__conf_backup")
unset "$__conf_name"
done
# charger le fichier
source "$__conf_file"
# puis restaurer les variables ou les fusionner avec une éventuelle nouvelle valeur
__conf_i=0
for __conf_name in "${__CONF_ARRAY_VARS[@]}" "${__CONF_PATH_VARS[@]}"; do
__conf_backup="${__conf_backups[$__conf_i]}"
if [ -n "$(declare -p "$__conf_name" 2>/dev/null)" ]; then
# la variable a été redéfinie, la fusionner avec la précédente valeur
if array_contains __CONF_ARRAY_VARS "$__conf_name"; then
array_copy __conf_values "$__conf_name"
eval "$__conf_backup"
array_extend "$__conf_name" __conf_values
elif array_contains __CONF_PATH_VARS "$__conf_name"; then
__conf_values="${!__conf_name}"
eval "$__conf_backup"
uaddpath "$__conf_values" "$__conf_name"
fi
else
# la variable n'a pas été redéfinie, restaurer la précédente valeur
eval "$__conf_backup"
fi
__conf_i=$(($__conf_i + 1))
done
done
}
function conf_install() {
# USAGE: conf_install DEST SRCS...
# installer les fichiers de SRCS dans le répertoire standardisé DEST
# ## destination
# - si DEST est un nom sans chemin, e.g NAME, alors la destination est
# ~/etc/NAME.d
# - si DEST est un nom avec chemin, alors la valeur est prise telle quelle
# comme destination, et le répertoire est créé le cas échéant.
# Si un fichier existe déjà dans la destination, afficher une demande de
# confirmation avant de l'écraser
# ## source
# - si SRC est un fichier, le prendre tel quel
# - si SRC est un répertoire, prendre tous les fichiers SRC/*.conf
# - si SRC est un pattern, prendre tous les fichiers correspondant
local -a srcs
local src dir wc
local dest="$1"; shift
[[ "$dest" == */* ]] || dest="$HOME/etc/$dest.d"
mkdir -p "$dest" || return 1
for src in "$@"; do
if [ -f "$src" ]; then
srcs=("$src")
elif [ -d "$src" ]; then
array_lsfiles srcs "$src" "*.conf"
else
splitwcs "$src" dir wc
array_lsfiles srcs "$dir" "$wc"
fi
for src in "${srcs[@]}"; do
copy_update_ask -y "$src" "$dest"
done
done
}
function conf_upgrade() {
# USAGE: conf_upgrade DEST VARS...
# Si les variables VARS... sont spécifiées, on appelle au préalable conf_init()
local dest="$1"; shift
if [ $# -gt 0 ]; then
eval "$(conf_local)"
conf_init "$@"
fi
local desc namevalue name value
# calculer le préfixe et initialiser le fichier le cas échéant
if [ ! -f "$dest" ]; then
local prefix
for desc in "${__CONF_DESCS[@]}"; do
[ "${desc:0:1}" == "#" ] && prefix="$desc"
break
done
[ ${#prefix} -gt 0 ] || prefix="# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8"
echo "$prefix" >"$dest"
fi
# vérifier la présence de chaque variable
for desc in "${__CONF_DESCS[@]}"; do
[ "${desc:0:1}" == "#" ] && continue
splitfsep "$desc" // namevalue desc
splitvar "$namevalue" name value
if ! grep -qE "^\s*#*(\s*export)?\s*$name=" "$dest"; then
echo >>"$dest"
[ -n "$desc" ] && echo "# $desc" >>"$dest"
echo -n "#" >>"$dest"
echo_setv "$name" "$value" >>"$dest"
fi
done
}

50
ufile
View File

@ -1,7 +1,7 @@
#!/bin/bash
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
source "$(dirname "$0")/lib/ulib/ulib" || exit 1
urequire DEFAULTS
urequire DEFAULTS multiconf
function display_help() {
uecho "$scriptname: classer des fichiers selon certains règles
@ -37,6 +37,7 @@ forme pattern:destdir[:renamef]
USAGE
$scriptname [options] <files...>
$scriptname [options] -r <files|dirs...>
OPTIONS
-c, --config CONFIG
@ -56,6 +57,9 @@ OPTIONS
Toujours utiliser scp pour une copie distante. Par défaut s'il est
déterminé que l'hôte distant est en réalité l'hôte courant, alors la
copie est effectuée directement.
-r, --recursive
Classer récursivement tous les fichiers d'un répertoire. Sans cette
option, il n'est pas autorisé de fournir un répertoire comme argument.
-n, --fake
Afficher les opérations qui seraient faites
-l, --list
@ -116,6 +120,7 @@ args=(%
--force-cp force_cp=1
-S:,--ssh: SSH=
--force-scp force_scp=1
-r,--recursive recursive=1
-n,--fake fake=1
-l,--list action=list
-e,--edit action=edit
@ -126,8 +131,7 @@ parse_args "$@"; set -- "${args[@]}"
## charger toutes les règles
RULES=()
INCLUDES=()
conf_init -a RULES
if [ -n "$config" ]; then
if [ "$action" != edit ]; then
# le fichier doit exister, sauf en mode édition où il sera créé s'il
@ -140,22 +144,11 @@ if [ -n "$config" ]; then
else
set_defaults ufile
fi
array_copy rules RULES
for include in "${INCLUDES[@]}"; do
if [ -f "$include" ]; then
RULES=()
source "$include"
array_extend rules RULES
else
ewarn "$include: fichier introuvable"
fi
done
array_copy RULES rules
conf_load "$HOME/etc/ufile.d/*.conf"
## actions particulières
if [ "$action" == list ]; then
echo "# $(echo_seta2 INCLUDES)"
array_to_lines RULES
exit 0
elif [ "$action" == edit ]; then
@ -180,7 +173,7 @@ else
fi
[ $# -gt 0 ] || die "Vous devez spécifier des fichiers à classer"
[ ${#RULES[*]} -gt 0 ] || die "Vous devez spécifier des règles pour le classement des fichiers dans ~/etc/default/ufile"
[ ${#RULES[*]} -gt 0 ] || die "Vous devez spécifier des règles pour le classement des fichiers dans ~/etc/default/ufile ou ~/etc/ufile.d/*.conf"
# vérifier les règles
for rule in "${RULES[@]}"; do
@ -194,13 +187,28 @@ for rule in "${RULES[@]}"; do
fi
done
# faire la liste des fichiers
files=()
for file in "$@"; do
if [ -d "$file" -a -n "$recursive" ]; then
setx file=abspath "$file"
array_from_lines rfiles "$(find "$file" -type f)"
array_extendu files rfiles
elif [ -f "$file" ]; then
setx file=abspath "$file"
array_addu files "$file"
elif [ -n "$fake" ]; then
: # on est en mode fake, pas grave si le fichier n'est pas trouvé
elif [ -d "$file" ]; then
eerror "$file: est un répertoire. essayez avec -r"
else
eerror "$file: fichier introuvable. il sera ignoré"
fi
done
# faire le classement effectif
r=
for file in "$@"; do
[ -f "$file" -o -n "$fake" ] || {
eerror "$file: fichier introuvable. il sera ignoré"
continue
}
for file in "${files[@]}"; do
setx pf=abspath "$file"
setx dir=dirname -- "$pf"
setx filename=basename -- "$pf"

View File

@ -234,6 +234,9 @@ OPTIONS
$USCRONTAB_USERFILE
et chacun des fichiers du répertoire
$USCRONTAB_USERDIR
-N, --nop
Ne pas examiner la planification. Traiter uniquement l'option --osvar le
cas échéant.
-n, --fake
Afficher au lieu de les exécuter les commandes qui doivent être lancées
-P, --pause-for NBMINS
@ -248,6 +251,9 @@ OPTIONS
-f, --force
Forcer l'exécution de la planification, même si elle a été mise en pause
avec l'option --pause
-v, --osvar NAME[=VALUE]
Définir une variable de type oneshot. Par défaut, VALUE vaut 1 si elle
n'est pas spécifiée.
OPTIONS AVANCEES
--lock LOCKFILE
@ -286,6 +292,14 @@ OPTIONS AVANCEES
référence. Il faut respecter le format, sinon les résultats ne sont pas
garantis. Le mieux est de reprendre le résultat de l'option --show-ctnow
en le modifiant un peu si nécessaire.
-@, --hm H[:M]
-H, --h00
-M, --h30
Options pour simplifier l'utilisation de --force-ctnow. Supposons que
--show-ctnow affiche 'Y X day mon dow', alors:
-@ H:M | est équivalent à | --force-ctnow 'M H day mon dow'
-H | '' | --force-ctnow '0 X day mon dow'
-M | '' | --force-ctnow '30 X day mon dow'
-G, --any-ctnow
Pour le développement ou des tests, lancer toutes les commandes dans
l'ordre sans tenir compte de l'heure de référence. Cette commande ne
@ -345,8 +359,10 @@ lockfile=auto
lockdelay=
fake=
continuous=
force_ctnow=
pause=
force=
osvars=()
parse_opts "${PRETTYOPTS[@]}" \
--help '$exit_with display_help' \
-A,--add,--install action=install \
@ -356,25 +372,50 @@ parse_opts "${PRETTYOPTS[@]}" \
-a,--add action=add \
-r,--remove action=remove \
-l,--list action=list \
-N,--nop action=nop \
-n,--fake fake=1 \
-P:,--pause-for: '$action=pause; set@ pause' \
-p,--pause action=pause \
-Y,--unpause action=unpause \
-f,--force force=1 \
-v:,--osvar: osvars \
--lock: lockfile= \
--lockdelay: lockdelay= \
-c,--continuous continuous=1 \
-k:,--stop: USCRONTAB_STOPEC= \
--show-ctnow action=show-ctnow \
--force-ctnow: __CTRESOLVE_CTNOW= \
-@:,--hm: force_ctnow= \
-H,--h00 force_ctnow=h00 \
-M,--h30 force_ctnow=h30 \
-G,--any-ctnow __CTRESOLVE_CTNOW="**ANY**" \
@ args -- "$@" && set -- "${args[@]}" || die "$args"
uscrontab="$1"; shift
pausefile="$USCRONTAB_USERFILE.pauseuntil"
now="$(awk 'BEGIN { print int(systime() / 60) * 60 }')"
# ne prendre le premier argument comme un fichier que s'il existe ou s'il n'est
# pas de la forme *=*
if [[ "$1" == *=* ]]; then
if [ -f "$1" ]; then
uscrontab="$1"; shift
fi
else
uscrontab="$1"; shift
fi
# écrire les variables oneshot
for osvar in "${osvars[@]}"; do
if [[ "$osvar" == *=* ]]; then
splitvar "$osvar" name value
else
name="$osvar"
value=1
fi
name="${name##*/}" # au cas où...
echo -n "$value" >"$USCRONTAB_USERFILE.$name.osvar"
done
if [ "$action" == "pause" ]; then
[ -n "$pause" ] || pause=1440
if [ "$pause" -lt 0 ]; then
@ -436,10 +477,6 @@ elif [ "$action" == "remove" ]; then
exit 0
elif [ "$action" == "list" ]; then
if check_pause "$pausefile" "$now"; then
ewarn "En pause. Réactiver avec $scriptname -Y"
fi
if [ -n "$uscrontab" ]; then
uscrontab="$(abspath "$uscrontab")"
array_from_lines ctfiles "$(crontab -l 2>/dev/null | awkrun script="$script" uscrontab="$uscrontab" '$6 == script && $7 == uscrontab { print $7 }')"
@ -472,11 +509,18 @@ elif [ "$action" == "list" ]; then
etitle "$(ppath "$ctfile")" \
cat "$ctfile"
done
if check_pause "$pausefile" "$now"; then
ewarn "En pause. Réactiver avec $scriptname -Y"
fi
exit $r
elif [ "$action" == "show-ctnow" ]; then
ctnow "$now"
exit 0
elif [ "$action" == "nop" ]; then
exit 0
fi
[ -z "$uscrontab" -o -f "$uscrontab" ] || die "$uscrontab: fichier introuvable"
@ -569,7 +613,7 @@ elif [ "$action" == "run" ]; then
local cmd
cmd="${1%% *}"
case "$cmd" in
check_pidfile|remove_pidfile|elogto) return 1;;
check_pidfile|remove_pidfile|osvar|elogto) return 1;;
esac
return 0
}
@ -604,6 +648,21 @@ elif [ "$action" == "run" ]; then
die "$*"
}
if [ -n "$force_ctnow" ]; then
ctnow=($(ctnow "$now"))
case "$force_ctnow" in
h00) ctnow[0]=0;;
h30) ctnow[0]=30;;
*)
force_ctnow="${force_ctnow//./:}" # autoriser H.M en plus de H:M
splitpair "$force_ctnow" h m
ctnow[0]="${m:-0}"
ctnow[1]="$h"
;;
esac
__CTRESOLVE_CTNOW="${ctnow[*]}"
fi
__ctscript="$(ctresolve <"$uscrontab")"
ec=0
edebug "$__ctscript"
@ -648,6 +707,17 @@ puis supprimez le cas échéant le fichier $pidfile"
array_del __USCRONTAB_PIDFILES "$pidfile"
fi
}
function osvar() {
local __name __value
for __name in "$@"; do
splitvar "$__name" __name __value
if [ -f "$USCRONTAB_USERFILE.$__name.osvar" ]; then
__value="$(<"$USCRONTAB_USERFILE.$__name.osvar")"
rm "$USCRONTAB_USERFILE.$__name.osvar"
fi
_setv "$__name" "$__value"
done
}
__ac_forgetall
# Si des variables sont spécifiées, les initialiser avant de lancer le

16
uwatch
View File

@ -18,6 +18,10 @@ OPTIONS
Afficher un décompte depuis DURATION jusqu'à 0 puis terminer le script.
DURATION exprimé en secondes est le premier argument du script et vaut
par défaut ${DEFAULT_DURATION} soit $(($DEFAULT_DURATION / 60)) minutes.
-f, --wfile FILE
Arrêter dès que le fichier FILE n'existe plus
-p, --wpid PID
Arrêter dès que la processus PID n'existe plus
-u, --units
Avec l'option --count, afficher l'unité: sec., min. ou heures
-o, --offset NBSEC
@ -42,6 +46,8 @@ DEFAULT_STEP=1
DEFAULT_DURATION=300
what=time
wfile=
wpid=
units=
offset=
step=
@ -52,6 +58,8 @@ args=(
-t,--time what=time
-c,--count what=count
-r,--rcount what=rcount
-f:,--wfile: wfile=
-p:,--wpid: wpid=
-u,--units units=1
-o:,--offset: offset=
-s:,--step: step=
@ -112,5 +120,13 @@ while true; do
msg="$msg (jusqu'à $until)"
esac
echo -n $'\e[1G\e[K'"$prefix$msg$suffix"
if [ -n "$wfile" -a ! -f "$wfile" ]; then
echo
break
fi
if [ -n "$wpid" ] && ! kill -0 "$wpid" 2>/dev/null; then
echo
break
fi
sleep "$step"
done