1995 lines
76 KiB
Bash
1995 lines
76 KiB
Bash
##@cooked comments # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
|
|
## Fonctions pour la commande runs
|
|
##@cooked nocomments
|
|
##@require base
|
|
uprovide runs
|
|
urequire base
|
|
|
|
################################################################################
|
|
# Configuration
|
|
|
|
function __runs_initt() {
|
|
if is_yes "$verbose"; then
|
|
rscriptt="# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
|
|
desc \"CHANGEME: Description du script $rscriptname\"
|
|
#var name=value arr+=value arr-=value
|
|
#var arr value0 value1...
|
|
|
|
script:
|
|
|
|
# pour un script d'installation qui ne doit tourner qu'une seule fois:
|
|
#shouldrun || exit
|
|
#...
|
|
#setdone"
|
|
runsconft="# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
|
|
# Ce fichier contient les paramètres qui sont partagés par tous les scripts de $host
|
|
#var name=value arr+=value arr-=value
|
|
#var arr value0 value1..."
|
|
else
|
|
rscriptt="# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
|
|
desc \"\"
|
|
|
|
script:"
|
|
runsconft="# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
|
|
# Ce fichier contient les paramètres qui sont partagés par tous les scripts de $host"
|
|
fi
|
|
sysinfost="# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
|
|
# Ce fichier contient les informations sur le type de système installé sur $host
|
|
# Il est possible de recopier la valeur affichée par la commande usysinfos"
|
|
if [ -n "$sysinfos_data" ]; then
|
|
sysinfost="$sysinfost
|
|
$sysinfos_data"
|
|
else
|
|
sysinfost="$sysinfost
|
|
#sysname=()
|
|
#sysdist=()
|
|
#sysver=()
|
|
#bits="
|
|
fi
|
|
defaultt="# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
|
|
# Ce fichier contient la liste des script à lancer avec le compte root pour
|
|
# configurer $host
|
|
# Chaque ligne contient le nom du script suivi des arguments éventuels
|
|
#generic-base
|
|
#@services
|
|
#@config"
|
|
configt="# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
|
|
# Ce fichier contient la recette pour configurer le serveur: configuration des
|
|
# mappings, configuration du serveur de courrier, de la sauvegarde, etc... Il
|
|
# faut relancer cette recette à chaque fois que la configuration change.
|
|
#mailrelay rootmail=
|
|
#hostmappings mappings
|
|
#backupclient bckhost="
|
|
servicest="# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
|
|
# Ce fichier contient la recette pour installer les services du serveur. Cette
|
|
# installation ne se fait en principe qu'une seule fois."
|
|
userdefaultt="# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
|
|
# Ce fichier contient la liste des script à lancer avec le compte utilisateur
|
|
# pour configurer $host
|
|
# Chaque ligne contient le nom du script suivi des arguments éventuels"
|
|
}
|
|
|
|
function runs_initdir() {
|
|
# Initialiser le répertoire d'hôte. $1 est un nom d'hôte pleinement
|
|
# qualifié, et les fichiers sont créés dans le premier répertoire de
|
|
# RUNSHOSTSDIRS qui convient: si un fichier .udir existe avec un tableau
|
|
# runs_domains qui contient le domaine de l'hôte spécifié, alors c'est ce
|
|
# répertoire qui est sélectionné. Sinon, on prend le premier répertoire de
|
|
# RUNSHOSTSDIRS.
|
|
# $2 spécifie si le fichier doit être créé avec de l'aide (yes) ou avec le
|
|
# script minimum (no)
|
|
# $3 est le contenu à placer dans le fichier sysinfos.conf, s'il n'a pas
|
|
# déjà été provisionné.
|
|
# Il faut lancer __runs_setpath avant d'utiliser cette fonction et
|
|
# RUNSHOSTDIRS ne doit pas être vide
|
|
[ -n "${RUNSHOSTSDIRS[*]}" ] || return 1
|
|
|
|
local runshostdir
|
|
local edit_default
|
|
local host hostname domain
|
|
splithost "$1" hostname domain
|
|
local verbose="${2:-yes}"
|
|
local sysinfos_data="$3"
|
|
if [ -n "$domain" ]; then
|
|
host="$hostname.$domain"
|
|
|
|
local dir found
|
|
# d'abord chercher si le répertoire existe déjà
|
|
for runshostdir in "${RUNSHOSTSDIRS[@]}"; do
|
|
found=
|
|
for dir in "$runshostdir/$host/runs" "$runshostdir/$domain/$hostname/runs" "$runshostdir/$host" "$runshostdir/$domain/$hostname"; do
|
|
if [ -d "$dir" ]; then
|
|
found=1
|
|
break
|
|
fi
|
|
done
|
|
done
|
|
# sinon chercher un répertoire qui convient
|
|
if [ -z "$found" ]; then
|
|
for runshostdir in "${RUNSHOSTSDIRS[@]}"; do
|
|
if [ -f "$runshostdir/.udir" ]; then
|
|
(source "$runshostdir/.udir"; array_contains runs_domains "$domain") && {
|
|
found=1
|
|
break
|
|
}
|
|
fi
|
|
done
|
|
fi
|
|
if [ -n "$found" ]; then
|
|
found=
|
|
for dir in "$runshostdir/$host" "$runshostdir/$domain/$hostname"; do
|
|
if [ -d "$dir" ]; then
|
|
runshostdir="$dir/runs"
|
|
found=1
|
|
break
|
|
fi
|
|
done
|
|
[ -n "$found" ] || runshostdir="$runshostdir/$host/runs"
|
|
else
|
|
runshostdir="${RUNSHOSTSDIRS[0]}/$host/runs"
|
|
fi
|
|
else
|
|
host="$hostname"
|
|
runshostdir="${RUNSHOSTSDIRS[0]}/$host/runs"
|
|
fi
|
|
|
|
local rscriptt runsconft sysinfost defaultt configt servicest
|
|
__runs_initt
|
|
|
|
mkdir -p "$runshostdir"
|
|
if [ ! -f "$runshostdir/runs.conf" ]; then
|
|
estep "Création de $(ppath "$runshostdir/runs.conf")"
|
|
echo "$runsconft" >"$runshostdir/runs.conf"
|
|
fi
|
|
if [ ! -f "$runshostdir/sysinfos.conf" ]; then
|
|
estep "Création de $(ppath "$runshostdir/sysinfos.conf")"
|
|
echo "$sysinfost" >"$runshostdir/sysinfos.conf"
|
|
fi
|
|
if [ ! -f "$runshostdir/default.rr" ]; then
|
|
estep "Création de $(ppath "$runshostdir/default.rr")"
|
|
echo "$defaultt" >"$runshostdir/default.rr"
|
|
edit_default=1
|
|
fi
|
|
if [ ! -f "$runshostdir/config.rr" ]; then
|
|
estep "Création de $(ppath "$runshostdir/config.rr")"
|
|
echo "$configt" >"$runshostdir/config.rr"
|
|
fi
|
|
if [ ! -f "$runshostdir/services.rr" ]; then
|
|
estep "Création de $(ppath "$runshostdir/services.rr")"
|
|
echo "$servicest" >"$runshostdir/services.rr"
|
|
fi
|
|
if [ ! -f "$runshostdir/userdefault.rr" ]; then
|
|
estep "Création de $(ppath "$runshostdir/userdefault.rr")"
|
|
echo "$userdefaultt" >"$runshostdir/userdefault.rr"
|
|
fi
|
|
|
|
[ -n "$edit_default" ] && "${EDITOR:-vi}" "$runshostdir/default.rr"
|
|
|
|
return 0
|
|
}
|
|
|
|
function __runs_create_rscript() {
|
|
local rscript="$1"
|
|
local rscriptname="$(basename "$rscript")"
|
|
local overwrite="$2"
|
|
local template
|
|
if [ "$rscriptname" == "runs.conf" ]; then
|
|
template="$runsconft"
|
|
elif [ "$rscriptname" == "sysinfos.conf" ]; then
|
|
template="$sysinfost"
|
|
elif [ "$rscriptname" == "default" -o "$rscriptname" == "default.rr" ]; then
|
|
template="$defaultt"
|
|
elif [ "$rscriptname" == "userdefault" -o "$rscriptname" == "userdefault.rr" ]; then
|
|
template="$userdefaultt"
|
|
elif false; then
|
|
: # XXX reconnaitre l'extension .rr pour créer un modèle de recette
|
|
else
|
|
withext "$rscript" || rscript="$rscript.rs"
|
|
template="$rscriptt"
|
|
fi
|
|
|
|
if [ -f "$rscript" ] && is_no "$overwrite"; then
|
|
eerror "$(ppath "$rscript"): fichier déjà existant"
|
|
return 1
|
|
fi
|
|
|
|
mkdirof "$rscript"
|
|
estep "Création de $(ppath "$rscript")"
|
|
echo "$template" >"$rscript"
|
|
|
|
array_add new_rscripts "$(abspath "$rscript")"
|
|
|
|
return 0
|
|
}
|
|
|
|
function runs_create_rscript() {
|
|
# Créer un modèle de script. Si $2 est spécifié, c'est un nom d'hôte
|
|
# pleinement qualifié. Le répertoire d'hôte correspondant *doit* exister.
|
|
# $3 spécifie si le fichier doit être créé avec de l'aide (yes) ou avec le
|
|
# script minimum (no)
|
|
# Si $2!="", il faut lancer __runs_setpath avant d'utiliser cette fonction
|
|
# et RUNSHOSTDIRS ne doit pas être vide
|
|
# Le chemin du nouveau script est ajouté au tableau new_rscripts
|
|
local rscript="$1"
|
|
local host="$2"
|
|
local verbose="${3:-yes}"
|
|
local overwrite="${4:-no}"
|
|
|
|
local rscriptt runsconft sysinfost defaultt userdefaultt
|
|
__runs_initt
|
|
|
|
if [ -n "$host" ]; then
|
|
if withpath "$rscript"; then
|
|
# si c'est un chemin relatif à '.', '..', ou un chemin absolu, le
|
|
# prendre tel quel
|
|
__runs_create_rscript "$rscript" "$overwrite" || return 1
|
|
else
|
|
# trouver le répertoire d'hôte
|
|
[ -n "${RUNSHOSTSDIRS[*]}" ] || return 1
|
|
|
|
local found runsdir hostname domain
|
|
splithost "$host" hostname domain
|
|
for runsdir in "${RUNSHOSTSDIRS[@]}"; do
|
|
found=
|
|
for dir in "$runsdir/$host/runs" "$runsdir/$domain/$hostname/runs" "$runsdir/$host" "$runsdir/$domain/$hostname"; do
|
|
if [ -d "$dir" ]; then
|
|
runsdir="$dir"
|
|
found=1
|
|
break
|
|
fi
|
|
done
|
|
[ -n "$found" ] && break
|
|
done
|
|
[ -n "$found" ] || return 1
|
|
|
|
# puis exprimer le chemin spécifié par rapport à runsdir
|
|
__runs_create_rscript "$runsdir/$rscript" "$overwrite" || return 1
|
|
fi
|
|
|
|
else
|
|
__runs_create_rscript "$rscript" "$overwrite" || return 1
|
|
fi
|
|
}
|
|
|
|
function runs_unsupported_system() {
|
|
# Afficher un message d'erreur indiquant que le système actuel n'est pas
|
|
# supporté, et quitter le script
|
|
local msg="Ce script n'est pas supporté sur $MYSYSNAME${MYSYSDIST:+/$MYSYSDIST}${MYSYSVER:+/$MYSYSVER}"
|
|
[ -n "$*" ] && msg="$msg
|
|
Il faut au moins l'un des systèmes suivants: $*"
|
|
die "$msg"
|
|
}
|
|
|
|
function runs_require_sysinfos() {
|
|
# Vérifier le système actuel avec check_sysinfos(), et afficher un message
|
|
# d'erreur avec runs_unsupported_system() s'il ne correspond pas à la
|
|
# requête
|
|
check_sysinfos "$@" && return 0
|
|
local infos info
|
|
# Construire une description du type de système attendu en fonction des
|
|
# arguments. Actuellement, on se contente de copier la ligne de commande, en
|
|
# sautant les options.
|
|
# XXX améliorer l'algorithme pour décrire précisément le système attendu
|
|
for info in "$@"; do
|
|
if ! [[ "$info" == -* ]]; then
|
|
infos=("${infos[@]}" "$info")
|
|
fi
|
|
done
|
|
runs_unsupported_system "${infos[@]}"
|
|
}
|
|
|
|
################################################################################
|
|
# Lancement de scripts nommés
|
|
|
|
function __runs_setpath() {
|
|
# Initialiser les tableaux $1(=RUNSSCRIPTSDIRS), $2(=RUNSMODULESDIRS),
|
|
# $3(=RUNSHOSTSDIRS) avec les chemins de RUNSSCRIPTSPATH, RUNSMODULESPATH,
|
|
# RUNSHOSTSPATH
|
|
function __runs_addsuffix() { echo "$1${2:+/$2}"; }
|
|
local -a __runsdirs __tmpa
|
|
local __runsscriptsdirs="${1:-RUNSSCRIPTSDIRS}"
|
|
local __runsmodulesdirs="${2:-RUNSMODULESDIRS}"
|
|
local __runshostsdirs="${3:-RUNSHOSTSDIRS}"
|
|
|
|
array_from_path "$__runsscriptsdirs" "$RUNSSCRIPTSPATH"
|
|
array_map "$__runsscriptsdirs" abspath
|
|
|
|
array_from_path "$__runsmodulesdirs" "$RUNSMODULESPATH"
|
|
array_map "$__runsmodulesdirs" abspath
|
|
|
|
array_from_path "$__runshostsdirs" "$RUNSHOSTSPATH"
|
|
array_map "$__runshostsdirs" abspath
|
|
}
|
|
|
|
function __runs_find_host() {
|
|
# Si $1 est un nom d'hôte pleinement qualifié, retourner cette valeur
|
|
# Sinon, chercher en utilisant RUNSDOMAINS un nom d'hôte qui aurait déjà été
|
|
# configuré
|
|
local host="$1" hostname domain
|
|
splithost "$host" hostname domain
|
|
if [ -n "$domain" ]; then
|
|
echo "$host"
|
|
return 0
|
|
fi
|
|
|
|
local runsdomain runsdir
|
|
for runsdomain in "${RUNSDOMAINS[@]}"; do
|
|
for runsdir in "${RUNSHOSTSDIRS[@]}"; do
|
|
if [ -d "$runsdir/$hostname.$runsdomain" ]; then
|
|
echo "$hostname.$runsdomain"
|
|
return 0
|
|
elif [ -d "$runsdir/$runsdomain/$hostname" ]; then
|
|
echo "$hostname.$runsdomain"
|
|
return 0
|
|
fi
|
|
done
|
|
done
|
|
echo "$host"
|
|
return 1
|
|
}
|
|
function runs_find_host() {
|
|
local RUNSSCRIPTSDIRS RUNSMODULESDIRS RUNSHOSTSDIRS; __runs_setpath
|
|
__runs_find_host "$@"
|
|
}
|
|
|
|
function runs_add_domain() {
|
|
# Si $1 est nom d'hôte pleinement qualifié, retourner cette valeur
|
|
# Sinon, lui rajouter le domaine RUNSDOMAIN
|
|
local host="$1" hostname domain
|
|
splithost "$host" hostname domain
|
|
if [ -n "$domain" -o -z "$RUNSDOMAIN" ]; then
|
|
echo "$host"
|
|
return 0
|
|
fi
|
|
echo "$host.$RUNSDOMAIN"
|
|
return 1
|
|
}
|
|
|
|
function runs_find_hostfile() {
|
|
# Trouver et afficher le fichier d'hôte $1 dans les répertoires du tableau
|
|
# $3(=RUNSHOSTSDIRS), pour l'hôte $2(=$RUNSHOST). Retourner 0 en cas de
|
|
# succès, 1 en cas d'échec.
|
|
# Si host=$2 est une valeur non vide, la recherche est effectuée dans
|
|
# {$RUNSHOSTSDIRS}/$host et {$RUNSHOSTSDIRS}/$domain/$hostname. Sinon,
|
|
# retourner 1, car il faut spécifier un nom d'hôte.
|
|
local __hostfile="$1" __runshost="${2:-$RUNSHOST}" __runshostsdirs="${3:-RUNSHOSTSDIRS}[@]"
|
|
local __hostname __domain
|
|
local __runsdir __runsfile
|
|
|
|
[ -n "$__runshost" ] || return 1
|
|
splithost "$__runshost" __hostname __domain
|
|
for __runsdir in "${!__runshostsdirs}"; do
|
|
for __runsfile in \
|
|
"$__runsdir/$__runshost/runs/$__hostfile" \
|
|
"$__runsdir/$__domain/$__hostname/runs/$__hostfile"\
|
|
"$__runsdir/$__runshost/$__hostfile" \
|
|
"$__runsdir/$__domain/$__hostname/$__hostfile"; do
|
|
if [ -e "$__runsfile" ]; then
|
|
echo "$__runsfile"
|
|
return 0
|
|
fi
|
|
done
|
|
done
|
|
return 1
|
|
}
|
|
|
|
function runs_find_datafile() {
|
|
# Trouver et afficher le fichier de données $1 dans le répertoire $3 s'il
|
|
# est non vide puis dans les répertoires des tableaux $4(=RUNSSCRIPTSDIRS),
|
|
# $5(=RUNSMODULESDIRS) et $6(=RUNSHOSTSDIRS), pour l'hôte
|
|
# $2(=$RUNSHOST). Retourner 0 en cas de succès, 1 en cas d'échec.
|
|
# - D'abord, si $1 *n'est pas* de la forme "./path" ou "../path", chercher
|
|
# dans $3.
|
|
# - Puis si l'hôte est spécifié, chercher dans {$RUNSHOSTSDIRS}/$host et
|
|
# {$RUNSHOSTSDIRS}/$domain/$hostname.
|
|
# - Puis chercher dans {$RUNSSCRIPTSDIRS} puis {$RUNSMODULESDIRS}.
|
|
# - Puis, si $1 est de la forme "./path" ou "../path", chercher dans $3.
|
|
# - Sinon, retourner 1
|
|
local __datafile="$1" __runshost="${2:-$RUNSHOST}"
|
|
local __runsscriptdir="$3"
|
|
local __runsscriptsdirs="${4:-RUNSSCRIPTSDIRS}[@]"
|
|
local __runsmodulesdirs="${5:-RUNSMODULESDIRS}[@]"
|
|
local __runshostsdirs="${6:-RUNSHOSTSDIRS}[@]"
|
|
local __domain __hostname
|
|
local __runsdir __runsfile
|
|
local __withpath
|
|
|
|
withpath "$__datafile" && __withpath=1
|
|
|
|
# D'abord chercher dans le répertoire du script
|
|
if [ -n "$__withpath" -a -n "$__runsscriptdir" ]; then
|
|
__runsfile="$__runsscriptdir/$__datafile"
|
|
if [ -e "$__runsfile" ]; then
|
|
echo "$__runsfile"
|
|
return 0
|
|
fi
|
|
fi
|
|
# puis chercher dans les répertoire d'hôtes
|
|
if [ -n "$__runshost" ]; then
|
|
splithost "$__runshost" __hostname __domain
|
|
for __runsdir in "${!__runshostsdirs}"; do
|
|
for __runsfile in \
|
|
"$__runsdir/$__runshost/runs/$__datafile" \
|
|
"$__runsdir/$__domain/$__hostname/runs/$__datafile"\
|
|
"$__runsdir/$__runshost/$__datafile" \
|
|
"$__runsdir/$__domain/$__hostname/$__datafile"; do
|
|
if [ -e "$__runsfile" ]; then
|
|
echo "$__runsfile"
|
|
return 0
|
|
fi
|
|
done
|
|
done
|
|
fi
|
|
# puis chercher dans les répertoires des scripts et des modules
|
|
for __runsdir in "${!__runsscriptsdirs}" "${!__runsmodulesdirs}"; do
|
|
__runsfile="$__runsdir/$__datafile"
|
|
if [ -e "$__runsfile" ]; then
|
|
echo "$__runsfile"
|
|
return 0
|
|
fi
|
|
done
|
|
# puis chercher dans le répertoire du script
|
|
if [ -z "$__withpath" -a -n "$__runsscriptdir" ]; then
|
|
__runsfile="$__runsscriptdir/$__datafile"
|
|
if [ -e "$__runsfile" ]; then
|
|
echo "$__runsfile"
|
|
return 0
|
|
fi
|
|
fi
|
|
# fichier non trouvé
|
|
return 1
|
|
}
|
|
|
|
function runs_initvars() {
|
|
# Initialiser les variables RUNSDIR, RUNSSCRIPT, RUNSDIRPATH,
|
|
# RUNSSCRIPTPATH, RUNSSCRIPTDIR et RUNSSCRIPTNAME pour le script $1.
|
|
# Les valeurs sont initialisées comme suit:
|
|
# RUNSSCRIPT="$(abspath "$1")"
|
|
# RUNSDIR="$2" (le répertoire de $RUNS*PATH dans lequel a été trouvé le
|
|
# script)
|
|
# Si $3!="", RUNSDIRPATH="$3" et RUNSSCRIPTPATH="$4"
|
|
# Sinon, RUNSDIRPATH="$RUNSSCRIPTDIR" et RUNSSCRIPTPATH="$RUNSSCRIPTNAME"
|
|
RUNSSCRIPT="$(abspath "$1")"
|
|
RUNSSCRIPTDIR="$(dirname "$RUNSSCRIPT")"
|
|
RUNSSCRIPTNAME="$(basename "$RUNSSCRIPT")"
|
|
RUNSDIR="$2"
|
|
if [ -n "$3" ]; then
|
|
RUNSDIRPATH="$3"
|
|
RUNSSCRIPTPATH="$4"
|
|
else
|
|
RUNSDIRPATH="$RUNSSCRIPTDIR"
|
|
RUNSSCRIPTPATH="$RUNSSCRIPTNAME"
|
|
fi
|
|
}
|
|
|
|
function runs_find_scriptfile() {
|
|
# Trouver sans l'afficher le script $1 dans les répertoires des tableaux
|
|
# $3(=RUNSSCRIPTSDIRS), $4(=RUNSMODULESDIRS) et $5(=RUNSHOSTSDIRS), en
|
|
# considérant que le script sera lancé sur l'hôte $2(=$RUNSHOST), et
|
|
# initialiser les variables RUNSDIR, RUNSSCRIPT, RUNSSCRIPTDIR,
|
|
# RUNSSCRIPTNAME, RUNSDIRPATH et RUNSSCRIPTPATH. Retourner 0 en cas de
|
|
# succès, 1 en cas d'échec.
|
|
# $6 vaut ".rs" par défaut est c'est une extension à rajouter au nom
|
|
# spécifié si le fichier sans l'extension n'existe pas
|
|
# RUNSDIR est le répertoire dans lequel a été trouvé le script (parmi les
|
|
# valeurs fournies dans les tableaux RUNSSCRIPTSDIRS, RUNSMODULESDIRS,
|
|
# RUNSHOSTSDIRS), RUNSDIRPATH est le répertoire à partir duquel est exprimé
|
|
# le chemin du script (i.e RUNSDIRPATH + RUNSSCRIPTPATH == RUNSSCRIPT),
|
|
# RUNSSCRIPT contient le chemin absolu vers le script, RUNSSCRIPTPATH
|
|
# contient le chemin du script dans RUNSDIRPATH, RUNSSCRIPTDIR le répertoire
|
|
# du script, et RUNSSCRIPTNAME le nom du script.
|
|
# D'abord, si l'hôte est spécifié, chercher dans {$RUNSHOSTSDIRS}/$host et
|
|
# {$RUNSHOSTSDIRS}/$domain/$hostname. Puis chercher dans {$RUNSSCRIPTSDIRS}
|
|
# puis {$RUNSMODULESDIRS}. Sinon, retourner 1
|
|
local __scriptfile="$1" __runshost="${2:-$RUNSHOST}"
|
|
local __runsscriptsdirs="${3:-RUNSSCRIPTSDIRS}[@]"
|
|
local __runsmodulesdirs="${4:-RUNSMODULESDIRS}[@]"
|
|
local __runshostsdirs="${5:-RUNSHOSTSDIRS}[@]"
|
|
local __runsext="${6:-.rs}"
|
|
local __domain __hostname
|
|
local __runsdir __runsfile
|
|
|
|
# chercher le cas échéant dans les répertoire d'hôtes
|
|
if [ -n "$__runshost" ]; then
|
|
splithost "$__runshost" __hostname __domain
|
|
for __runsdir in "${!__runshostsdirs}"; do
|
|
for __runsfile in \
|
|
"$__runsdir/$__runshost/runs/$__scriptfile" \
|
|
"$__runsdir/$__domain/$__hostname/runs/$__scriptfile" \
|
|
"$__runsdir/$__runshost/$__scriptfile" \
|
|
"$__runsdir/$__domain/$__hostname/$__scriptfile"; do
|
|
if [ "${__runsfile%$__runsext}" == "$__runsfile" ]; then
|
|
[ ! -f "$__runsfile" -a -f "$__runsfile$__runsext" ] && __runsfile="$__runsfile$__runsext"
|
|
fi
|
|
if [ -e "$__runsfile" ]; then
|
|
runs_initvars "$__runsfile" "$__runsdir" "$__runsdirpath" "$__scriptfile"
|
|
return 0
|
|
fi
|
|
done
|
|
done
|
|
fi
|
|
# puis chercher dans les répertoires des scripts et des modules
|
|
for __runsdir in "${!__runsscriptsdirs}" "${!__runsmodulesdirs}"; do
|
|
__runsfile="$__runsdir/$__scriptfile"
|
|
if [ "${__runsfile%$__runsext}" == "$__runsfile" ]; then
|
|
[ ! -f "$__runsfile" -a -f "$__runsfile$__runsext" ] && __runsfile="$__runsfile$__runsext"
|
|
fi
|
|
if [ -e "$__runsfile" ]; then
|
|
runs_initvars "$__runsfile" "$__runsdir" "$__runsdir" "$__scriptfile"
|
|
return 0
|
|
fi
|
|
done
|
|
return 1
|
|
}
|
|
|
|
function runs_find_scriptfile_reverse() {
|
|
# Soit le fichier de script $1, exprimée de façon absolue, trouver le
|
|
# fichier parmi les tableaux $3(=RUNSSCRIPTSDIRS), $4(=RUNSMODULESDIRS)
|
|
# et $5(=RUNSHOSTSDIRS), en considérant que le script sera lancé sur l'hôte
|
|
# $2(=$RUNSHOST), puis initialiser les variables RUNSDIR, RUNSSCRIPT,
|
|
# RUNSSCRIPTDIR, RUNSSCRIPTNAME, RUNSDIRPATH et RUNSSCRIPTPATH. Retourner 0
|
|
# en cas de succès, 1 en cas d'échec.
|
|
local __runsscript="$1" __runshost="${2:-$RUNSHOST}"
|
|
local __runsscriptsdirs="${3:-RUNSSCRIPTSDIRS}[@]"
|
|
local __runsmodulesdirs="${4:-RUNSMODULESDIRS}[@]"
|
|
local __runshostsdirs="${5:-RUNSHOSTSDIRS}[@]"
|
|
local __domain __hostname
|
|
local __runsdir __runsfile __prefix
|
|
|
|
# chercher le cas échéant dans les répertoire d'hôtes
|
|
if [ -n "$__runshost" ]; then
|
|
splithost "$__runshost" __hostname __domain
|
|
for __runsdir in "${!__runshostsdirs}"; do
|
|
__prefix="$__runsdir/$__runshost/runs/"
|
|
if [ "${__runsscript#$__prefix}" != "$__runsscript" ]; then
|
|
runs_initvars "$__runsscript" "$__runsdir" "$__prefix" "${__runsscript#$__prefix/}"
|
|
return 0
|
|
fi
|
|
__prefix="$__runsdir/$__domain/$__hostname/runs/"
|
|
if [ "${__runsscript#$__prefix}" != "$__runsscript" ]; then
|
|
runs_initvars "$__runsscript" "$__runsdir" "$__prefix" "${__runsscript#$__prefix/}"
|
|
return 0
|
|
fi
|
|
__prefix="$__runsdir/$__runshost/"
|
|
if [ "${__runsscript#$__prefix}" != "$__runsscript" ]; then
|
|
runs_initvars "$__runsscript" "$__runsdir" "$__prefix" "${__runsscript#$__prefix/}"
|
|
return 0
|
|
fi
|
|
__prefix="$__runsdir/$__domain/$__hostname/"
|
|
if [ "${__runsscript#$__prefix}" != "$__runsscript" ]; then
|
|
runs_initvars "$__runsscript" "$__runsdir" "$__prefix" "${__runsscript#$__prefix/}"
|
|
return 0
|
|
fi
|
|
done
|
|
fi
|
|
# puis chercher dans les répertoires des scripts et des modules
|
|
for __runsdir in "${!__runsscriptsdirs}"; do
|
|
__prefix="$__runsdir/"
|
|
if [ "${__runsscript#$__prefix}" != "$__runsscript" ]; then
|
|
runs_initvars "$__runsscript" "$__runsdir" "$__prefix" "${__runsscript#$__prefix/}"
|
|
return 0
|
|
fi
|
|
done
|
|
for __runsdir in "${!__runsmodulesdirs}"; do
|
|
__prefix="$__runsdir/"
|
|
if [ "${__runsscript#$__prefix}" != "$__runsscript" ]; then
|
|
runs_initvars "$__runsscript" "$__runsdir" "$__prefix" "${__runsscript#$__prefix/}"
|
|
return 0
|
|
fi
|
|
done
|
|
return 1
|
|
}
|
|
|
|
function runs_rscript() {
|
|
# Lancer le fichier $1 comme un script avec les arguments $2..$*. Retourner
|
|
# la valeur de retour du script.
|
|
local state
|
|
local RUNSDIR RUNSSCRIPT RUNSSCRIPTDIR RUNSSCRIPTNAME RUNSDIRPATH RUNSSCRIPTPATH
|
|
local RUNSSCRIPTSDIRS RUNSMODULESDIRS RUNSHOSTSDIRS; __runs_setpath
|
|
|
|
local rscript="$1"; shift
|
|
if [ ! -f "$rscript" ]; then
|
|
eerror "$rscript: fichier introuvable."
|
|
return 123
|
|
fi
|
|
|
|
# trouver runs*dir correspondant à $rscript
|
|
rscript="$(abspath "$rscript")"
|
|
runs_find_scriptfile_reverse "$rscript" "$RUNSHOST" || runs_initvars "$rscript"
|
|
|
|
# puis lancer le script
|
|
RUNSSTORY=("${RUNSSTORY[@]}" "$RUNSSCRIPTPATH")
|
|
state=0
|
|
"$RUNSACTION" "$@" || {
|
|
state=$?
|
|
eerror "$RUNSSCRIPTPATH: Une erreur s'est produite."
|
|
}
|
|
return $state
|
|
}
|
|
|
|
function __runs_iscont() {
|
|
# tester si $1 est une ligne de continuation dans une recette
|
|
[ "${1# }" != "$1" ] && return 0
|
|
[ "${1#$TAB}" != "$1" ] && return 0
|
|
return 1
|
|
}
|
|
|
|
function runs_recipe() {
|
|
# Lancer les scripts de la recette contenue dans le fichier $1. Arrêter au
|
|
# premier script qui est en erreur
|
|
local recipe rcmds rcmd i count rscripts rscript
|
|
|
|
recipe="$(abspath "$1")"
|
|
if [ -d "$recipe" ]; then
|
|
if is_root; then
|
|
if [ -f "$recipe/default.rr" ]; then
|
|
recipe="$recipe/default.rr"
|
|
elif [ -f "$recipe/default" ]; then
|
|
recipe="$recipe/default"
|
|
else
|
|
recipe="$recipe/default.rr"
|
|
fi
|
|
else
|
|
if [ -f "$recipe/userdefault.rr" ]; then
|
|
recipe="$recipe/userdefault.rr"
|
|
elif [ -f "$recipe/userdefault" ]; then
|
|
recipe="$recipe/userdefault"
|
|
else
|
|
recipe="$recipe/userdefault.rr"
|
|
fi
|
|
fi
|
|
fi
|
|
if [ "${recipe%.rr}" == "$recipe" ]; then
|
|
[ ! -f "$recipe" -a -f "$recipe.rr" ] && recipe="$recipe.rr"
|
|
fi
|
|
if [ ! -f "$recipe" ]; then
|
|
eerror "$(ppath "$recipe"): fichier introuvable"
|
|
return 1
|
|
fi
|
|
if array_contains RUNSRECIPES "$recipe"; then
|
|
eerror "$(ppath "$recipe"): inclusion récursive"
|
|
return 1
|
|
fi
|
|
RUNSRECIPES=("${RUNSRECIPES[@]}" "$recipe")
|
|
# lire les ingredients de la recette
|
|
recipe="$(<"$recipe" filter_comment -m)"
|
|
array_from_lines rcmds "$recipe"
|
|
# fusionner les lignes d'ingrédients
|
|
let i=0
|
|
let count=${#rcmds[@]}
|
|
rscript=
|
|
rscripts=()
|
|
while [ $i -lt $count ]; do
|
|
rcmd="${rcmds[$i]}"
|
|
if ! __runs_iscont "$rcmd"; then
|
|
# il faut recommencer une nouvelle commande
|
|
# mais d'abord, traiter l'ancienne commande si nécessaire
|
|
[ -n "$rscript" ] && rscripts=("${rscripts[@]}" "$rscript")
|
|
rscript="$rcmd"
|
|
elif [ -z "$rscript" ]; then
|
|
# nous avons une ligne de continuation mal placée
|
|
ewarn "$rcmd: Ligne de continuation mal placée, elle sera ignorée"
|
|
else
|
|
# nous avons une ligne de continuation
|
|
rscript="$rscript \; $rcmd"
|
|
fi
|
|
let i=$i+1
|
|
[ $i -eq $count -a -n "$rscript" ] && rscripts=("${rscripts[@]}" "$rscript")
|
|
done
|
|
# lancer les ingrédients et s'arrêter à la premier erreur
|
|
for rscript in "${rscripts[@]}"; do
|
|
eval "set -- $rscript"
|
|
if [ "${1#@}" != "$1" ]; then
|
|
# Le caractère @ identifie une recette au lieu d'un script individuel
|
|
local RUNSDIR RUNSSCRIPT RUNSSCRIPTDIR RUNSSCRIPTNAME RUNSDIRPATH RUNSSCRIPTPATH
|
|
local RUNSSCRIPTSDIRS RUNSMODULESDIRS RUNSHOSTSDIRS; __runs_setpath
|
|
recipe="${1#@}"
|
|
if ! runs_find_scriptfile "$recipe" "" "" "" "" ".rr"; then
|
|
eerror "$recipe: fichier introuvable. Vérifiez les valeurs suivantes:
|
|
RUNSSCRIPTSPATH=$RUNSSCRIPTSPATH
|
|
RUNSMODULESPATH=$RUNSMODULESPATH
|
|
RUNSHOSTSPATH=$RUNSHOSTSPATH
|
|
RUNSHOST=$RUNSHOST"
|
|
return 123
|
|
fi
|
|
etitle "$1" runs_recipe "$RUNSSCRIPT" || return
|
|
else
|
|
etitle "$1" runs_rscriptpath "$@" || return
|
|
fi
|
|
done
|
|
return 0
|
|
}
|
|
|
|
function runs_rscriptpath() {
|
|
# Lancer le script $1 avec les arguments $2..$*. Le script est cherché dans
|
|
# les répertoires de RUNSSCRIPTSPATH. Retourner 123 si le script n'est pas
|
|
# trouvé, sinon retourner la valeur de retour du script.
|
|
local state
|
|
local RUNSDIR RUNSSCRIPT RUNSSCRIPTDIR RUNSSCRIPTNAME RUNSDIRPATH RUNSSCRIPTPATH
|
|
local RUNSSCRIPTSDIRS RUNSMODULESDIRS RUNSHOSTSDIRS; __runs_setpath
|
|
if ! runs_find_scriptfile "$1"; then
|
|
eerror "$1: fichier introuvable. Vérifiez les valeurs suivantes:
|
|
RUNSSCRIPTSPATH=$RUNSSCRIPTSPATH
|
|
RUNSMODULESPATH=$RUNSMODULESPATH
|
|
RUNSHOSTSPATH=$RUNSHOSTSPATH
|
|
RUNSHOST=$RUNSHOST"
|
|
return 123
|
|
fi
|
|
shift
|
|
|
|
RUNSSTORY=("${RUNSSTORY[@]}" "$RUNSSCRIPTPATH")
|
|
state=0
|
|
"$RUNSACTION" "$@" || {
|
|
state=$?
|
|
eerror "$RUNSSCRIPTPATH: Une erreur s'est produite."
|
|
}
|
|
return $state
|
|
}
|
|
|
|
function runs_recipepath() {
|
|
# Lancer la recette $1. Le fichier de recette est cherché dans les
|
|
# répertoires de RUNSSCRIPTSPATH. Retourner 123 si le fichier de recette n'a
|
|
# pas été trouvé, sinon retourner la valeur de retour de runs_recipe()
|
|
local RUNSDIR RUNSSCRIPT RUNSSCRIPTDIR RUNSSCRIPTNAME RUNSDIRPATH RUNSSCRIPTPATH
|
|
local RUNSSCRIPTSDIRS RUNSMODULESDIRS RUNSHOSTSDIRS; __runs_setpath
|
|
if ! runs_find_scriptfile "$1" "" "" "" "" ".rr"; then
|
|
eerror "$1: fichier introuvable. Vérifiez les valeurs suivantes:
|
|
RUNSSCRIPTSPATH=$RUNSSCRIPTSPATH
|
|
RUNSMODULESPATH=$RUNSMODULESPATH
|
|
RUNSHOSTSPATH=$RUNSHOSTSPATH
|
|
RUNSHOST=$RUNSHOST"
|
|
return 123
|
|
fi
|
|
|
|
runs_recipe "$RUNSSCRIPT"
|
|
}
|
|
|
|
################################################################################
|
|
# Moteur de script
|
|
|
|
function runs_init() {
|
|
RUNSSRCDIR="${1:-$scriptdir}" # répertoire d'où sont copiés les scripts
|
|
RUNSACTION=runs_action_run
|
|
# informations sur le système
|
|
RUNSHOST="$MYHOST"
|
|
RUNSACTUALSYSNAME=("${MYSYSNAME[@]}")
|
|
RUNSACTUALSYSDIST=("${MYSYSDIST[@]}")
|
|
RUNSACTUALSYSVER=("${MYSYSVER[@]}")
|
|
RUNSACTUALBITS="$MYBITS"
|
|
RUNSEXPORTDIR= # avec --export, répertoire de base de l'export
|
|
RUNSROOTDIR= # avec --export, répertoire correspondant à la racine
|
|
RUNSWORKDIR=
|
|
RUNSUPDATERECIPE=1 # faut-il rajouter la ligne de recette lors d'un export
|
|
RUNSCONFFILES= # fichier de configuration qui ont été chargés
|
|
# liste des varibles définies
|
|
RUNSVARS=()
|
|
# parmis les variables de RUNSVARS, liste de celles qui sont des tableaux
|
|
RUNSARRAYS=()
|
|
# parmis les variables de RUNSVARS, liste de celles qui sont des indirections
|
|
RUNSVARSINDIRECT=()
|
|
# liste des références définies
|
|
RUNSREFS=()
|
|
# recettes qui ont déjà été lancées, pour éviter les inclusions récursives
|
|
RUNSRECIPES=()
|
|
# scripts qui ont déjà été lancés, pour la commande after
|
|
RUNSSTORY=()
|
|
# flags valides et ceux qui ont été activés
|
|
RUNSVALIDCONFS=(root local proxy nolang)
|
|
RUNSCONFS=()
|
|
# Faut-il réinitialiser les scripts qui se basent sur shouldrun/setdone
|
|
RUNSRESET=
|
|
}
|
|
|
|
function runs_initdomains() {
|
|
# Si ce n'est pas déjà le cas, initialiser RUNSDOMAINS en fonction de
|
|
# /etc/resolv.conf
|
|
[ -n "${RUNSDOMAINS[*]}" ] && return
|
|
local domains="$(awk '$1 == "search" { $1 = ""; print }' /etc/resolv.conf)"
|
|
eval "RUNSDOMAINS=($domains)"
|
|
}
|
|
|
|
function runs_inithost() {
|
|
[ -n "$1" ] && RUNSHOST="$1"
|
|
}
|
|
|
|
function runs_initsysinfos() {
|
|
local RUNSSCRIPTSDIRS RUNSMODULESDIRS RUNSHOSTSDIRS; __runs_setpath
|
|
local sysname="$1" sysdist="$2" sysver="$3" bits="$4"
|
|
|
|
# on a spécifié le nombre de bits
|
|
[ -n "$bits" ] && MYBITS="$bits"
|
|
|
|
if [ -n "$sysname" -o -n "$sysdist" -o -n "$sysver" ]; then
|
|
# on a spécifié un système en ligne de commande
|
|
ensure_sysinfos sysname sysdist sysver
|
|
else
|
|
# Si le fichier sysinfos.conf existe dans le répertoire d'hôte, y
|
|
# prendre les valeurs
|
|
local sysinfos
|
|
if sysinfos="$(runs_find_hostfile sysinfos.conf)"; then
|
|
sysname=()
|
|
sysdist=()
|
|
sysver=()
|
|
bits=
|
|
source "$sysinfos"
|
|
[ -n "$bits" ] && MYBITS="$bits"
|
|
if [ -n "$sysname" -o -n "$sysdist" -o -n "$sysver" ]; then
|
|
ensure_sysinfos sysname sysdist sysver
|
|
else
|
|
# aucune modification n'a été faite par le fichier de
|
|
# configuration. ne pas modifier les valeurs courantes
|
|
return
|
|
fi
|
|
else
|
|
# aucun fichier de configuration. ne pas modifier les valeurs
|
|
# courantes
|
|
return
|
|
fi
|
|
fi
|
|
MYSYSNAME=("${sysname[@]}")
|
|
MYSYSDIST=("${sysdist[@]}")
|
|
MYSYSVER=("${sysver[@]}")
|
|
MYBITS="$bits"
|
|
}
|
|
|
|
function runs_initworkdir() {
|
|
local runsexportdir="$1" runsworkdir="$2" scriptdir="${3:-$scriptdir}"
|
|
if [ -z "$runsexportdir" -a "$RUNSACTION" == runs_action_export ]; then
|
|
# en mode export, il faut définir runsexportdir
|
|
ac_set_tmpdir runsexportdir
|
|
fi
|
|
if [ -n "$runsexportdir" ]; then
|
|
if [ -n "$runsworkdir" ]; then
|
|
ewarn "Avec --export, la valeur de --runsworkdir est ignorée"
|
|
fi
|
|
RUNSEXPORTDIR="$(abspath "$runsexportdir")"
|
|
RUNSROOTDIR="$RUNSEXPORTDIR/root"
|
|
RUNSWORKDIR="$RUNSEXPORTDIR/work"
|
|
mkdir -p "$RUNSEXPORTDIR"
|
|
mkdir -p "$RUNSROOTDIR"
|
|
mkdir -p "$RUNSWORKDIR"
|
|
|
|
if [ "$RUNSACTION" == "runs_action_export" ]; then
|
|
# préparer les fichiers pour l'export
|
|
>"$RUNSEXPORTDIR/varsfile"
|
|
>"$RUNSEXPORTDIR/localuser"
|
|
>"$RUNSEXPORTDIR/localroot"
|
|
>"$RUNSEXPORTDIR/remoteuser"
|
|
>"$RUNSEXPORTDIR/remoteroot"
|
|
|
|
# synchronisation ulib
|
|
# comme on copie runs et uinst, il faut copier ulib et pyulib comme pour nutools: dans le répertoire lib/
|
|
urequire ulib pyulib/pyulib
|
|
mkdir -p "$RUNSEXPORTDIR/lib"
|
|
ulibsync "$RUNSEXPORTDIR/lib"
|
|
pyulibsync "$RUNSEXPORTDIR/lib"
|
|
|
|
# copie runs, uinst
|
|
cp "$RUNSSRCDIR/runs" "$RUNSEXPORTDIR"
|
|
cp "$RUNSSRCDIR/uinst" "$RUNSEXPORTDIR"
|
|
|
|
# faire les scripts
|
|
args_def="args=($(quoted_args ./runs --runsscriptspath "$RUNSSCRIPTSPATH" --runsmodulespath "$RUNSMODULESPATH" --runshostspath "$RUNSHOSTSPATH" --runsexportdir . --runsvarsfile varsfile -h "$RUNSHOST" ${RUNSRESET:+-z}))"
|
|
echo '#!/bin/bash
|
|
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
|
|
cd "$(dirname "$0")"
|
|
'"$args_def"'
|
|
[ -s localuser ] && { "${args[@]}" -r localuser || exit 1; }
|
|
[ -s localroot ] && { "${args[@]}" -r localroot -s || exit 1; }
|
|
exit 0
|
|
' >"$RUNSEXPORTDIR/runs-local"
|
|
echo '#!/bin/bash
|
|
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
|
|
cd "$(dirname "$0")"
|
|
'"$args_def"'
|
|
if [ -s remote ]; then
|
|
[ -f remote-needs-root ] && args=("${args[@]}" -s)
|
|
"${args[@]}" -r remote || exit 1
|
|
fi
|
|
exit 0
|
|
' >"$RUNSEXPORTDIR/runs-remote"
|
|
chmod +x "$RUNSEXPORTDIR/runs-local" "$RUNSEXPORTDIR/runs-remote"
|
|
else
|
|
# corriger RUNS*PATH à partir de RUNSROOTDIR
|
|
function __runs_add_runsroot() { echo "$RUNSROOTDIR$1"; }
|
|
local runspath runsdirs
|
|
for runspath in RUNSSCRIPTSPATH RUNSMODULESPATH RUNSHOSTSPATH; do
|
|
array_from_path runsdirs "${!runspath}"
|
|
array_map runsdirs abspath
|
|
array_map runsdirs __runs_add_runsroot
|
|
set_var "$runspath" "$(array_join runsdirs :)"
|
|
done
|
|
# XXX quelles autres variables doivent être corrigées?
|
|
fi
|
|
elif [ -n "$runsworkdir" ]; then
|
|
RUNSWORKDIR="$runsworkdir"
|
|
else
|
|
ac_set_tmpdir RUNSWORKDIR
|
|
fi
|
|
}
|
|
|
|
function runs_after_export() {
|
|
# après l'export, initialiser varsfile avec les valeurs qu'il faut garder
|
|
# entre le déploiement local et le déploiement distant.
|
|
if [ "$RUNSACTION" == runs_action_export ]; then
|
|
set_array_cmd RUNSSTORY >>"$RUNSEXPORTDIR/varsfile"
|
|
fi
|
|
}
|
|
|
|
function __runs_is_runsscript() {
|
|
if [ -f "$1" ]; then
|
|
quietgrep "^script:" "$1"
|
|
elif [ -d "$1" ]; then
|
|
[ -f "$1/.udir" ]
|
|
else
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
function runs_check_runsscript() {
|
|
if [ -f "$1" ] && ! __runs_is_runsscript "$1"; then
|
|
eerror "$1: ce n'est pas un fichier de script valide: il manque la ligne 'script:'"
|
|
return 1
|
|
elif [ -d "$1" ]; then
|
|
return 0
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
function __runs_check_varname() {
|
|
if [ "${1#RUNS}" != "$1" -o "${1#_}" != "$1" ]; then
|
|
ewarn "Variable invalide: $1. Cette valeur a été ignorée"
|
|
return 1
|
|
fi
|
|
return 0
|
|
}
|
|
function __runs_check_notref() {
|
|
if array_contains RUNSREFS "$1"; then
|
|
ewarn "Vous ne pouvez pas modifier la référence $1. La valeur sera ignorée"
|
|
return 1
|
|
fi
|
|
return 0
|
|
}
|
|
function __runs_splitref() {
|
|
if [[ "$1" == *=* ]]; then
|
|
set_var "${2:-__name}" "${1%%=*}"
|
|
set_var "${3:-__value}" "${1#*=}"
|
|
else
|
|
set_var "${2:-__name}" "$1"
|
|
set_var "${3:-__value}" "$1"
|
|
fi
|
|
}
|
|
|
|
function runs_var() {
|
|
# Initialiser les variables selon les directives données en ligne de
|
|
# commande.
|
|
# Les arguments peuvent être une suite de définitions de la forme
|
|
# 'scalar=value', 'scalar!=name', 'array+=value', 'array-=value' ou
|
|
# 'array@=name'.
|
|
# Sinon, le *dernier* argument peut-être de l'une des formes suivantes:
|
|
# 'array value0 [value1...]' pour initialiser un tableau,
|
|
# 'array+ value0 [value1...]' pour ajouter des valeurs à un tableau,
|
|
# 'array- value0 [value1...]' pour enlever des valeurs à un tableau.
|
|
# Les formes 'scalar!=value' et 'array@=value' sont des indirections et
|
|
# permettent d'initialiser la variable avec la valeur d'une autre
|
|
# variable. L'avantage est que la résolution de la valeur est faite
|
|
# uniquement lors de l'appel de cette fonction, ce qui est utile avec des
|
|
# fonction comme 'after -r'
|
|
local __name __value
|
|
# variables scalaires ou manipulation de tableaux
|
|
while [ -n "$1" ]; do
|
|
if [[ "$1" == *+=* ]]; then
|
|
__name="${1%%+=*}"
|
|
__value="${1#*+=}"
|
|
if __runs_check_varname "$__name" && __runs_check_notref "$__name"; then
|
|
array_set RUNSVARS "$__name"
|
|
array_set RUNSARRAYS "$__name"
|
|
array_del RUNSVARSINDIRECT "$__name"
|
|
array_add "$__name" "$__value"
|
|
fi
|
|
elif [[ "$1" == *-=* ]]; then
|
|
__name="${1%%-=*}"
|
|
__value="${1#*-=}"
|
|
if __runs_check_varname "$__name" && __runs_check_notref "$__name"; then
|
|
array_set RUNSVARS "$__name"
|
|
array_set RUNSARRAYS "$__name"
|
|
array_del RUNSVARSINDIRECT "$__name"
|
|
array_del "$__name" "$__value"
|
|
fi
|
|
elif [[ "$1" == *!=* ]]; then
|
|
__name="${1%%!=*}"
|
|
__value="${1#*!=}"
|
|
if __runs_check_varname "$__name" && __runs_check_notref "$__name"; then
|
|
array_set RUNSVARS "$__name"
|
|
array_del RUNSARRAYS "$__name"
|
|
array_set RUNSVARSINDIRECT "$__name"
|
|
set_var "$__name" "$__value"
|
|
fi
|
|
elif [[ "$1" == *@=* ]]; then
|
|
__name="${1%%@=*}"
|
|
__value="${1#*@=}"
|
|
if __runs_check_varname "$__name" && __runs_check_notref "$__name"; then
|
|
array_set RUNSVARS "$__name"
|
|
array_set RUNSARRAYS "$__name"
|
|
array_set RUNSVARSINDIRECT "$__name"
|
|
set_var "$__name" "$__value"
|
|
fi
|
|
elif [[ "$1" == *=* ]]; then
|
|
__name="${1%%=*}"
|
|
__value="${1#*=}"
|
|
if __runs_check_varname "$__name" && __runs_check_notref "$__name"; then
|
|
array_set RUNSVARS "$__name"
|
|
array_del RUNSARRAYS "$__name"
|
|
array_del RUNSVARSINDIRECT "$__name"
|
|
set_var "$__name" "$__value"
|
|
fi
|
|
else
|
|
break
|
|
fi
|
|
[ -n "$RUNSVARDESC" ] && set_var "RUNSVARDESC_$__name" "$RUNSVARDESC"
|
|
shift
|
|
done
|
|
# variables tableau
|
|
if [ -n "$1" ]; then
|
|
__name="$1"; shift
|
|
if __runs_check_varname "$__name" && __runs_check_notref "$__name"; then
|
|
if [ "${__name%+}" != "$__name" ]; then
|
|
__name="${__name%+}"
|
|
for __value in "$@"; do
|
|
array_add "$__name" "$__value"
|
|
done
|
|
elif [ "${__name%-}" != "$__name" ]; then
|
|
__name="${__name%-}"
|
|
for __value in "$@"; do
|
|
array_del "$__name" "$__value"
|
|
done
|
|
else
|
|
set_array "$__name" @ "$@"
|
|
fi
|
|
# Placer $__name dans les tableau après qu'il aie été corrigé
|
|
# si par exemple il se terminer par '+' ou '-'
|
|
array_set RUNSVARS "$__name"
|
|
array_set RUNSARRAYS "$__name"
|
|
array_del RUNSVARSINDIRECT "$__name"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
function runs_conf() {
|
|
# Activer les flags $*
|
|
for __conf in "$@"; do
|
|
if array_contains RUNSVALIDCONFS "$__conf"; then
|
|
array_set RUNSCONFS "$__conf"
|
|
else
|
|
ewarn "Flag inconnu: $__conf. Il sera ignoré"
|
|
fi
|
|
done
|
|
}
|
|
|
|
function runs_indref() {
|
|
# fonction de convenance pour créer des références $3..* avec le fichier de
|
|
# configuration $1 et les variables $2
|
|
local __sconf="$1" __vars="$2"; shift; shift
|
|
ref -s "$__sconf" -v "$__vars" "$@"
|
|
}
|
|
function runs_refcerts() {
|
|
# fonction de convenance pour créer une référence à un répertoire contenant
|
|
# des certificats mentionnés dans le fichier de configuration $1. Si les
|
|
# références $2..* ne sont pas mentionnées, la variable certsdir dans le
|
|
# fichier de configuration est utilisée.
|
|
local __sconf="$1"; shift
|
|
runs_indref "$__sconf" ca,cert,key -V certsdir "$@"
|
|
}
|
|
function runs_refapacheconfig() {
|
|
# fonction de convenance pour créer les références à un répertoire de
|
|
# configuration pour apache.
|
|
# USAGE: refapacheconfig autoconfdir=path/to/autoconfdir [certsdir=[path/to/certsdir]]
|
|
# - autoconfdir= est requis et permet de définir à la fois la variable qui
|
|
# contiendra la référence ainsi que le répertoire à référencer.
|
|
# - certsdir= est optionel. Si cet argument est spécifié sous la forme
|
|
# certsdir=path/to/certsdir, il permet de définir à la fois la variable qui
|
|
# contiendra la référence ainsi que le répertoire à référencer. Si
|
|
# l'argument est spécifié sous la forme certsdir=, il permet de définir la
|
|
# variable qui contiendra la référence. C'est cette variable qui sera lue
|
|
# dans les fichiers de configuration. Si l'argument n'est pas spécifié, on
|
|
# considère que l'argument 'certsdir=' a été utilisé.
|
|
:
|
|
#local -a __args
|
|
#parse_opts + \
|
|
# @ __args -- "$@" && set -- "${__args[@]}" || die "$__args"
|
|
}
|
|
|
|
function runs_set_lang() {
|
|
# Charger la valeur de LANG depuis l'environnement. La variable LANG est
|
|
# initialisée
|
|
if ! array_contains RUNSCONFS nolang; then
|
|
if check_sysinfos -d debianlike; then
|
|
eval "$(LANG=
|
|
source_ifexists /etc/default/locale
|
|
set_var_cmd LANG "$LANG"
|
|
)"
|
|
fi
|
|
export LANG
|
|
fi
|
|
}
|
|
|
|
function runs_set_proxy() {
|
|
# Charger la valeur du proxy depuis l'environnement. Les variables
|
|
# http_proxy, ftp_proxy et no_proxy sont initialisées
|
|
if array_contains RUNSCONFS proxy; then
|
|
if check_sysinfos -d debianlike; then
|
|
eval "$(http_proxy=; ftp_proxy=; no_proxy=
|
|
source_ifexists /etc/environment
|
|
set_var_cmd http_proxy "$http_proxy"
|
|
set_var_cmd ftp_proxy "$ftp_proxy"
|
|
set_var_cmd no_proxy "$no_proxy"
|
|
)"
|
|
fi
|
|
export http_proxy ftp_proxy no_proxy
|
|
fi
|
|
}
|
|
|
|
function runs_check_confs() {
|
|
# Vérifier l'état courant par rapport aux flags
|
|
if array_contains RUNSCONFS root; then
|
|
is_root || die "Ce script requière d'être lancé en root (essayer avec l'option -s)"
|
|
fi
|
|
}
|
|
|
|
function runs_after() {
|
|
# Vérifier que ce script est lancé après le scriptpath $1, par rapport à
|
|
# RUNSSTORY
|
|
local -a __args
|
|
local runslevel=0
|
|
parse_opts + \
|
|
-r,--run runslevel \
|
|
@ __args -- "$@" && set -- "${__args[@]}" || die "$__args"
|
|
|
|
# Le traitement est fait en fonction de runslevel
|
|
if [ $runslevel -eq 0 ]; then
|
|
# sans l'option -r, on ne fait que vérifier que les scriptpaths
|
|
# correspondant aux arguments ont déjà été lancés. On peut spécifier
|
|
# autant de scriptpaths que nécessaire, puisque que des arguments ne
|
|
# sont pas nécessaires
|
|
local scriptpath
|
|
for scriptpath in "$@"; do
|
|
if ! array_contains RUNSSTORY "$scriptpath"; then
|
|
eerror "Ce script requière d'être lancé après $scriptpath"
|
|
return 1
|
|
fi
|
|
done
|
|
return 0
|
|
fi
|
|
|
|
# Protéger la liste actuelle des variables en en faisant une copie
|
|
# locale. En effet, cette liste sera supprimée à la fin de l'invocation
|
|
# récursive avec -r. Protéger également les valeurs de variables en en
|
|
# faisant une copie locale, puis fusionner avec les valeurs saisies sur la
|
|
# ligne de commande.
|
|
# Attention! si on veut utiliser dans les paramètre du script dépendant une
|
|
# valeur d'une variable déjà définie, il faut utiliser une indirection
|
|
# var!=othervar, parce que la valeur définitive est calculée dans cette
|
|
# fonction, et non avant son appel!
|
|
local __var __tmp
|
|
for __var in "${RUNSVARS[@]}"; do
|
|
if array_contains RUNSARRAYS "$__var"; then
|
|
eval "array_copy __tmp $__var; local -a $__var; array_copy $__var __tmp"
|
|
else
|
|
eval "set_var __tmp \"\${!__var}\"; local $__var; $__var=\"\$__tmp\""
|
|
fi
|
|
done
|
|
runs_clvars "${RUNSCLVARS[@]}"
|
|
runs_indvars
|
|
# Etendre tout de suite les indirections var!=othervar et array@=otherarray,
|
|
# parce que la valeur qui doit être prise en compte est la valeur actuelle.
|
|
local -a __args
|
|
local __arg __name __value
|
|
__args=("$1"); shift
|
|
for __arg in "$@"; do
|
|
if [[ "$__arg" == *!=* ]]; then
|
|
__name="${__arg%%!=*}"
|
|
__value="${__arg#*!=}"
|
|
__args=("${__args[@]}" "$__name=$(quoted_arg "${!__value}")")
|
|
elif [[ "$__arg" == *@=* ]]; then
|
|
__name="${__arg%%@=*}"
|
|
__value="${__arg#*@=}[@]"
|
|
__args=("${__args[@]}" \; "$__name")
|
|
for __var in "${!__value}"; do
|
|
__args=("${__args[@]}" "$__var")
|
|
done
|
|
__args=("${__args[@]}" \;)
|
|
else
|
|
__args=("${__args[@]}" "$__arg")
|
|
fi
|
|
done
|
|
set -- "${__args[@]}"
|
|
|
|
if [ $runslevel -eq 1 ]; then
|
|
# Avec une seule option -r, si le scriptpath a déjà été lancé, on ne
|
|
# fait rien. Sinon, le lancer maintenant avec les arguments $2..$*
|
|
# Ne pas mettre à jour la ligne de recette lors d'un export pour éviter
|
|
# de lancer le script deux fois
|
|
local RUNSUPDATERECIPE=
|
|
if ! array_contains RUNSSTORY "$1"; then
|
|
etitle "Lancement du script dépendant $1" \
|
|
runs_rscriptpath "$@"
|
|
fi
|
|
return 0
|
|
else
|
|
# Avec deux options -r et plus, forcer le lancer de scriptpath avec les
|
|
# arguments $2..$*, même s'il a déjà été lancé auparavant.
|
|
# Ne pas mettre à jour la ligne de recette lors d'un export pour éviter
|
|
# de lancer le script deux fois
|
|
local RUNSUPDATERECIPE=
|
|
etitle "Lancement du script dépendant $1" \
|
|
runs_rscriptpath "$@"
|
|
fi
|
|
}
|
|
|
|
function runs_clvars() {
|
|
# Traiter les spécifications de variables données en ligne de commande ou
|
|
# dans un fichier de recettes
|
|
local __vars
|
|
__vars=()
|
|
while [ -n "$1" ]; do
|
|
if [ "$1" == ";" ]; then
|
|
runs_var "${__vars[@]}"
|
|
__vars=()
|
|
else
|
|
__vars=("${__vars[@]}" "$1")
|
|
fi
|
|
shift
|
|
done
|
|
[ -n "${__vars[*]}" ] && runs_var "${__vars[@]}"
|
|
}
|
|
|
|
function runs_indvars() {
|
|
# Résoudre les valeurs effectives des variables qui sont des indirections
|
|
local __var __ind
|
|
for __var in "${RUNSVARSINDIRECT[@]}"; do
|
|
if array_contains RUNSARRAYS "$__var"; then
|
|
# tableau
|
|
array_copy "$__var" "${!__var}"
|
|
else
|
|
# variable scalaire
|
|
__ind="${!__var}"
|
|
set_var "$__var" "${!__ind}"
|
|
fi
|
|
done
|
|
RUNSVARSINDIRECT=()
|
|
}
|
|
|
|
function runs_clvars_cmd() {
|
|
# écrire la ligne de recette correspondant au script $1 et aux variables
|
|
# $2..$*
|
|
local __vars __prefix
|
|
__vars=()
|
|
while [ -n "$1" ]; do
|
|
if [ "$1" == ";" ]; then
|
|
echo "$__prefix$(quoted_args "${__vars[@]}")"
|
|
__vars=()
|
|
__prefix=" "
|
|
else
|
|
__vars=("${__vars[@]}" "$1")
|
|
fi
|
|
shift
|
|
done
|
|
[ -n "${__vars[*]}" ] && echo "$__prefix$(quoted_args "${__vars[@]}")"
|
|
}
|
|
|
|
function runs_loadconfs() {
|
|
local __conffile __path __done
|
|
RUNSCONFFILES=()
|
|
if [ -n "$RUNSDIR" ]; then
|
|
__path="$RUNSSCRIPT"
|
|
while [ -n "$__path" ]; do
|
|
__path="$(dirname "$__path")"
|
|
__conffile="$__path/runs.conf"
|
|
if [ -f "$__conffile" ]; then
|
|
RUNSCONFFILES=("$__conffile" "${RUNSCONFFILES[@]}")
|
|
fi
|
|
[ "$__path" == "$RUNSDIR" ] && __path=
|
|
done
|
|
fi
|
|
|
|
for __conffile in "${RUNSCONFFILES[@]}"; do
|
|
source "$__conffile"
|
|
done
|
|
}
|
|
|
|
function runs_clearvars() {
|
|
local __var
|
|
for __var in "${RUNSVARS[@]}"; do
|
|
eval "unset $__var"
|
|
done
|
|
}
|
|
|
|
function runs_action_desc() {
|
|
local -a RUNSVARS RUNSARRAYS RUNSVARSINDIRECT
|
|
local -a RUNSCLVARS RUNSCONFS RUNSCONFFILES
|
|
local RUNSVARDESC __state
|
|
|
|
function desc() { eecho "$(ppath "$RUNSSCRIPT"): $*"; exit 0; }
|
|
function unsupported_system() { runs_unsupported_system "$@"; }
|
|
function require_sysinfos() { runs_require_sysinfos "$@"; }
|
|
function vardesc() { RUNSVARDESC="$*"; }
|
|
function var() { runs_var "$@"; RUNSVARDESC=; }
|
|
function conf() { runs_conf "$@"; }
|
|
function after() {
|
|
local scriptpath
|
|
for scriptpath in "$@"; do
|
|
einfo "Ce script doit être lancé après $scriptpath"
|
|
done
|
|
}
|
|
function ref() {
|
|
local -a __args
|
|
parse_opts + \
|
|
-r,--required,-m,--mandatory '$:' \
|
|
-f,--required-file '$:' \
|
|
-d,--required-dir '$:' \
|
|
-s:,--sconf: '$:' \
|
|
--rs,--rsconf,--required-sconf '$:' \
|
|
-V:,--refvar: '$:' \
|
|
-v:,--vars: '$:' \
|
|
-l:,--lconf: '$:' \
|
|
--force '$:' \
|
|
--copy-links '$:' \
|
|
--with-vcs '$:' \
|
|
@ __args -- "$@" && set -- "${__args[@]}" || die "$__args"
|
|
runs_var "$@"
|
|
RUNSVARDESC=
|
|
local __name __value; __runs_splitref "$1" __name __value
|
|
array_add RUNSREFS "$__name"
|
|
}
|
|
function indref() { runs_indref "$@"; }
|
|
function refcerts() { runs_refcerts "$@"; }
|
|
function refapacheconfig() { runs_refapacheconfig "$@"; }
|
|
function out() { runs_var "$@"; }
|
|
function script:() {
|
|
eecho "(pas de description)"
|
|
exit 0
|
|
}
|
|
|
|
runs_check_runsscript "$RUNSSCRIPT" || die
|
|
runs_loadconfs
|
|
(source "$RUNSSCRIPT"); __state=$?
|
|
runs_clearvars
|
|
return $__state
|
|
}
|
|
|
|
function runs_action_dump() {
|
|
local -a RUNSVARS RUNSARRAYS RUNSVARSINDIRECT
|
|
local -a RUNSCLVARS RUNSCONFS RUNSCONFFILES
|
|
local RUNSVARDESC __state
|
|
|
|
RUNSCLVARS=("$@")
|
|
|
|
function desc() { eecho "$(ppath "$RUNSSCRIPT"): $*"; }
|
|
function unsupported_system() { runs_unsupported_system "$@"; }
|
|
function require_sysinfos() { runs_require_sysinfos "$@"; }
|
|
function vardesc() { RUNSVARDESC="$*"; }
|
|
function var() { runs_var "$@"; RUNSVARDESC=; }
|
|
function conf() { runs_conf "$@"; }
|
|
function after() { :; }
|
|
function ref() {
|
|
local -a __args
|
|
parse_opts + \
|
|
-r,--required,-m,--mandatory '$:' \
|
|
-f,--required-file '$:' \
|
|
-d,--required-dir '$:' \
|
|
-s:,--sconf: '$:' \
|
|
--rs,--rsconf,--required-sconf '$:' \
|
|
-V:,--refvar: '$:' \
|
|
-v:,--vars: '$:' \
|
|
-l:,--lconf: '$:' \
|
|
--force '$:' \
|
|
--copy-links '$:' \
|
|
--with-vcs '$:' \
|
|
@ __args -- "$@" && set -- "${__args[@]}" || die "$__args"
|
|
runs_var "$@"
|
|
RUNSVARDESC=
|
|
local __name __value; __runs_splitref "$1" __name __value
|
|
array_add RUNSREFS "$__name"
|
|
}
|
|
function indref() { runs_indref "$@"; }
|
|
function refcerts() { runs_refcerts "$@"; }
|
|
function refapacheconfig() { runs_refapacheconfig "$@"; }
|
|
function out() { runs_var "$@"; }
|
|
function script:() {
|
|
runs_set_lang
|
|
runs_set_proxy
|
|
runs_clvars "${RUNSCLVARS[@]}"
|
|
runs_indvars
|
|
|
|
local __var __desc __values __count
|
|
for __var in "${RUNSVARS[@]}"; do
|
|
__desc="RUNSVARDESC_$__var"
|
|
[ -n "${!__desc}" ] && eecho "${COULEUR_BLEUE}$__var${COULEUR_NORMALE}: ${!__desc}"
|
|
|
|
__values="$__var[@]"
|
|
eval "__count=\"\${#$__var[@]}\""
|
|
if [ "$__count" -eq 1 ]; then
|
|
# variable scalaire
|
|
eecho "$__var=$(quoted_args "${!__values}")"
|
|
else
|
|
# variable tableau
|
|
eecho "$__var=($(quoted_args "${!__values}"))"
|
|
fi
|
|
done
|
|
exit 0
|
|
}
|
|
|
|
runs_check_runsscript "$RUNSSCRIPT" || die
|
|
runs_loadconfs
|
|
(source "$RUNSSCRIPT"); __state=$?
|
|
runs_clearvars
|
|
return $__state
|
|
}
|
|
|
|
function runs_action_run() {
|
|
local -a RUNSVARS RUNSARRAYS RUNSVARSINDIRECT
|
|
local -a RUNSCLVARS RUNSCONFS RUNSCONFFILES
|
|
local RUNSVARDESC __state
|
|
|
|
RUNSCLVARS=("$@")
|
|
|
|
function desc() { :; }
|
|
function unsupported_system() { runs_unsupported_system "$@"; }
|
|
function require_sysinfos() { runs_require_sysinfos "$@"; }
|
|
function vardesc() { RUNSVARDESC="$*"; }
|
|
function var() { runs_var "$@"; RUNSVARDESC=; }
|
|
function conf() { runs_conf "$@"; }
|
|
function after() { runs_after "$@" || exit 1; }
|
|
function ref() {
|
|
local -a __args
|
|
local __ref __name __value __found __required __rdir __rfile __rsconf
|
|
local __shellconfs __shellconf __refvarname=refdir __refvar
|
|
local __tmpconf __wildconf
|
|
# ignorer les options -v, -l et leur argument
|
|
parse_opts + \
|
|
-r,--required,-m,--mandatory __required=1 \
|
|
-f,--required-file '$__required=1; __rfile=1' \
|
|
-d,--required-dir '$__required=1; __rdir=1' \
|
|
-s:,--sconf: __shellconf= \
|
|
--rs,--rsconf,--required-sconf __rsconf=1 \
|
|
-V:,--refvar: __refvarname= \
|
|
-v:,--vars: '$:' \
|
|
-l:,--lconf: '$:' \
|
|
--force '$:' \
|
|
--copy-links '$:' \
|
|
--with-vcs '$:' \
|
|
@ __args -- "$@" && set -- "${__args[@]}" || die "$__args"
|
|
|
|
if [ -n "$__shellconf" ]; then
|
|
splitwcs "$__shellconf" __tmpconf __wildconf
|
|
[ -n "$__wildconf" ] && __shellconf="$__tmpconf"
|
|
if [ -e "$__shellconf" -a "${__shellconf#/}" != "$__shellconf" ]; then
|
|
# un chemin absolu _existant_, le garder tel quel
|
|
:
|
|
elif withpath "$__shellconf" && [ -e "$RUNSSCRIPTDIR/$__shellconf" ]; then
|
|
# d'abord dans le répertoire du script
|
|
__shellconf="$RUNSSCRIPTDIR/$__shellconf"
|
|
elif __tmpconf="$(runs_find_datafile "$__shellconf" "" "$RUNSSCRIPTDIR")"; then
|
|
# puis chercher dans RUNS*DIRS
|
|
__shellconf="$__tmpconf"
|
|
fi
|
|
if [ ! -e "$__shellconf" ]; then
|
|
if [ -n "$__rsconf" ]; then
|
|
die "$__shellconf: fichier introuvable"
|
|
else
|
|
ewarn "$__shellconf: fichier introuvable"
|
|
fi
|
|
fi
|
|
[ -n "$__wildconf" ] && __shellconf="$__shellconf/$__wildconf"
|
|
|
|
if [ -z "$*" ]; then
|
|
# Si aucun argument n'est spécifié, essayer de prendre la
|
|
# configuration dans le fichier $__shellconf
|
|
|
|
__runs_check_varname "$__refvarname" || die
|
|
set_var "$__refvarname" ""
|
|
|
|
splitwcs "$__shellconf" __tmpconf __wildconf
|
|
if [ -n "$__wildconf" ]; then
|
|
array_lsall __shellconfs "$__tmpconf" "$__wildconf"
|
|
else
|
|
__shellconfs=("$__shellconf")
|
|
fi
|
|
__args=()
|
|
for __tmpconf in "${__shellconfs[@]}"; do
|
|
[ -f "$__tmpconf" ] || {
|
|
eerror "$__tmpconf: fichier introuvable. Il a été ignoré"
|
|
continue
|
|
}
|
|
__refvar="$(source "$__tmpconf"; echo "${!__refvarname}")"
|
|
__args=("${__args[@]}" "$__refvarname=$__refvar")
|
|
done
|
|
set -- "${__args[@]}"
|
|
fi
|
|
fi
|
|
|
|
for __ref in "$@"; do
|
|
__runs_splitref "$__ref" __name __value
|
|
if __runs_check_varname "$__name"; then
|
|
__found=
|
|
if [ "${__value#/}" != "$__value" ]; then
|
|
# un chemin absolu. corriger éventuellement avec RUNSROOTDIR
|
|
# s'il existe, le garder tel quel
|
|
if [ -n "$RUNSROOTDIR" ]; then
|
|
# corriger le chemin à partir de RUNSROOTDIR
|
|
__value="$RUNSROOTDIR$__value"
|
|
fi
|
|
[ -e "$__value" ] && __found=1
|
|
fi
|
|
if [ -z "$__found" ]; then
|
|
if withpath "$__value" && [ -e "$RUNSSCRIPTDIR/$__value" ]; then
|
|
# d'abord dans le répertoire du script
|
|
__value="$RUNSSCRIPTDIR/$__value"
|
|
elif [ -e "$RUNSWORKDIR/$__value" ]; then
|
|
# ensuite dans le répertoire partagé
|
|
__value="$RUNSWORKDIR/$__value"
|
|
else
|
|
# puis chercher dans RUNS*DIRS
|
|
local __file
|
|
if __file="$(runs_find_datafile "$__value" "" "$RUNSSCRIPTDIR")"; then
|
|
__value="$__file"
|
|
elif [ -z "$__required" ]; then
|
|
# par défaut, prendre dans le répertoire partagé
|
|
__value="$RUNSWORKDIR/$__value"
|
|
else
|
|
die "Le fichier $__value ($__name) est requis"
|
|
fi
|
|
fi
|
|
fi
|
|
[ -z "$__rfile" -o -f "$__value" ] || die "Le fichier $__value ($__name) est requis"
|
|
[ -z "$__rdir" -o -d "$__value" ] || die "Le répertoire $__value ($__name) est requis"
|
|
|
|
runs_var "$__name=$__value"
|
|
RUNSVARDESC=
|
|
array_add RUNSREFS "$__name"
|
|
fi
|
|
done
|
|
}
|
|
function indref() { runs_indref "$@"; }
|
|
function refcerts() { runs_refcerts "$@"; }
|
|
function refapacheconfig() { runs_refapacheconfig "$@"; }
|
|
function out() {
|
|
for __out in "$@"; do
|
|
if [[ "$__out" == *=* ]]; then
|
|
__name="${__out%%=*}"
|
|
__value="${__out#*=}"
|
|
else
|
|
__name="$__out"
|
|
__value="$__out"
|
|
fi
|
|
if __runs_check_varname "$__name"; then
|
|
__value="$RUNSWORKDIR/$__value"
|
|
runs_var "$__name=$__value"
|
|
|
|
mkdirof "$__value"
|
|
>"$__value" # s'assurer que le fichier est vide
|
|
fi
|
|
done
|
|
}
|
|
function script:() {
|
|
runs_set_lang
|
|
runs_set_proxy
|
|
runs_clvars "${RUNSCLVARS[@]}"
|
|
runs_indvars
|
|
runs_check_confs
|
|
}
|
|
|
|
runs_check_runsscript "$RUNSSCRIPT" || die
|
|
runs_loadconfs
|
|
if [ -d "$RUNSSCRIPT" ]; then
|
|
# installer le répertoire avec uinst
|
|
# les variables sont passées en ligne de commande, et les tableau sont
|
|
# transformés en chaine avec chaque élément séparés par ':'
|
|
(
|
|
runs_clvars "${RUNSCLVARS[@]}"
|
|
runs_indvars
|
|
for __name in "${RUNSVARS[@]}"; do
|
|
__value="$(array_join "$__name" ":")"
|
|
__vars=("${__vars[@]}" "$(set_var_cmd "$__name" "$__value")")
|
|
done
|
|
|
|
urequire uinst udir prefixes uinc
|
|
# Il faut définir UINST, chemin vers le script uinst.
|
|
UINST="$RUNSSRCDIR/uinst"
|
|
uinst $(get_interaction_option) $(get_verbosity_option) \
|
|
"$RUNSSCRIPT" "${__vars[@]}"
|
|
); __state=$?
|
|
else
|
|
# lancer le script avec le protocole runs
|
|
(source "$RUNSSCRIPT"); __state=$?
|
|
fi
|
|
runs_clearvars
|
|
return $__state
|
|
}
|
|
|
|
function runs_action_export() {
|
|
local -a RUNSVARS RUNSARRAYS RUNSVARSINDIRECT
|
|
local -a RUNSCLVARS RUNSCONFS RUNSCONFFILES
|
|
local RUNSVARDESC __state
|
|
|
|
RUNSCLVARS=("$@")
|
|
|
|
function desc() { :; }
|
|
function unsupported_system() { runs_unsupported_system "$@"; }
|
|
function require_sysinfos() { runs_require_sysinfos "$@"; }
|
|
function vardesc() { RUNSVARDESC="$*"; }
|
|
function var() { runs_var "$@"; RUNSVARDESC=; }
|
|
function conf() { runs_conf "$@"; }
|
|
function after() { runs_after "$@" || exit 1; }
|
|
function ref() {
|
|
local -a __args
|
|
local __ref __name __value __copy __required __rdir __rfile __rsconf
|
|
local __shellconfs __shellconf __refvarname=refdir __refvar __shellvars
|
|
local __lineconfs __lineconf __force __copy_links __novcs=1
|
|
local __tmpconf __wildconf __cpcmd
|
|
parse_opts + \
|
|
-r,--required,-m,--mandatory __required=1 \
|
|
-f,--required-file '$__required=1; __rfile=1' \
|
|
-d,--required-dir '$__required=1; __rdir=1' \
|
|
-s:,--sconf: __shellconf= \
|
|
--rs,--rsconf,--required-sconf __rsconf=1 \
|
|
-V:,--refvar: __refvarname= \
|
|
-v:,--vars: __shellvars= \
|
|
-l:,--lconf: __lineconf= \
|
|
--force __force=1 \
|
|
--copy-links __copy_links=1 \
|
|
--with-vcs __novcs= \
|
|
@ __args -- "$@" && set -- "${__args[@]}" || die "$__args"
|
|
|
|
if [ -n "$__shellconf" ]; then
|
|
splitwcs "$__shellconf" __tmpconf __wildconf
|
|
[ -n "$__wildconf" ] && __shellconf="$__tmpconf"
|
|
if [ -e "$__shellconf" -a "${__shellconf#/}" != "$__shellconf" ]; then
|
|
# un chemin absolu _existant_, le garder tel quel
|
|
:
|
|
elif withpath "$__shellconf" && [ -e "$RUNSSCRIPTDIR/$__shellconf" ]; then
|
|
# d'abord dans le répertoire du script
|
|
__shellconf="$RUNSSCRIPTDIR/$__shellconf"
|
|
elif __tmpconf="$(runs_find_datafile "$__shellconf" "" "$RUNSSCRIPTDIR")"; then
|
|
# puis chercher dans RUNS*DIRS
|
|
__shellconf="$__tmpconf"
|
|
fi
|
|
if [ ! -e "$__shellconf" ]; then
|
|
if [ -n "$__rsconf" ]; then
|
|
die "$__shellconf: fichier introuvable"
|
|
else
|
|
ewarn "$__shellconf: fichier introuvable"
|
|
fi
|
|
fi
|
|
[ -n "$__wildconf" ] && __shellconf="$__shellconf/$__wildconf"
|
|
[ -n "$__lineconf" ] && ewarn "L'option -s étant spécifiée, l'option -l a été ignorée"
|
|
|
|
if [ -z "$*" ]; then
|
|
# Si aucun argument n'est spécifié, essayer de prendre la
|
|
# configuration dans le fichier $__shellconf
|
|
|
|
__runs_check_varname "$__refvarname" || die
|
|
set_var "$__refvarname" ""
|
|
|
|
splitwcs "$__shellconf" __tmpconf __wildconf
|
|
if [ -n "$__wildconf" ]; then
|
|
array_lsall __shellconfs "$__tmpconf" "$__wildconf"
|
|
else
|
|
__shellconfs=("$__shellconf")
|
|
fi
|
|
__args=()
|
|
for __tmpconf in "${__shellconfs[@]}"; do
|
|
[ -f "$__tmpconf" ] || {
|
|
eerror "$__tmpconf: fichier introuvable. Il a été ignoré"
|
|
continue
|
|
}
|
|
__refvar="$(source "$__tmpconf"; echo "${!__refvarname}")"
|
|
__args=("${__args[@]}" "$__refvarname=$__refvar")
|
|
done
|
|
set -- "${__args[@]}"
|
|
fi
|
|
|
|
elif [ -n "$__lineconf" ]; then
|
|
splitwcs "$__lineconf" __tmpconf __wildconf
|
|
[ -n "$__wildconf" ] && __lineconf="$__tmpconf"
|
|
if [ -e "$__lineconf" -a "${__lineconf#/}" != "$__lineconf" ]; then
|
|
# un chemin absolu _existant_, le garder tel quel
|
|
:
|
|
elif withpath "$__lineconf" && [ -e "$RUNSSCRIPTDIR/$__lineconf" ]; then
|
|
# d'abord dans le répertoire du script
|
|
__lineconf="$RUNSSCRIPTDIR/$__lineconf"
|
|
elif __tmpconf="$(runs_find_datafile "$__lineconf" "" "$RUNSSCRIPTDIR")"; then
|
|
# puis chercher dans RUNS*DIRS
|
|
__lineconf="$__tmpconf"
|
|
fi
|
|
[ -e "$__lineconf" ] || die "$__lineconf: fichier introuvable"
|
|
[ -n "$__wildconf" ] && __lineconf="$__lineconf/$__wildconf"
|
|
fi
|
|
if [ -n "$__rfile" ]; then
|
|
[ -n "$__shellconf" -o -n "$__lineconf" ] && die "-f est incompatible avec -s et -l"
|
|
fi
|
|
|
|
# utiliser par défaut cpnovcs pour la copie des fichiers sauf si
|
|
# --with-vcs est utilisé
|
|
[ -n "$__novcs" ] && __cpcmd=cpnovcs || __cpcmd=cpvcs
|
|
local -a __CPNOVCS_RSYNC_ARGS
|
|
if [ -n "$__copy_links" ]; then
|
|
__CPNOVCS_RSYNC_ARGS=(--copy-links)
|
|
else
|
|
__CPNOVCS_RSYNC_ARGS=(--copy-unsafe-links)
|
|
fi
|
|
|
|
for __ref in "$@"; do
|
|
if [ -n "$__shellconf" -a -z "$__shellvars" ]; then
|
|
ewarn "L'option -v n'a pas été spécifiée pour $__ref"
|
|
fi
|
|
__copy=1
|
|
__runs_splitref "$__ref" __name __value
|
|
if __runs_check_varname "$__name"; then
|
|
if [ -e "$__value" -a "${__value#/}" != "$__value" ]; then
|
|
# un chemin absolu _existant_, le garder tel quel
|
|
:
|
|
elif withpath "$__value" && [ -e "$RUNSSCRIPTDIR/$__value" ]; then
|
|
# d'abord dans le répertoire du script
|
|
__value="$RUNSSCRIPTDIR/$__value"
|
|
elif [ -e "$RUNSWORKDIR/$__value" ]; then
|
|
# puis dans le répertoire partagé
|
|
__value="$RUNSWORKDIR/$__value"
|
|
__copy=
|
|
else
|
|
# puis chercher dans RUNS*DIRS
|
|
local __file
|
|
if __file="$(runs_find_datafile "$__value" "" "$RUNSSCRIPTDIR")"; then
|
|
__value="$__file"
|
|
elif [ -z "$__required" ]; then
|
|
# par défaut, prendre dans le répertoire partagé
|
|
__value="$RUNSWORKDIR/$__value"
|
|
__copy=
|
|
else
|
|
die "Le fichier $__value ($__name) est requis"
|
|
fi
|
|
fi
|
|
[ -z "$__rfile" -o -f "$__value" ] || die "Le fichier $__value ($__name) est requis"
|
|
[ -z "$__rdir" -o -d "$__value" ] || die "Le répertoire $__value ($__name) est requis"
|
|
|
|
runs_var "$__name=$__value"
|
|
RUNSVARDESC=
|
|
array_add RUNSREFS "$__name"
|
|
|
|
# options de copie
|
|
[ -n "$__force" ] && __copy=1
|
|
|
|
if [ -n "$__copy" ]; then
|
|
if [ -n "$__shellconf" ]; then
|
|
# copier les fichiers mentionnés dans le fichier de
|
|
# configuration, d'après les valeurs de __shellvars
|
|
estep "Vérification du répertoire $(ppath "$__value")"
|
|
mkdirof "$RUNSROOTDIR$__value"
|
|
if [ -n "$__shellvars" ]; then
|
|
(
|
|
array_split __shellvars "$__shellvars" ,
|
|
splitwcs "$__shellconf" __tmpconf __wildconf
|
|
if [ -n "$__wildconf" ]; then
|
|
array_lsall __shellconfs "$__tmpconf" "$__wildconf"
|
|
else
|
|
__shellconfs=("$__shellconf")
|
|
fi
|
|
for __shellconf in "${__shellconfs[@]}"; do
|
|
estep "Dans $(ppath "$__shellconf")"
|
|
for __shellvar in "${__shellvars[@]}"; do
|
|
# s'assurer que la variables sont vides
|
|
# avant de sourcer $__shellconf
|
|
set_var "$__shellvar"
|
|
done
|
|
source "$__shellconf"
|
|
for __shellvar in "${__shellvars[@]}"; do
|
|
[ -n "${!__shellvar}" ] || continue
|
|
estep "... Copie de ${!__shellvar}"
|
|
"$__cpcmd" "$__value/${!__shellvar}" "$(dirname "$RUNSROOTDIR$__value/${!__shellvar}")"
|
|
done
|
|
done
|
|
)
|
|
fi
|
|
elif [ -n "$__lineconf" ]; then
|
|
# copier les fichiers mentionnés dans le fichier de
|
|
# configuration, à raison de un par ligne
|
|
estep "Vérification du répertoire $(ppath "$__value")"
|
|
mkdirof "$RUNSROOTDIR$__value"
|
|
(
|
|
splitwcs "$__lineconf" __tmpconf __wildconf
|
|
if [ -n "$__wildconf" ]; then
|
|
array_lsall __lineconfs "$__tmpconf" "$__wildconf"
|
|
else
|
|
__lineconfs=("$__lineconf")
|
|
fi
|
|
for __lineconf in "${__lineconfs[@]}"; do
|
|
estep "Dans $(ppath "$__lineconf")"
|
|
array_from_lines __relpaths "$(<"$__lineconf" filter_conf)"
|
|
for __relpath in "${__relpaths[@]}"; do
|
|
estep "... Copie de $__relpath"
|
|
"$__cpcmd" "$__value/$__relpath" "$(dirname "$RUNSROOTDIR$__value/$__relpath")"
|
|
done
|
|
done
|
|
)
|
|
else
|
|
# copie standard
|
|
estep "Copie de $(ppath "$__value")"
|
|
mkdirof "$RUNSROOTDIR$__value"
|
|
"$__cpcmd" "$__value" "$(dirname "$RUNSROOTDIR$__value")"
|
|
fi
|
|
fi
|
|
fi
|
|
done
|
|
}
|
|
function indref() { runs_indref "$@"; }
|
|
function refcerts() { runs_refcerts "$@"; }
|
|
function refapacheconfig() { runs_refapacheconfig "$@"; }
|
|
function out() {
|
|
for __out in "$@"; do
|
|
if [[ "$__out" == *=* ]]; then
|
|
__name="${__out%%=*}"
|
|
__value="${__out#*=}"
|
|
else
|
|
__name="$__out"
|
|
__value="$__out"
|
|
fi
|
|
if __runs_check_varname "$__name"; then
|
|
__value="$RUNSWORKDIR/$__value"
|
|
runs_var "$__name=$__value"
|
|
|
|
mkdirof "$__value"
|
|
>"$__value" # s'assurer que le fichier est vide
|
|
fi
|
|
done
|
|
}
|
|
function script:() {
|
|
runs_set_lang
|
|
runs_set_proxy
|
|
runs_clvars "${RUNSCLVARS[@]}"
|
|
runs_indvars
|
|
|
|
local __recipe
|
|
if array_contains RUNSCONFS local; then
|
|
if array_contains RUNSCONFS root; then
|
|
__recipe="$RUNSEXPORTDIR/localroot"
|
|
else
|
|
__recipe="$RUNSEXPORTDIR/localuser"
|
|
fi
|
|
else
|
|
__recipe="$RUNSEXPORTDIR/remote"
|
|
if array_contains RUNSCONFS root; then
|
|
touch "$RUNSEXPORTDIR/remote-needs-root"
|
|
fi
|
|
fi
|
|
if [ -n "$RUNSUPDATERECIPE" ]; then
|
|
estep "Ajout de la ligne de recette"
|
|
runs_clvars_cmd "$RUNSSCRIPTPATH" "${RUNSCLVARS[@]}" >>"$__recipe"
|
|
fi
|
|
|
|
if [ ! -e "$RUNSROOTDIR$RUNSSCRIPT" ]; then
|
|
estep "Copie du script"
|
|
mkdirof "$RUNSROOTDIR$RUNSSCRIPT"
|
|
cpnovcs "$RUNSSCRIPT" "$(dirname "$RUNSROOTDIR$RUNSSCRIPT")"
|
|
fi
|
|
exit 0
|
|
}
|
|
|
|
runs_check_runsscript "$RUNSSCRIPT" || die
|
|
runs_loadconfs
|
|
|
|
local __conffile
|
|
for __conffile in "${RUNSCONFFILES[@]}"; do
|
|
if [ ! -e "$RUNSROOTDIR$__conffile" ]; then
|
|
estep "Copie de $(ppath "$__conffile")"
|
|
mkdirof "$RUNSROOTDIR$__conffile"
|
|
cpnovcs "$__conffile" "$(dirname "$RUNSROOTDIR$__conffile")"
|
|
fi
|
|
done
|
|
|
|
if [ -d "$RUNSSCRIPT" ]; then
|
|
# le répertoire sera installé avec uinst
|
|
if [ -n "$RUNSUPDATERECIPE" ]; then
|
|
estep "Ajout de la ligne de recette"
|
|
runs_clvars_cmd "$RUNSSCRIPTPATH" "${RUNSCLVARS[@]}" >>"$RUNSEXPORTDIR/remote"
|
|
fi
|
|
|
|
if [ ! -e "$RUNSROOTDIR$RUNSSCRIPT" ]; then
|
|
estep "Copie des fichiers"
|
|
mkdir -p "$RUNSROOTDIR$RUNSSCRIPT" || return 1
|
|
cpdirnovcs "$RUNSSCRIPT" "$RUNSROOTDIR$RUNSSCRIPT" || return 1
|
|
fi
|
|
else
|
|
# le script sera lancé avec le protocole runs
|
|
(source "$RUNSSCRIPT") || return 1
|
|
fi
|
|
runs_clearvars
|
|
return 0
|
|
}
|
|
|
|
################################################################################
|
|
# Les fonctions de cette section permettent de maintenir des informations sur
|
|
# des opérations _effectuées avec l'utilisateur root_. Cela permet à un script de
|
|
# savoir s'il a déjà été lancé. Le code typique sera celui-ci:
|
|
# shouldrun || exit
|
|
# ...
|
|
# setdone
|
|
# Les informations sont stockées sur la machine cible dans /var/lib/runs.state
|
|
|
|
if is_root; then
|
|
RUNSSTATE_FILE=/var/lib/runs.state
|
|
else
|
|
RUNSSTATE_FILE="$HOME/etc/runs.state"
|
|
fi
|
|
RUNSSTATE_LASTKEY=
|
|
RUNSSTATE_LASTVALUE=
|
|
# Vérifier que la clé $1 existe dans $RUNSSTATE_FILE, et si $2!="", qu'elle
|
|
# existe avec la valeur $2. Si la clé existe, retourner faux (il ne faut pas
|
|
# lancer le script).
|
|
# Si $RUNSRESET est vrai, toujours retourner vrai. Ceci permet de forcer
|
|
# l'installation pour un script
|
|
# La clé est toujours automatiquement préfixée de $3(=$RUNSSCRIPTPATH)
|
|
function shouldrun() {
|
|
[ -f "$RUNSSTATE_FILE" ] || return 0
|
|
is_yes "$RUNSRESET" && return 0
|
|
local key="${3:-$RUNSSCRIPTPATH}${1:+-$1}"
|
|
if ! quietgrep "^$key:$2" "$RUNSSTATE_FILE"; then
|
|
RUNSSTATE_LASTKEY="$1"
|
|
RUNSSTATE_LASTVALUE="$2"
|
|
return 0
|
|
else
|
|
return 1
|
|
fi
|
|
}
|
|
# Pour le script de chemin scriptpath $1, vérifier que la clé $2 existe dans
|
|
# $RUNSSTATE_FILE, et si $3!="", qu'elle existe avec la valeur $3.
|
|
# Cette fonction permet de ne lancer un traitement que si un autre script a été
|
|
# lancé auparavant avec succès
|
|
function checkdone() {
|
|
[ -n "$1" ] || return 1
|
|
[ -f "$RUNSSTATE_FILE" ] || return 1
|
|
local key="$1${1:+-$2}" value="$3"
|
|
quietgrep "^$key:$value" "$RUNSSTATE_FILE"
|
|
}
|
|
# Comme checkdone(), mais si la clé n'existe pas, afficher un message d'erreur
|
|
# et quitter le script
|
|
function requiredone() {
|
|
if ! checkdone "$@"; then
|
|
msg="Ce script requière que le script dépendant $1"
|
|
if [ -n "$2" ]; then
|
|
msg="${msg} soit dans l'état $2=${3:-done}"
|
|
else
|
|
msg="${msg} aie été installé avec succès"
|
|
fi
|
|
die "$msg.
|
|
Pour résoudre ce problème, vous pouvez essayer de relancer le script dépendant"
|
|
fi
|
|
}
|
|
# Ajouter la clé $1 avec la valeur $2(=done) dans $RUNSSTATE_FILE si elle n'y
|
|
# existe pas déjà. Si $1 est vide, prendre par défaut la dernière clé utilisée
|
|
# avec shouldrun()
|
|
# La clé est toujours automatiquement préfixée de $3(=$RUNSSCRIPTPATH)
|
|
function setdone() {
|
|
local key="$1" value="$2"
|
|
[ -n "$key" ] || key="$RUNSSTATE_LASTKEY"
|
|
[ -n "$value" ] || value="$RUNSSTATE_LASTVALUE"
|
|
key="${3:-$RUNSSCRIPTPATH}${key:+-$key}"
|
|
[ -n "$value" ] || value=done
|
|
|
|
local line="$key:$value"
|
|
mkdirof "$RUNSSTATE_FILE"
|
|
[ -f "$RUNSSTATE_FILE" ] || touch "$RUNSSTATE_FILE"
|
|
if ! quietgrep "^$line" "$RUNSSTATE_FILE"; then
|
|
echo "$line" >>"$RUNSSTATE_FILE"
|
|
fi
|
|
RUNSSTATE_LASTKEY=
|
|
RUNSSTATE_LASTVALUE=
|
|
}
|
|
# Supprimer toutes les valeurs de la clé $1 dans $RUNSSTATE_FILE
|
|
# La clé est toujours automatiquement préfixée de $2(=$RUNSSCRIPTPATH)
|
|
function resetdone() {
|
|
local key="${2:-$RUNSSCRIPTPATH}${1:+-$1}"
|
|
[ -n "$key" ] || return
|
|
[ -f "$RUNSSTATE_FILE" ] || return
|
|
sedi "/^${key//\//\\/}:/d" "$RUNSSTATE_FILE"
|
|
}
|