2018-09-27 21:00:45 +04:00
|
|
|
#!/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
|
|
|
|
|
|
|
|
function display_help() {
|
|
|
|
uecho "$scriptname: outil pour faciliter l'utilisation de docker
|
|
|
|
|
|
|
|
USAGE
|
|
|
|
$scriptname CMDs...
|
|
|
|
|
|
|
|
COMMANDES
|
|
|
|
build
|
2019-03-28 10:53:50 +04:00
|
|
|
Construire les images
|
2018-10-08 11:50:56 +04:00
|
|
|
push
|
2019-03-28 10:53:50 +04:00
|
|
|
Pousser les images vers le serveur
|
|
|
|
start, run [SERVICE]
|
|
|
|
Démarrer le(s) service(s)
|
|
|
|
stop [SERVICE]
|
|
|
|
Arrêter le(s) service(s)
|
2018-09-27 21:00:45 +04:00
|
|
|
up
|
2019-03-28 10:53:50 +04:00
|
|
|
Créer l'environnement, démarrer les services et suivre les logs de façon
|
|
|
|
interactive.
|
|
|
|
logs [SERVICE]
|
|
|
|
Afficher les logs
|
2018-09-27 21:00:45 +04:00
|
|
|
down
|
2019-03-28 10:53:50 +04:00
|
|
|
Arrêter les services et supprimer l'environnement
|
2018-09-27 21:00:45 +04:00
|
|
|
brd
|
2019-03-28 10:53:50 +04:00
|
|
|
Construire les images (comme avec build), démarrer les services et
|
|
|
|
suivre les logs de façon interactive (comme avec up). Dès que l'on
|
|
|
|
arrête l'affichage des logs avec Ctrl+C, arrêter les services et
|
|
|
|
supprimer l'environnement (comme avec down)
|
2018-12-09 22:33:07 +04:00
|
|
|
bs
|
2019-03-28 10:53:50 +04:00
|
|
|
Construire les images (comme avec build) puis démarrer les services
|
|
|
|
(comme avec start)
|
|
|
|
exec SERVICE COMMAND
|
|
|
|
Lancer la commande dans le container spécifié
|
|
|
|
service
|
|
|
|
Générer une unité systemd qui démarre les services
|
2018-09-27 21:00:45 +04:00
|
|
|
ps
|
2019-03-28 10:53:50 +04:00
|
|
|
Afficher les containers en cours d'exécution
|
2018-09-27 21:00:45 +04:00
|
|
|
ls
|
2019-03-28 10:53:50 +04:00
|
|
|
Lister les images actuellement présentes
|
2018-09-27 21:00:45 +04:00
|
|
|
rm
|
2019-03-28 10:53:50 +04:00
|
|
|
Supprimer une image
|
2018-11-19 09:56:04 +04:00
|
|
|
prune
|
2019-03-28 10:53:50 +04:00
|
|
|
Supprimer les containers et les images inutilisées
|
2018-11-19 09:56:04 +04:00
|
|
|
|
2019-04-02 15:59:47 +04:00
|
|
|
OPTIONS générales
|
|
|
|
(ces options sont communes à toutes les commandes)
|
2018-11-19 09:56:04 +04:00
|
|
|
-d, --chdir PROJDIR
|
|
|
|
-p, --profile PROFILE
|
|
|
|
-P, --prod
|
|
|
|
-T, --test
|
2018-11-22 15:34:07 +04:00
|
|
|
-n, --fake
|
2018-11-19 09:56:04 +04:00
|
|
|
-j, --no-cache
|
2019-04-02 15:59:47 +04:00
|
|
|
-h, --host HOST
|
|
|
|
|
|
|
|
OPTIONS build
|
|
|
|
(ces options ne sont valides que pour les commandes build, brd, bs)
|
|
|
|
-g, --ug, --no-update-apps
|
|
|
|
ne pas mettre à jour les dépôts dépendants. ces dépôts sont
|
|
|
|
définis dans le fichier update-apps.conf qui a le format
|
|
|
|
suivant:
|
|
|
|
DEFAULT_BRANCH=
|
|
|
|
APPS=()
|
|
|
|
app_URL=
|
|
|
|
app_DEST=
|
|
|
|
app_ORIGIN=
|
|
|
|
app_BRANCH=
|
|
|
|
app_TYPE=
|
|
|
|
app_AFTER_UPDATE=()
|
|
|
|
-u, --uu, --update-apps-only
|
|
|
|
Ne faire que la mise à jour depuis les dépôts dépendants.
|
|
|
|
--uo, --update-apps-origin ORIGIN
|
|
|
|
Spécifier l'origine par défaut pour update-apps
|
|
|
|
--ub, --update-apps-branch BRANCH
|
|
|
|
Spécifier la branche par défaut pour update-apps"
|
2018-09-27 21:00:45 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
function get_version() {
|
|
|
|
local GIT_DIR; unset GIT_DIR
|
|
|
|
if git rev-parse --git-dir >/dev/null 2>&1; then
|
|
|
|
local head commit tag
|
|
|
|
commit="$(git rev-list --tags --max-count=1 2>/dev/null)"
|
|
|
|
if [ -n "$commit" ]; then
|
|
|
|
tag="$(git describe --tags "$commit" 2>/dev/null)"
|
|
|
|
if [ -n "$tag" ]; then
|
|
|
|
head="$(git rev-parse HEAD)"
|
|
|
|
if [ "$commit" != "$head" ]; then
|
|
|
|
echo "$tag-develop"
|
|
|
|
else
|
|
|
|
echo "$tag"
|
|
|
|
fi
|
|
|
|
return
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
elif [ -f VERSION.txt ]; then
|
|
|
|
cat VERSION.txt
|
|
|
|
fi
|
|
|
|
echo develop
|
|
|
|
}
|
|
|
|
|
|
|
|
function docker_add_build_arg() {
|
|
|
|
eval "replace_build_args+=(--build-arg $1=\"$2\"); $1=\"$2\""
|
|
|
|
}
|
|
|
|
function docker_parse_build_args() {
|
|
|
|
cat "$1" |
|
|
|
|
grep -v '^#' |
|
|
|
|
grep -v '^$' |
|
|
|
|
sed -r 's/([^=]+)=(.*)/replace_build_args+=(--build-arg \1="\2"); \1="\2"/'
|
|
|
|
}
|
|
|
|
function docker_parse_env_args() {
|
|
|
|
[ -f .build.env ] && eval "$(docker_parse_build_args .build.env)"
|
|
|
|
[ -f build.env ] && eval "$(docker_parse_build_args build.env)"
|
2018-11-16 14:16:16 +04:00
|
|
|
[ -n "$PROFILE" -a -f ".build.$PROFILE.env" ] && eval "$(docker_parse_build_args ".build.$PROFILE.env")"
|
2018-09-27 21:00:45 +04:00
|
|
|
}
|
|
|
|
function docker_set_env_args() {
|
|
|
|
[ -f .build.env ] && source ./.build.env
|
|
|
|
[ -f build.env ] && source ./build.env
|
2018-11-16 14:16:16 +04:00
|
|
|
[ -n "$PROFILE" -a -f ".build.$PROFILE.env" ] && source "./.build.$PROFILE.env"
|
2018-09-27 21:00:45 +04:00
|
|
|
}
|
|
|
|
function docker_set_run_args() {
|
|
|
|
replace_run_args+=(--env-file "$1")
|
|
|
|
source "$1"
|
|
|
|
}
|
|
|
|
function docker_check_name() {
|
|
|
|
[ -n "$NAME" ] || die "Vous devez définir NAME dans .build.env"
|
2018-11-22 15:34:07 +04:00
|
|
|
if [ "$1" == set_container_name ]; then
|
|
|
|
project_name="$NAME"
|
|
|
|
container_name="${project_name//[^a-zA-Z0-9_-]/}"
|
|
|
|
[ -n "$PROFILE" ] && container_name="${container_name}_$PROFILE"
|
2018-09-27 21:00:45 +04:00
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
|
|
|
function compose_set_env_args() {
|
|
|
|
replace_env_args+=(-f docker-compose.yml)
|
|
|
|
if [ -f docker-compose.override.yml ]; then
|
|
|
|
replace_env_args+=(-f docker-compose.override.yml)
|
|
|
|
fi
|
2018-10-09 19:12:07 +04:00
|
|
|
local PROJECT_NAME=--none--
|
|
|
|
[ -f .compose.env ] && source ./.compose.env
|
2018-11-16 14:16:16 +04:00
|
|
|
if [ -n "$PROFILE" ]; then
|
|
|
|
if [ -f "docker-compose.$PROFILE.yml" ]; then
|
|
|
|
replace_env_args+=(-f "docker-compose.$PROFILE.yml")
|
2018-10-09 19:12:07 +04:00
|
|
|
fi
|
|
|
|
if [ "$PROJECT_NAME" != --none-- ]; then
|
|
|
|
if [ -z "$COMPOSE_PROJECT_NAME" ]; then
|
|
|
|
[ -n "$PROJECT_NAME" ] || PROJECT_NAME="$(basename -- "$(pwd)")"
|
2018-11-16 14:16:16 +04:00
|
|
|
COMPOSE_PROJECT_NAME="${PROJECT_NAME}_${PROFILE}"
|
2018-10-09 19:12:07 +04:00
|
|
|
fi
|
|
|
|
export COMPOSE_PROJECT_NAME
|
|
|
|
fi
|
2018-09-27 21:00:45 +04:00
|
|
|
fi
|
2018-11-22 15:34:07 +04:00
|
|
|
if [ "$1" == set_container_name ]; then
|
|
|
|
if [ "$PROJECT_NAME" == --none-- ]; then
|
|
|
|
project_name="$(basename -- "$(pwd)")"
|
|
|
|
else
|
|
|
|
project_name="$PROJECT_NAME"
|
|
|
|
fi
|
|
|
|
container_name="${project_name//[^a-zA-Z0-9_-]/}"
|
|
|
|
[ -n "$PROFILE" ] && container_name="${container_name}_$PROFILE"
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
|
|
|
function host_run() {
|
|
|
|
# lancer le script $2..@ sur l'hôte $1
|
|
|
|
# si $1 n'est pas défini ou est le nom l'hôte local, lancer le script en
|
|
|
|
# local avec les droits root
|
|
|
|
# sinon, si docker-machine existe, l'hôte doit correspondre à la machine active
|
|
|
|
# sinon, lancer inconditionnellement le script sur l'hôte distant
|
|
|
|
local host="$1" script="$2"; shift; shift
|
|
|
|
if [ -n "$host" ]; then
|
|
|
|
if check_hostname "$host"; then
|
|
|
|
estep "Lancement de $script localement"
|
|
|
|
runscript_as_root "$script" "$@"
|
|
|
|
elif progexists docker-machine; then
|
|
|
|
local dm; setx dm=docker-machine active 2>/dev/null
|
|
|
|
if [ "${host%%.*}" == "$dm" ]; then
|
|
|
|
estep "Copie du script vers root@$host"
|
|
|
|
scp "$script" "root@$host:/tmp/tmp-dk-service-script" || die
|
|
|
|
estep "Lancement du script à distance"
|
|
|
|
local -a args; args=(/tmp/tmp-dk-service-script "$@")
|
|
|
|
ssh -qt "root@$host" "$(qvals "${args[@]}"); rm -f /tmp/tmp-dk-service-script"
|
|
|
|
else
|
|
|
|
ewarn "La machine active ($dm) n'est pas la destination ($host)"
|
|
|
|
fi
|
|
|
|
else
|
|
|
|
estep "Copie du script vers root@$host"
|
|
|
|
scp "$script" "root@$host:/tmp/tmp-dk-service-script" || die
|
|
|
|
estep "Lancement du script à distance"
|
|
|
|
local -a args; args=(/tmp/tmp-dk-service-script "$@")
|
|
|
|
ssh -qt "root@$host" "$(qvals "${args[@]}"); rm -f /tmp/tmp-dk-service-script"
|
|
|
|
fi
|
|
|
|
else
|
|
|
|
estep "Lancement de $script localement"
|
|
|
|
runscript_as_root "$script" "$@"
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
function local_run() {
|
|
|
|
# lancer le script $2..@ sur l'hôte $1 uniquement si c'est l'hôte courant
|
|
|
|
local host="$1" script="$2"; shift; shift
|
|
|
|
if [ -n "$host" ]; then
|
|
|
|
if ! check_hostname "$host"; then
|
|
|
|
eerror "Cette commande doit obligatoirement être lancée depuis l'hôte $host"
|
|
|
|
return 1
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
estep "Lancement de $script localement"
|
|
|
|
runscript_as_root "$script" "$@"
|
2018-09-27 21:00:45 +04:00
|
|
|
}
|
|
|
|
|
2019-04-02 15:59:47 +04:00
|
|
|
BUILD_UPDATE_APPS=
|
|
|
|
BUILD_BUILD=
|
|
|
|
UPDATE_APPS_ORIGIN=
|
|
|
|
UPDATE_APPS_BRANCH=
|
|
|
|
function build_set_options() {
|
|
|
|
case "$1" in
|
|
|
|
u) BUILD_UPDATE_APPS=1; BUILD_BUILD=;;
|
|
|
|
b) BUILD_UPDATE_APPS=; BUILD_BUILD=1;;
|
|
|
|
*) BUILD_UPDATE_APPS=1; BUILD_BUILD=1;;
|
|
|
|
esac
|
|
|
|
UPDATE_APPS_ORIGIN="$2"
|
|
|
|
UPDATE_APPS_BRANCH="$3"
|
|
|
|
}
|
|
|
|
|
|
|
|
function update_apps_func_sqlmig() {
|
|
|
|
local destdir="$1" srcdir="$2"
|
|
|
|
[ -n "$destdir" ] || destdir=db
|
|
|
|
[ "${destdir%/config/mariadb/sqlmig}" != "$destdir" ] || destdir="$destdir/config/mariadb/sqlmig"
|
|
|
|
|
|
|
|
[ -n "$srcdir" ] || srcdir="$dest"
|
|
|
|
[ "${srcdir%/config/sqlmig}" != "$srcdir" ] || srcdir="$srcdir/config/sqlmig"
|
|
|
|
|
|
|
|
[ -d "$srcdir" ] || return 0
|
|
|
|
|
|
|
|
local -a sqlmigs; local sqlmig name
|
|
|
|
array_lsall sqlmigs "$srcdir"
|
|
|
|
mkdir -p "$destdir" || return 1
|
|
|
|
for sqlmig in "${sqlmigs[@]}"; do
|
|
|
|
if [ -d "$sqlmig" ]; then
|
|
|
|
setx name=basename -- "$sqlmig"
|
|
|
|
rsync -av --delete-after "$sqlmig/" "$destdir/$name"
|
|
|
|
else
|
|
|
|
rsync -av "$sqlmig" "$destdir"
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
|
|
|
function build_update_apps() {
|
|
|
|
[ -n "$BUILD_UPDATE_APPS" ] || return 0
|
|
|
|
[ -f update-apps.conf ] || return 0
|
|
|
|
|
|
|
|
# charger le fichier de configuration
|
|
|
|
local DEFAULT_ORIGIN DEFAULT_BRANCH APPS
|
|
|
|
DEFAULT_ORIGIN="$UPDATE_APPS_ORIGIN"
|
|
|
|
[ -z "$DEFAULT_ORIGIN" ] && DEFAULT_ORIGIN=origin
|
|
|
|
DEFAULT_BRANCH="$UPDATE_APPS_BRANCH"
|
|
|
|
#XXX à terme, on déploiera la branche master en prod
|
|
|
|
[ -z "$DEFAULT_BRANCH" -a "$PROFILE" == prod ] && DEFAULT_BRANCH=develop #master
|
|
|
|
[ -z "$DEFAULT_BRANCH" ] && DEFAULT_BRANCH=develop
|
|
|
|
APPS=()
|
|
|
|
[ -f update-apps.conf ] && source ./update-apps.conf
|
|
|
|
[ ${#APPS[*]} -gt 0 ] || return 0
|
|
|
|
|
|
|
|
local PRODUCTION DEVELOPMENT
|
|
|
|
case "$PROFILE" in
|
|
|
|
prod) PRODUCTION=1; DEVELOPMENT=;;
|
|
|
|
test) PRODUCTION=1; DEVELOPMENT=1;;
|
|
|
|
devel) PRODUCTION=; DEVELOPMENT=;;
|
|
|
|
esac
|
|
|
|
|
|
|
|
etitle "Mise à jour des dépendances"
|
|
|
|
local app type url dest branch after_update after_updates
|
|
|
|
for app in "${APPS[@]}"; do
|
|
|
|
etitle "$app"
|
|
|
|
url="${app}_URL"; url="${!url}"
|
|
|
|
dest="${app}_DEST"; dest="${!dest}"
|
|
|
|
origin="${app}_ORIGIN"; origin="${!origin}"
|
|
|
|
branch="${app}_BRANCH"; branch="${!branch}"
|
|
|
|
type="${app}_TYPE"; type="${!type}"
|
|
|
|
after_updates="${app}_AFTER_UPDATE"
|
|
|
|
if is_defined "$after_updates"; then
|
|
|
|
after_updates="$after_updates[@]"; after_updates="${!after_updates}"
|
|
|
|
else
|
|
|
|
# script par défaut après update-apps
|
|
|
|
after_updates=(sqlmig)
|
|
|
|
fi
|
|
|
|
|
|
|
|
[ -n "$url" ] || {
|
|
|
|
ewarn "$app: vous devez définir l'url"
|
|
|
|
eend; return 1
|
|
|
|
}
|
|
|
|
[ -n "$dest" ] || dest="$app"
|
|
|
|
mkdir -p "$dest" || { eend; return 1; }
|
|
|
|
[ -n "$origin" ] || origin="$DEFAULT_ORIGIN"
|
|
|
|
[ -n "$branch" ] || branch="$DEFAULT_BRANCH"
|
|
|
|
|
|
|
|
dest="$dest/$app"
|
|
|
|
if [ ! -d "$dest" ]; then
|
|
|
|
# clonage initial
|
|
|
|
estep "Clonage $url:$branch --> $dest"
|
|
|
|
git clone -o "$origin" -b "$branch" "$url" "$dest" || { eend; return 1; }
|
|
|
|
else
|
|
|
|
# mise à jour
|
|
|
|
estep "Maj dépôt $url:$branch --> $dest"
|
|
|
|
setx cwd=pwd
|
|
|
|
cd "$dest"
|
|
|
|
git fetch --all -p -f || { eend; return 1; }
|
|
|
|
git reset --hard "$origin/$branch" || { eend; return 1; }
|
|
|
|
cd "$cwd"
|
|
|
|
fi
|
|
|
|
|
|
|
|
if [ -z "$type" ]; then
|
|
|
|
if [ -f "$dest/composer.json" ]; then
|
|
|
|
type=composer
|
|
|
|
else
|
|
|
|
type=inconnu
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
estep "Type de dépôt: $type"
|
|
|
|
if [ "$type" == composer ]; then
|
|
|
|
composer=/usr/bin/composer
|
|
|
|
[ -x "$dest/composer.phar" ] && composer="$dest/composer.phar"
|
|
|
|
|
|
|
|
estep "Installation des dépendances composer"
|
|
|
|
"$composer" -d"$dest" install ${PRODUCTION:+--no-dev -o} || { eend; return 1; }
|
|
|
|
fi
|
|
|
|
|
|
|
|
for after_update in "${after_updates[@]}"; do
|
|
|
|
if [ "${after_update#/}" != "$after_update" ]; then
|
|
|
|
# commande absolue, la lancer telle quelle
|
|
|
|
estep "$after_update"
|
|
|
|
eval "$after_update" || { eend; return 1; }
|
|
|
|
elif [ "${after_update#./}" != "$after_update" ]; then
|
|
|
|
# commande relative, la lancer telle quelle
|
|
|
|
estep "$after_update"
|
|
|
|
eval "$after_update" || { eend; return 1; }
|
|
|
|
else
|
|
|
|
# c'est une fonction update_apps_func_*
|
|
|
|
estep "$after_update"
|
|
|
|
eval "update_apps_func_$after_update" || { eend; return 1; }
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
|
|
|
|
eend
|
|
|
|
done
|
|
|
|
eend
|
|
|
|
}
|
|
|
|
|
2018-10-08 11:50:56 +04:00
|
|
|
function initialize_build_env() {
|
|
|
|
CTXDIR=.
|
|
|
|
NAME=
|
|
|
|
TAGS=(latest)
|
|
|
|
VERSION=
|
|
|
|
}
|
2018-10-09 10:02:57 +04:00
|
|
|
function default_update_build_env() {
|
|
|
|
[ -n "$VERSION" ] || docker_add_build_arg VERSION "$(get_version)"
|
|
|
|
[ -n "$VERSION" ] && TAGS+=("$VERSION")
|
|
|
|
}
|
2018-10-08 11:50:56 +04:00
|
|
|
function update_build_env() { default_update_build_env; }
|
|
|
|
|
2018-09-27 21:00:45 +04:00
|
|
|
function default_compose_build() {
|
2018-11-19 09:56:04 +04:00
|
|
|
${FAKE:+qvals} docker-compose \
|
2018-09-27 21:00:45 +04:00
|
|
|
"${replace_env_args[@]}" "${env_args[@]}" \
|
2018-11-16 21:22:05 +04:00
|
|
|
build \
|
|
|
|
${NO_CACHE:+--no-cache} \
|
|
|
|
"${replace_build_args[@]}" "${build_args[@]}" \
|
2018-09-27 21:00:45 +04:00
|
|
|
"$@"
|
|
|
|
}
|
|
|
|
function default_docker_build() {
|
2018-10-08 11:50:56 +04:00
|
|
|
local tag
|
|
|
|
for tag in "${TAGS[@]}"; do
|
|
|
|
replace_build_args+=(-t "$NAME:$tag")
|
|
|
|
done
|
2018-11-19 09:56:04 +04:00
|
|
|
${FAKE:+qvals} docker build \
|
2018-11-16 20:48:51 +04:00
|
|
|
${NO_CACHE:+--no-cache} \
|
2018-09-27 21:00:45 +04:00
|
|
|
"${replace_env_args[@]}" "${env_args[@]}" \
|
|
|
|
"${replace_build_args[@]}" "${build_args[@]}" \
|
|
|
|
"$@" "$CTXDIR"
|
|
|
|
}
|
2019-04-02 15:59:47 +04:00
|
|
|
function compose_build() {
|
|
|
|
[ -n "$BUILD_BUILD" ] || return 0
|
|
|
|
default_compose_build "$@"
|
|
|
|
}
|
|
|
|
function docker_build() {
|
|
|
|
[ -n "$BUILD_BUILD" ] || return 0
|
|
|
|
default_docker_build "$@"
|
|
|
|
}
|
2018-09-27 21:00:45 +04:00
|
|
|
function auto_build() {
|
|
|
|
local -a replace_env_args env_args
|
|
|
|
local -a replace_build_args build_args
|
2018-10-08 11:50:56 +04:00
|
|
|
initialize_build_env
|
2018-09-27 21:00:45 +04:00
|
|
|
if [ -f docker-compose.yml ]; then
|
|
|
|
compose_set_env_args
|
2018-10-08 11:50:56 +04:00
|
|
|
update_build_env
|
2019-04-02 15:59:47 +04:00
|
|
|
build_update_apps || return 1
|
2018-09-27 21:00:45 +04:00
|
|
|
compose_build
|
|
|
|
else
|
|
|
|
docker_parse_env_args
|
|
|
|
docker_check_name
|
|
|
|
docker_add_build_arg build_date "$(date +%y%m%d)"
|
2018-10-08 11:50:56 +04:00
|
|
|
update_build_env
|
2019-04-02 15:59:47 +04:00
|
|
|
build_update_apps || return 1
|
2018-09-27 21:00:45 +04:00
|
|
|
docker_build
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
2018-10-08 11:50:56 +04:00
|
|
|
function auto_push() {
|
2018-10-09 10:02:57 +04:00
|
|
|
local -a replace_env_args env_args
|
|
|
|
local -a replace_build_args build_args
|
|
|
|
local tag
|
2018-10-08 11:50:56 +04:00
|
|
|
initialize_build_env
|
2018-10-09 10:02:57 +04:00
|
|
|
if [ -f docker-compose.yml ]; then
|
|
|
|
compose_set_env_args
|
|
|
|
update_build_env
|
|
|
|
else
|
|
|
|
docker_parse_env_args
|
|
|
|
docker_check_name
|
|
|
|
update_build_env
|
|
|
|
fi
|
2018-10-08 11:50:56 +04:00
|
|
|
for tag in "${TAGS[@]}"; do
|
2018-11-19 09:56:04 +04:00
|
|
|
${FAKE:+qvals} docker push "$NAME:$tag"
|
2018-10-08 11:50:56 +04:00
|
|
|
done
|
|
|
|
}
|
|
|
|
|
2018-09-27 21:00:45 +04:00
|
|
|
function default_compose_up() {
|
2018-11-19 09:56:04 +04:00
|
|
|
${FAKE:+qvals} docker-compose \
|
2018-09-27 21:00:45 +04:00
|
|
|
"${replace_env_args[@]}" "${env_args[@]}" \
|
|
|
|
up "${replace_run_args[@]}" "${run_args[@]}" \
|
|
|
|
"${replace_user_args[@]}" "${user_args[@]}" "$@"
|
|
|
|
}
|
|
|
|
function default_docker_up() {
|
2018-11-19 09:56:04 +04:00
|
|
|
${FAKE:+qvals} docker run \
|
2018-09-27 21:00:45 +04:00
|
|
|
"${replace_env_args[@]}" "${env_args[@]}" \
|
|
|
|
"${replace_run_args[@]}" "${run_args[@]}" \
|
|
|
|
"$NAME" \
|
|
|
|
"${replace_user_args[@]}" "${user_args[@]}" "$@"
|
|
|
|
}
|
|
|
|
function compose_up() { default_compose_up "$@"; }
|
|
|
|
function docker_up() { default_docker_up "$@"; }
|
|
|
|
function auto_up() {
|
|
|
|
local -a replace_env_args env_args
|
|
|
|
local -a replace_run_args run_args
|
|
|
|
local -a replace_user_args user_args
|
2018-11-22 15:34:07 +04:00
|
|
|
local project_name container_name
|
2018-09-27 21:00:45 +04:00
|
|
|
if [ -f docker-compose.yml ]; then
|
|
|
|
compose_set_env_args
|
|
|
|
replace_run_args=(-d)
|
|
|
|
compose_up "$@"
|
|
|
|
else
|
|
|
|
docker_set_env_args
|
2018-11-22 15:34:07 +04:00
|
|
|
docker_check_name set_container_name
|
|
|
|
replace_run_args=(-d --name "$container_name")
|
2018-09-27 21:00:45 +04:00
|
|
|
docker_up "$@"
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
2019-03-28 10:53:50 +04:00
|
|
|
function default_compose_stop() {
|
|
|
|
${FAKE:+qvals} docker-compose \
|
|
|
|
"${replace_env_args[@]}" "${env_args[@]}" \
|
|
|
|
stop "${replace_stop_args[@]}" "${stop_args[@]}" \
|
|
|
|
"$@"
|
|
|
|
}
|
|
|
|
function default_docker_stop() {
|
|
|
|
${FAKE:+qvals} docker container stop \
|
|
|
|
"${replace_stop_args[@]}" "${stop_args[@]}" \
|
|
|
|
"$container_name" "$@"
|
|
|
|
}
|
|
|
|
function compose_stop() { default_compose_stop "$@"; }
|
|
|
|
function docker_stop() { default_docker_stop "$@"; }
|
|
|
|
function auto_stop() {
|
|
|
|
local -a replace_env_args env_args
|
|
|
|
local -a replace_stop_args stop_args
|
|
|
|
local project_name container_name
|
|
|
|
if [ -f docker-compose.yml ]; then
|
|
|
|
compose_set_env_args
|
|
|
|
compose_stop "$@"
|
|
|
|
else
|
|
|
|
docker_set_env_args
|
|
|
|
docker_check_name set_container_name
|
|
|
|
docker_stop "$@"
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
|
|
|
function default_compose_logs() {
|
|
|
|
${FAKE:+qvals} docker-compose \
|
|
|
|
"${replace_env_args[@]}" "${env_args[@]}" \
|
|
|
|
logs "${replace_logs_args[@]}" "${logs_args[@]}" \
|
|
|
|
"$@"
|
|
|
|
}
|
|
|
|
function default_docker_logs() {
|
|
|
|
${FAKE:+qvals} docker logs \
|
|
|
|
"${replace_logs_args[@]}" "${logs_args[@]}" \
|
|
|
|
"$container_name" "$@"
|
|
|
|
}
|
|
|
|
function compose_logs() { default_compose_logs "$@"; }
|
|
|
|
function docker_logs() { default_docker_logs "$@"; }
|
|
|
|
function auto_logs() {
|
|
|
|
local -a replace_env_args env_args
|
|
|
|
local -a replace_logs_args logs_args
|
|
|
|
local project_name container_name
|
|
|
|
if [ -f docker-compose.yml ]; then
|
|
|
|
compose_set_env_args
|
|
|
|
replace_logs_args=(-f)
|
|
|
|
compose_logs "$@"
|
|
|
|
else
|
|
|
|
docker_set_env_args
|
|
|
|
docker_check_name set_container_name
|
|
|
|
replace_logs_args=(-f)
|
|
|
|
docker_logs "$@"
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
|
|
|
function default_compose_down() {
|
|
|
|
${FAKE:+qvals} docker-compose \
|
|
|
|
"${replace_env_args[@]}" "${env_args[@]}" \
|
|
|
|
down "${replace_down_args[@]}" "${down_args[@]}" \
|
|
|
|
"$@"
|
|
|
|
}
|
|
|
|
function default_docker_down() {
|
|
|
|
estep "stop"
|
|
|
|
${FAKE:+qvals} docker container stop \
|
|
|
|
"${replace_down_args[@]}" "${down_args[@]}" \
|
|
|
|
"$container_name" "$@"
|
|
|
|
estep "rm"
|
|
|
|
${FAKE:+qvals} docker container rm \
|
|
|
|
"${replace_rm_args[@]}" "${rm_args[@]}" \
|
|
|
|
"$container_name"
|
|
|
|
}
|
|
|
|
function compose_down() { default_compose_down "$@"; }
|
|
|
|
function docker_down() { default_docker_down "$@"; }
|
|
|
|
function auto_down() {
|
|
|
|
local -a replace_env_args env_args
|
|
|
|
local -a replace_down_args down_args
|
|
|
|
local -a replace_rm_args rm_args
|
|
|
|
local project_name container_name
|
|
|
|
if [ -f docker-compose.yml ]; then
|
|
|
|
compose_set_env_args
|
|
|
|
compose_down "$@"
|
|
|
|
else
|
|
|
|
docker_set_env_args
|
|
|
|
docker_check_name set_container_name
|
|
|
|
docker_down "$@"
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
|
|
|
function default_compose_exec() {
|
|
|
|
${FAKE:+qvals} docker-compose \
|
|
|
|
"${replace_env_args[@]}" "${env_args[@]}" \
|
|
|
|
exec "${replace_exec_args[@]}" "${exec_args[@]}" \
|
|
|
|
"$@"
|
|
|
|
}
|
|
|
|
function default_docker_exec() {
|
|
|
|
${FAKE:+qvals} docker container exec \
|
|
|
|
"${replace_exec_args[@]}" "${exec_args[@]}" \
|
|
|
|
"$container_name" "$@"
|
|
|
|
}
|
|
|
|
function compose_exec() { default_compose_exec "$@"; }
|
|
|
|
function docker_exec() { default_docker_exec "$@"; }
|
|
|
|
function auto_exec() {
|
|
|
|
local -a replace_env_args env_args
|
|
|
|
local -a replace_exec_args exec_args
|
|
|
|
local project_name container_name
|
|
|
|
if [ -f docker-compose.yml ]; then
|
|
|
|
compose_set_env_args
|
|
|
|
compose_exec "$@"
|
|
|
|
else
|
|
|
|
docker_set_env_args
|
|
|
|
docker_check_name set_container_name
|
|
|
|
docker_exec "$@"
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
2018-11-22 15:34:07 +04:00
|
|
|
function default_compose_service() {
|
2019-01-14 16:09:03 +04:00
|
|
|
local docker_compose="$(which docker-compose 2>/dev/null)"
|
|
|
|
if [ -z "$docker_compose" ]; then
|
|
|
|
if [ -x /usr/bin/docker-compose ]; then
|
|
|
|
docker_compose=/usr/bin/docker-compose
|
|
|
|
elif [ -x /usr/local/bin/docker-compose ]; then
|
|
|
|
docker_compose=/usr/local/bin/docker-compose
|
|
|
|
else
|
|
|
|
die "Impossible de trouver docker-compose"
|
|
|
|
fi
|
2018-12-07 16:04:18 +04:00
|
|
|
fi
|
2018-11-22 15:34:07 +04:00
|
|
|
setx startcmd=qvals "$docker_compose" \
|
|
|
|
"${replace_env_args[@]}" "${env_args[@]}" \
|
|
|
|
up "${replace_run_args[@]}" "${run_args[@]}" \
|
|
|
|
"${replace_user_args[@]}" "${user_args[@]}" "$@"
|
|
|
|
setx stopcmd=qvals "$docker_compose" down
|
|
|
|
}
|
|
|
|
function default_docker_service() {
|
2019-01-14 16:09:03 +04:00
|
|
|
local docker="$(which docker 2>/dev/null)"
|
|
|
|
if [ -z "$docker" ]; then
|
|
|
|
if [ -x /usr/bin/docker ]; then
|
|
|
|
docker=/usr/bin/docker
|
|
|
|
elif [ -x /usr/local/bin/docker ]; then
|
|
|
|
docker=/usr/local/bin/docker
|
|
|
|
else
|
|
|
|
die "Impossible de trouver docker"
|
|
|
|
fi
|
2018-12-07 16:04:18 +04:00
|
|
|
fi
|
2018-11-22 15:34:07 +04:00
|
|
|
setx startcmd=qvals "$docker" run \
|
|
|
|
"${replace_env_args[@]}" "${env_args[@]}" \
|
|
|
|
"${replace_run_args[@]}" "${run_args[@]}" \
|
|
|
|
"$NAME" \
|
|
|
|
"${replace_user_args[@]}" "${user_args[@]}" "$@"
|
|
|
|
setx stopcmd=qvals "$docker" stop "$container_name"
|
|
|
|
}
|
|
|
|
function compose_service() { default_compose_service "$@"; }
|
|
|
|
function docker_service() { default_docker_service "$@"; }
|
|
|
|
function auto_service() {
|
|
|
|
local -a replace_env_args env_args
|
|
|
|
local -a replace_run_args run_args
|
|
|
|
local -a replace_user_args user_args
|
|
|
|
local project_name container_name startcmd stopcmd
|
|
|
|
local tmpscript; ac_set_tmpfile tmpscript
|
|
|
|
|
|
|
|
estep "Génération du service"
|
|
|
|
export COMPOSE_PROJECT_NAME=
|
|
|
|
if [ -f docker-compose.yml ]; then
|
|
|
|
compose_set_env_args set_container_name
|
|
|
|
replace_run_args=(-d --no-color)
|
|
|
|
compose_service "$@"
|
|
|
|
if [ -z "$HOST" -a -f .env ]; then
|
|
|
|
source ./.env
|
|
|
|
if [ -n "$PROFILE" ]; then
|
|
|
|
HOST="${PROFILE^^}_HOST"; HOST="${!HOST}"
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
else
|
|
|
|
docker_set_env_args
|
|
|
|
docker_check_name set_container_name
|
|
|
|
replace_run_args=(-d --name "$container_name")
|
|
|
|
docker_service "$@"
|
|
|
|
fi
|
|
|
|
[ -n "$COMPOSE_PROJECT_NAME" ] || COMPOSE_PROJECT_NAME="$project_name"
|
|
|
|
chmod 755 "$tmpscript"
|
|
|
|
cat >"$tmpscript" <<EOF
|
|
|
|
#!/bin/bash
|
|
|
|
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
|
|
|
|
cat >/etc/systemd/system/$container_name.service <<EOD
|
|
|
|
[Unit]
|
|
|
|
Description=$project_name stack ($PROFILE)
|
2018-12-01 23:04:28 +04:00
|
|
|
Requires=docker.service
|
|
|
|
After=docker.service
|
2018-11-22 15:34:07 +04:00
|
|
|
|
|
|
|
[Service]
|
|
|
|
Type=oneshot
|
|
|
|
RemainAfterExit=yes
|
|
|
|
WorkingDirectory=$(pwd)
|
|
|
|
Environment=$(qval "COMPOSE_PROJECT_NAME=$COMPOSE_PROJECT_NAME")
|
|
|
|
ExecStart=$startcmd
|
|
|
|
ExecStop=$stopcmd
|
|
|
|
TimeoutStopSec=300
|
|
|
|
|
|
|
|
[Install]
|
|
|
|
WantedBy=multi-user.target
|
|
|
|
EOD
|
|
|
|
systemctl daemon-reload
|
|
|
|
systemctl enable $container_name.service
|
|
|
|
EOF
|
|
|
|
|
|
|
|
estep "Installation du service"
|
|
|
|
local_run "$HOST" "$tmpscript"
|
|
|
|
}
|
|
|
|
|
2018-10-01 09:28:20 +04:00
|
|
|
DEFAULT_PROFILE=devel
|
2018-10-01 20:49:00 +04:00
|
|
|
PROFILE=
|
2018-11-16 16:25:33 +04:00
|
|
|
DM_PROFILES=()
|
2018-10-01 09:28:20 +04:00
|
|
|
set_defaults dk
|
2018-11-16 14:16:16 +04:00
|
|
|
export PROFILE
|
2018-10-01 09:28:20 +04:00
|
|
|
|
2018-11-16 16:25:33 +04:00
|
|
|
if progexists docker-machine; then
|
2018-11-16 20:48:51 +04:00
|
|
|
setx active_dm=docker-machine active 2>/dev/null
|
2018-11-16 16:25:33 +04:00
|
|
|
for dm_profile in "${DM_PROFILES[@]}"; do
|
|
|
|
splitpair "$dm_profile" dm profile
|
|
|
|
if [ "$dm" == "$active_dm" ]; then
|
|
|
|
DEFAULT_PROFILE="$profile"
|
|
|
|
break
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
fi
|
|
|
|
|
2018-09-27 21:00:45 +04:00
|
|
|
chdir=
|
2018-11-19 09:56:04 +04:00
|
|
|
FAKE=
|
2018-11-22 15:34:07 +04:00
|
|
|
NO_CACHE=
|
|
|
|
HOST=
|
2019-04-02 15:59:47 +04:00
|
|
|
update_apps_mode=ub
|
|
|
|
update_apps_origin=
|
|
|
|
update_apps_branch=
|
2018-10-08 11:50:56 +04:00
|
|
|
args=(
|
2018-09-27 21:00:45 +04:00
|
|
|
--help '$exit_with display_help'
|
|
|
|
-d:,--chdir: chdir=
|
2018-11-16 14:16:16 +04:00
|
|
|
-p:,--profile: PROFILE=
|
|
|
|
-P,--prod PROFILE=prod
|
|
|
|
-T,--test PROFILE=test
|
2018-11-19 09:56:04 +04:00
|
|
|
-n,--fake FAKE=1
|
2018-11-22 15:34:07 +04:00
|
|
|
-j,--no-cache NO_CACHE=1
|
|
|
|
-h:,--host: HOST=
|
2019-04-02 15:59:47 +04:00
|
|
|
-g,--ug,--no-update-apps update_apps_mode=b
|
|
|
|
-u,--uu,--update-apps-only update_apps_mode=u
|
|
|
|
--uo:,--update-apps-origin: update_apps_origin=
|
|
|
|
--ub:,--update-apps-branch: update_apps_branch=
|
2018-09-27 21:00:45 +04:00
|
|
|
)
|
|
|
|
parse_args "$@"; set -- "${args[@]}"
|
|
|
|
|
2018-09-27 21:51:33 +04:00
|
|
|
# construire par défaut
|
|
|
|
[ $# -eq 0 ] && set -- build
|
2018-11-16 14:16:16 +04:00
|
|
|
[ -n "$PROFILE" ] || PROFILE="$DEFAULT_PROFILE"
|
2018-10-01 09:28:20 +04:00
|
|
|
|
|
|
|
[ -n "$chdir" ] && { cd "$chdir" || die; }
|
2018-09-27 21:51:33 +04:00
|
|
|
|
2018-09-27 21:00:45 +04:00
|
|
|
while [ $# -gt 0 ]; do
|
|
|
|
[ "$1" == -- ] && { shift; continue; }
|
|
|
|
cmd="$1"; shift
|
|
|
|
case "$cmd" in
|
2018-09-27 21:46:24 +04:00
|
|
|
b|build)
|
2019-04-02 15:59:47 +04:00
|
|
|
build_set_options "$update_apps_mode" "$update_apps_origin" "$update_apps_branch"
|
2018-09-27 21:00:45 +04:00
|
|
|
[ -f .build.scripts.sh ] && source ./.build.scripts.sh
|
|
|
|
[ -f build.scripts.sh ] && source ./build.scripts.sh
|
|
|
|
args=()
|
|
|
|
while [ $# -gt 0 -a "$1" != -- ]; do
|
|
|
|
args+=("$1"); shift
|
|
|
|
done
|
2018-11-16 14:16:16 +04:00
|
|
|
enote "Profil $PROFILE"
|
2018-09-27 21:00:45 +04:00
|
|
|
auto_build "${args[@]}" || die
|
|
|
|
;;
|
2018-10-08 11:50:56 +04:00
|
|
|
push)
|
|
|
|
[ -f .build.scripts.sh ] && source ./.build.scripts.sh
|
|
|
|
[ -f build.scripts.sh ] && source ./build.scripts.sh
|
|
|
|
args=()
|
|
|
|
while [ $# -gt 0 -a "$1" != -- ]; do
|
|
|
|
args+=("$1"); shift
|
|
|
|
done
|
2018-11-16 14:16:16 +04:00
|
|
|
enote "Profil $PROFILE"
|
2018-10-08 11:50:56 +04:00
|
|
|
auto_push "${args[@]}" || die
|
|
|
|
;;
|
2018-09-27 21:46:24 +04:00
|
|
|
s|run|start)
|
2018-09-27 21:00:45 +04:00
|
|
|
args=()
|
|
|
|
while [ $# -gt 0 -a "$1" != -- ]; do
|
|
|
|
args+=("$1"); shift
|
|
|
|
done
|
2018-11-16 14:16:16 +04:00
|
|
|
enote "Profil $PROFILE"
|
2018-09-27 21:00:45 +04:00
|
|
|
auto_up "${args[@]}" || die
|
|
|
|
;;
|
2018-09-27 21:46:24 +04:00
|
|
|
k|stop)
|
2019-03-28 10:19:55 +04:00
|
|
|
args=()
|
|
|
|
while [ $# -gt 0 -a "$1" != -- ]; do
|
|
|
|
args+=("$1"); shift
|
|
|
|
done
|
2018-11-16 14:16:16 +04:00
|
|
|
enote "Profil $PROFILE"
|
2019-03-28 10:19:55 +04:00
|
|
|
auto_stop "${args[@]}" || die
|
2018-09-27 21:00:45 +04:00
|
|
|
;;
|
2018-09-27 21:46:24 +04:00
|
|
|
1|up)
|
2018-09-27 21:00:45 +04:00
|
|
|
args=()
|
|
|
|
while [ $# -gt 0 -a "$1" != -- ]; do
|
|
|
|
args+=("$1"); shift
|
|
|
|
done
|
2018-11-16 14:16:16 +04:00
|
|
|
enote "Profil $PROFILE"
|
2018-09-27 21:00:45 +04:00
|
|
|
auto_up "${args[@]}" && auto_logs || die
|
|
|
|
;;
|
2019-03-28 10:19:55 +04:00
|
|
|
l|logs)
|
|
|
|
args=()
|
|
|
|
while [ $# -gt 0 -a "$1" != -- ]; do
|
|
|
|
args+=("$1"); shift
|
|
|
|
done
|
|
|
|
enote "Profil $PROFILE"
|
|
|
|
auto_logs "${args[@]}" || die
|
|
|
|
;;
|
|
|
|
0|down)
|
|
|
|
args=()
|
|
|
|
while [ $# -gt 0 -a "$1" != -- ]; do
|
|
|
|
args+=("$1"); shift
|
|
|
|
done
|
|
|
|
enote "Profil $PROFILE"
|
|
|
|
auto_down "${args[@]}" || die
|
|
|
|
;;
|
2018-09-27 21:46:24 +04:00
|
|
|
d|brd)
|
2018-09-27 21:00:45 +04:00
|
|
|
do_auto_down=1
|
|
|
|
function auto_down_trap() {
|
|
|
|
[ -n "$do_auto_down" ] && auto_down
|
|
|
|
}
|
|
|
|
trap auto_down_trap 1 3 15 EXIT
|
|
|
|
|
2019-04-02 15:59:47 +04:00
|
|
|
build_set_options "$update_apps_mode" "$update_apps_origin" "$update_apps_branch"
|
2018-11-14 14:28:24 +04:00
|
|
|
[ -f .build.scripts.sh ] && source ./.build.scripts.sh
|
|
|
|
[ -f build.scripts.sh ] && source ./build.scripts.sh
|
2018-09-27 21:00:45 +04:00
|
|
|
args=()
|
|
|
|
while [ $# -gt 0 -a "$1" != -- ]; do
|
|
|
|
args+=("$1"); shift
|
|
|
|
done
|
2018-11-16 14:16:16 +04:00
|
|
|
enote "Profil $PROFILE"
|
2018-09-27 21:00:45 +04:00
|
|
|
if auto_build; then
|
|
|
|
auto_up "${args[@]}" && auto_logs || die
|
|
|
|
else
|
|
|
|
do_auto_down=
|
|
|
|
fi
|
|
|
|
;;
|
2018-12-09 22:33:07 +04:00
|
|
|
bs)
|
2019-04-02 15:59:47 +04:00
|
|
|
build_set_options "$update_apps_mode" "$update_apps_origin" "$update_apps_branch"
|
2018-12-09 22:33:07 +04:00
|
|
|
[ -f .build.scripts.sh ] && source ./.build.scripts.sh
|
|
|
|
[ -f build.scripts.sh ] && source ./build.scripts.sh
|
|
|
|
args=()
|
|
|
|
while [ $# -gt 0 -a "$1" != -- ]; do
|
|
|
|
args+=("$1"); shift
|
|
|
|
done
|
|
|
|
enote "Profil $PROFILE"
|
|
|
|
auto_build && auto_up "${args[@]}"
|
|
|
|
;;
|
2019-03-28 10:53:50 +04:00
|
|
|
x|exec)
|
|
|
|
args=()
|
|
|
|
while [ $# -gt 0 -a "$1" != -- ]; do
|
|
|
|
args+=("$1"); shift
|
|
|
|
done
|
|
|
|
enote "Profil $PROFILE"
|
|
|
|
auto_exec "${args[@]}" || die
|
|
|
|
;;
|
|
|
|
service)
|
|
|
|
args=()
|
|
|
|
while [ $# -gt 0 -a "$1" != -- ]; do
|
|
|
|
args+=("$1"); shift
|
|
|
|
done
|
|
|
|
enote "Profil $PROFILE"
|
|
|
|
auto_service "${args[@]}" || die
|
|
|
|
;;
|
2018-09-27 21:00:45 +04:00
|
|
|
ps) docker container ps -a || die;;
|
|
|
|
ls) docker image ls || die;;
|
|
|
|
rm)
|
|
|
|
args=()
|
|
|
|
while [ $# -gt 0 -a "$1" != -- ]; do
|
|
|
|
args+=("$1"); shift
|
|
|
|
done
|
|
|
|
docker image rm "${args[@]}" || die
|
|
|
|
;;
|
2018-09-27 21:46:24 +04:00
|
|
|
X|prune)
|
2018-09-27 21:00:45 +04:00
|
|
|
docker container prune -f || die
|
|
|
|
docker image prune -f || die
|
|
|
|
;;
|
|
|
|
*) die "$cmd: commande inconnue";;
|
|
|
|
esac
|
|
|
|
done
|