#!/bin/bash # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 source "$(dirname -- "$0")/lib/ulib/auto" || exit 1 urequire runs runsmod function display_help() { uecho "$scriptname: Lancer un script avec le protocole runs USAGE $scriptname [options] rscriptname name=value... $scriptname [options] @recipe name=value... $scriptname [options] -f rscript name=value... $scriptname [options] -r recipe name=value... OPTIONS Configuration --init --verify Vérifier le nom d'hôte et créer si nécessaire le répertoire d'hôte correspondant à l'hôte courant ou à l'hôte spécifié avec l'option -h Avec --verify, la création du répertoire d'hôte n'est pas effectuée. --sysinfos DATA Avec l'option --init, initialiser le fichier sysinfos.conf avec DATA, si le fichier n'a pas déjà été provisionné. Sans cette option, un fichier vide avec des commentaires est créé à la place. --create RSCRIPT Créer un modèle de script avec le nom donné. Avec l'option -h, le script est créé dans le répertoire d'hôte correspondant à l'hôte spécifié Gestion des scripts -s Forcer l'exécution du script avec l'utilisateur root si ce n'est pas déjà le cas -f RSCRIPT Lancer le script individuel spécifié au lieu de chercher dans les répertoires de \$RUNSSCRIPTSPATH -r RECIPE Lancer les scripts spécifiés dans le fichier de recettes individuel spécifié. -h HOSTNAME[.DOMAIN] Spécifier que les scripts sont destinés à être lancés sur l'hôte spécifié. Les scripts sont alors aussi cherchés dans les répertoires {\$RUNSHOSTSPATH}/\$hostname.\$domain (par défaut) et {\$RUNSHOSTSPATH}/\$domain/\$hostname (le cas échéant) L'option --host est équivalente, sauf que son argument est facultatif et que sa valeur par défaut est l'hôte courant, soit $MYHOST --list Afficher la liste des scripts qui sont disponibles. Avec l'option -h, inclure aussi les scripts spécifiques à cet hôte. Avec cette option, les arguments supplémentaires agissent comme des filtres (regexp utilisée avec l'opérateur == de la commande [[). Les noms des scripts doivent valider au moins un filtre. --info Afficher la la description du script et la valeur de chaque variable définies --desc-only Afficher seulement la description du script -z Forcer la réinstallation des scripts qui se basent sur shouldrun/setdone" } function runs_path_required() { die "Vous devez définir $1 dans ~/etc/default/runs" } function runs_path_undefined() { ewarn "La variable $1 n'est pas définie dans ~/etc/default/runs" } runs_before_parse_args auto_runsmod=1 action=runs create_verbose= init_sysinfos=--NOT-SET-- list_verbose= run_as_root= rscripts=() recipes=() runshost= runssysname= runssysdist= runssysver= runsbits= runsscriptspath= runsscriptsdirs=() runsmodulespath= runsmodulesdirs=() runshostspath= runshostsdirs=() runsexportdir= # répertoire dans lequel exporter les fichiers runsworkdir= # si runsexportdir n'est pas spécifié, répertoire de travail runsvarsfile= # fichier contenant des définitions à charger runs_init "$scriptdir" parse_opts "${PRETTYOPTS[@]}" \ --help '$exit_with display_help' \ --no-auto-runsmod auto_runsmod= \ --i '$action=init;create_verbose=false' \ --init '$action=init;create_verbose=true' \ --verify action=verify \ --sysinfos: init_sysinfos= \ -c,--c '$action=create;create_verbose=false' \ --create '$action=create;create_verbose=true' \ -l,--l '$action=list;list_verbose=false' \ --list '$action=list;list_verbose=true' \ --desc-only '$action=runs;RUNSACTION=runs_action_desc' \ -d,--dump,-i,--info '$action=runs;RUNSACTION=runs_action_dump' \ --export '$action=runs;RUNSACTION=runs_action_export' \ -s run_as_root \ -f: rscripts \ -r: recipes \ -h:,-H: runshost= \ --host:: '$set@ runshost "$MYHOST"' \ --sysname: runssysname= \ --sysdist: runssysdist= \ --sysver: runssysver= \ --bits: runsbits= \ --runsscriptspath: runsscriptspath= \ --runsscriptsdir: runsscriptsdirs \ --runsmodulespath: runsmodulespath= \ --runsmodulesdir: runsmodulesdirs \ --runshostspath: runshostspath= \ --runshostsdir: runshostsdirs \ --runsexportdir: runsexportdir= \ --runsworkdir: runsworkdir= \ --runsvarsfile: runsvarsfile= \ -z RUNSRESET=1 \ @ args -- "$@" && set -- "${args[@]}" || die "$args" runs_after_parse_args if [ "$action" == runs \ -o "$action" == init -o "$action" == verify \ -o \( -n "$runshost" -a \( "$action" == create -o "$action" == list \) \) ]; then # configurer le nom d'hôté ici, parce qu'avec l'option -s, le fichier de # configuration ~/etc/default/runs ne sera plus disponible runs_initdomains runs_inithost "$runshost" host="$RUNSHOST" splithost "$host" hostname domain if [ -z "$domain" ]; then host="$(runs_find_host "$host")" splithost "$host" hostname domain fi [ -n "$domain" ] || host="$(runs_add_domain "$host")" if [ "$host" != "$RUNSHOST" ]; then enote "Le nom d'hôte '$RUNSHOST' a été automatiquement corrigé en '$host'" if ask_yesno "Acceptez-vous cette modification?" O; then RUNSHOST="$host" runshost="$host" # pour l'option -s fi fi fi [ -n "$auto_runsmod" ] && runsmod_autoconf if ! is_root && [ -n "$run_as_root" ]; then # reconstruire la ligne de commande args=(--no-auto-runsmod) if [ "$action" == "init" ]; then args=("${args[@]}" --init) elif [ "$action" == "verify" ]; then args=("${args[@]}" --verify) elif [ "$action" == "create" ]; then is_yes "$create_verbose" && args=("${args[@]}" --create) || args=("${args[@]}" -c) elif [ "$action" == "runs" ]; then if [ "$RUNSACTION" == "runs_action_run" ]; then : elif [ "$RUNSACTION" == "runs_action_desc" ]; then args=("${args[@]}" --desc-only) elif [ "$RUNSACTION" == "runs_action_dump" ]; then args=("${args[@]}" --dump) else ewarn "RUNSACTION inconnu: $RUNSACTION" fi else ewarn "action inconnue: $action" fi for rscript in "${rscripts[@]}"; do args=("${args[@]}" -f "$rscript") done for recipe in "${recipes[@]}"; do args=("${args[@]}" -r "$recipe") done args=("${args[@]}" ${runshost:+-h "$runshost"} ${runssysname:+--sysname "$runssysname"} ${runssysdist:+--sysdist "$runssysdist"} ${runssysver:+--sysver "$runssysver"} ${runsbits:+--bits "$runsbits"} ${RUNSSCRIPTSPATH:+--runsscriptspath "$RUNSSCRIPTSPATH"} ${RUNSMODULESPATH:+--runsmodulespath "$RUNSMODULESPATH"} ${RUNSHOSTSPATH:+--runshostspath "$RUNSHOSTSPATH"} ${runsexportdir:+--runsexportdir "$runsexportdir"} ${runsworkdir:+--runsworkdir "$runsworkdir"} ${runsvarsfile:+--runsvarsfile "$runsvarsfile"} ${RUNSRESET:+-z}) # puis relancer le script en root run_as root "${args[@]}" -- "$@" fi # si on donne un chemin relatif à '.' ou '..' ou un chemin absolu, forcer -f if [ -z "${rscripts[*]}" -a -z "${recipes[*]}" -a -n "$1" ]; then if withpath "$1"; then rscripts=("$1") shift fi fi ################################################################################ if [ "$action" == "init" -o "$action" == "verify" ]; then if [ "$init_sysinfos" == "--NOT-SET--" ]; then init_sysinfos= elif [ -z "$init_sysinfos" ]; then # Valeur par défaut de sysinfos pour l'hôte courant init_sysinfos="\ sysname=(${MYSYSNAME[*]}) sysdist=(${MYSYSDIST[*]}) sysver=(${MYSYSVER[*]}) bits=$MYBITS" fi __runs_setpath [ -n "${RUNSHOSTSDIRS[*]}" ] || runs_path_required RUNSHOSTSPATH runshost="${runshost:-$RUNSHOST}" resolv_ips __runs_ips "$runshost" if [ -z "${__runs_ips[*]}" ]; then check_interaction -c && eerror "$runshost ne semble pas être une adresse valide." ask_yesno "Voulez-vous réellement utiliser cette adresse, bien qu'elle n'existe pas dans le DNS?" C || die fi if [ "$action" == "init" ]; then etitle "$runshost" runs_initdir "$runshost" "$create_verbose" "$init_sysinfos" fi ################################################################################ elif [ "$action" == "create" ]; then __runs_setpath if [ -n "$runshost" ]; then [ -n "${RUNSHOSTSDIRS[*]}" ] || runs_path_required RUNSHOSTSPATH etitle "$runshost" runs_initdir "$runshost" "$create_verbose" fi # générer les scripts spécifié overwrite=no error= new_rscripts=() for rscript in "$@"; do etitle "$(ppath "$rscript")" runs_create_rscript "$rscript" "$runshost" "$create_verbose" "$overwrite" || error=1 done # Puis éditer les fichiers nouvellement créés if [ -z "$error" -a -n "${new_rscripts[*]}" ]; then etitle "Edition des fichiers" if ask_yesno "Voulez-vous éditer le script nouvellement créé?" O; then "${EDITOR:-vi}" "${new_rscripts[@]}" fi eend fi ################################################################################ elif [ "$action" == "list" ]; then function find_items() { # Trouver tous les scripts runs et les répertoire uinstallable à partir # du répertoire $2, et mettre les chemins dans le tableau $1 local dest="$1" local runsdir="$2" # $3 est un préfixe à enlever des chemins, pour qu'ils soient exprimés # relativement à un chemin qui vaut $2 par défaut local prefix="${3:-$runsdir/}" local items item [ -d "$runsdir" ] || return array_lsall items "$runsdir" for item in "${items[@]}"; do if __runs_is_runsscript "$item"; then array_add "$dest" "${item#$prefix}" elif [ -d "$item" ]; then find_items "$dest" "$item" "$prefix" fi done } __runs_setpath [ -n "${RUNSSCRIPTSDIRS[*]}" ] || runs_path_undefined RUNSSCRIPTSPATH [ -n "${RUNSMODULESDIRS[*]}" ] || runs_path_undefined RUNSMODULESPATH [ -z "$runshost" -o -n "${RUNSHOSTSDIRS[*]}" ] || runs_path_undefined RUNSHOSTSPATH splithost "$runshost" hostname domain # chercher tous les scripts runs et les répertoires uinstallables rscriptpaths=() if [ -n "$runshost" ]; then for runsdir in "${RUNSHOSTSDIRS[@]}"; do find_items rscriptpaths "$runsdir/$runshost/runs" find_items rscriptpaths "$runsdir/$domain/$hostname/runs" find_items rscriptpaths "$runsdir/$runshost" find_items rscriptpaths "$runsdir/$domain/$hostname" done fi for runsdir in "${RUNSSCRIPTSDIRS[@]}" "${RUNSMODULESDIRS[@]}"; do find_items rscriptpaths "$runsdir" done # les trier en enlevant les doublons, recalculer le nom canonique # RUNSSCRIPT, puis les afficher array_from_lines rscriptpaths "$(array_to_lines rscriptpaths | sort -u)" for rscriptpath in "${rscriptpaths[@]}"; do runs_find_scriptfile "$rscriptpath" "$runshost" || continue if [ -n "$*" ]; then # filtrer match= for filter in "$@"; do [[ "$filter" == *\** ]] || filter="$filter*" eval "[[ \"\$rscriptpath\" == $filter ]] && match=1" done [ -n "$match" ] || continue fi if is_yes "$list_verbose"; then echo "$rscriptpath $RUNSSCRIPT" else echo "$rscriptpath" fi done ################################################################################ elif [ "$action" == "runs" ]; then __runs_setpath if [ -z "${rscripts[*]}" -a -z "${recipes[*]}" ]; then # sans les options -f et -r, prendre par défaut le répertoire courant # comme répertoire de script, de module et d'hôtes refix= [ -n "${RUNSSCRIPTSDIRS[*]}" ] || { runs_path_undefined RUNSSCRIPTSPATH setx RUNSSCRIPTSPATH=pwd refix=1 } [ -n "${RUNSMODULESDIRS[*]}" ] || { runs_path_undefined RUNSMODULESPATH setx RUNSMODULESPATH=pwd refix=1 } [ -z "$runshost" -o -n "${RUNSHOSTSDIRS[*]}" ] || { runs_path_undefined RUNSHOSTSPATH setx RUNSHOSTSPATH=pwd refix=1 } [ -n "$refix" ] && __runs_setpath fi # initialisation [ -f "$runsvarsfile" ] && source "$runsvarsfile" runs_initsysinfos "$runssysname" "$runssysdist" "$runssysver" "$runsbits" runs_initworkdir "$runsexportdir" "$runsworkdir" "$scriptdir" if [ -n "${rscripts[*]}" ]; then # scripts individuels for rscript in "${rscripts[@]}"; do etitle "$(ppath "$rscript")" \ runs_rscript "$rscript" "$@" || die "Arrêt du déploiement" done elif [ -n "${recipes[*]}" ]; then # fichiers de recette for recipe in "${recipes[@]}"; do [ -f "$recipe" ] || die "$recipe: fichier introuvable" etitle "$(ppath "$recipe")" \ runs_recipe "$recipe" "$@" || die "Arrêt du déploiement" done else # suite de scripts et/ou de recettes séparés par -- # note: si on spécifie plusieurs scripts séparés par --, il faut le # faire de cette manière: # runs -- script1 ... -- script2 ... -- @recipe ... # le premier -- est important, il permet de ne pas traiter les arguments # suivants, et donc de ne pas fusionner les valeurs script1 avec script2 while [ -n "$1" ]; do if [ "$1" == -- ]; then shift continue elif [ "${1#@}" != "$1" ]; then # recette à chercher dans RUNSSCRIPTSPATH # prendre les arguments jusqu'à -- recipe="${1#@}"; shift args=() while [ -n "$1" -a "$1" != "--" ]; do args=("${args[@]}" "$1") shift done etitle "@$recipe" \ runs_recipepath "$recipe" "${args[@]}" || die "Arrêt du déploiement" shift else # script à chercher dans RUNSSCRIPTSPATH # prendre les arguments jusqu'à -- args=() while [ -n "$1" -a "$1" != "--" ]; do args=("${args[@]}" "$1") shift done etitle "${args[0]}" \ runs_rscriptpath "${args[@]}" || die "Arrêt du déploiement" fi done fi # traitement après déploiement runs_after_export fi