From 38d7ffca0b591694c17509d20c8bf55606e60536 Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Sun, 27 Oct 2013 15:07:31 +0100 Subject: app-ls-apps: o New command to list all applications installed under a directory. app-foreach-app: o New command to execute another command for each app installed under the current directory. app-init/app-install-file: o Adding -C and -c to prepand and append config files around the appliation's build-in configuration files. app-cat-conf: o Use $APP_HOME as the 'appliation installation directory' if set. app-operator-pid: o Support PID files created by the launcher. --- .gitignore | 1 + STYLE-GUIDE.md | 7 ++++- bin/app-foreach-app | 23 +++++++++++++++++ bin/app-init | 30 +++++++++++++++++++--- bin/app-ls-apps | 27 ++++++++++++++++++++ docs/app-cat-conf.txt | 5 ++++ docs/app-conf.txt | 5 ++++ docs/app-install-file.txt | 24 +++++++++++++++++ docs/app-operator-pid.txt | 27 ++++++++++++++++++++ docs/app.txt | 61 ++++++++++++++++++++++++++++++++++---------- docs/appinternals.txt | 8 ++++++ lib/common | 3 ++- libexec/app-install-file | 28 ++++++++++++++++++-- libexec/app-operator-pid | 65 ++++++++++++++++++++++++++++++++++++++++++----- 14 files changed, 287 insertions(+), 27 deletions(-) create mode 100755 bin/app-foreach-app create mode 100755 bin/app-ls-apps create mode 100644 docs/app-install-file.txt create mode 100644 docs/app-operator-pid.txt diff --git a/.gitignore b/.gitignore index 5299b29..b6d1d32 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ downloads target docs/*.html docs/*.1 +docs/*.7 .app/var /*/.gitignore diff --git a/STYLE-GUIDE.md b/STYLE-GUIDE.md index c4c3a66..207b988 100644 --- a/STYLE-GUIDE.md +++ b/STYLE-GUIDE.md @@ -18,7 +18,6 @@ because the user explicitly requested so. If the user gives some form of invalid argument or there is any other error the usage should go to stderr because the user might be using pipes. - How app.sh does it ------------------ @@ -44,6 +43,12 @@ Executing Commands * http://unix.stackexchange.com/q/23026 +Parsing options +=============== + +Applications should always check for extra options or define how +they're handled. + Resources --------- diff --git a/bin/app-foreach-app b/bin/app-foreach-app new file mode 100755 index 0000000..5b5b108 --- /dev/null +++ b/bin/app-foreach-app @@ -0,0 +1,23 @@ +#!/bin/bash + +set -e +set -u + +APPSH_HOME=$(cd $(dirname "$0")/.. && pwd) + +. $APPSH_HOME/lib/common +# HEADER END + +usage_text() { + echo "usage: $usage_app [args]" +} + +IFS=" " +app-ls-apps | while read app +do + unset IFS + (cd $app; "$@") | while read line + do + echo "$app: $line" + done +done diff --git a/bin/app-init b/bin/app-init index fb4f7cd..534a876 100755 --- a/bin/app-init +++ b/bin/app-init @@ -13,7 +13,9 @@ usage_text() { } dir= -while getopts "d:" opt +prepend_config= +append_config= +while getopts "d:C:c:" opt do case $opt in d) @@ -21,6 +23,24 @@ do shift 2 OPTIND=1 ;; + C) + prepend_config=$OPTARG + if [[ ! prepend_config =~ ^/ ]] + then + prepend_config="`pwd`/$prepend_config" + fi + shift 2 + OPTIND=1 + ;; + c) + append_config=$OPTARG + if [[ ! append_config =~ ^/ ]] + then + append_config="`pwd`/$append_config" + fi + shift 2 + OPTIND=1 + ;; esac done @@ -52,7 +72,7 @@ fi mkdir -p -- "$dir" "$dir/.app" ok=no -clean_dir=`cd "$dir">/dev/null; pwd` +clean_dir=`cd "$dir" && pwd` trap '[[ $ok == yes ]] || rm -rf "$clean_dir"' EXIT cd "$dir" @@ -74,6 +94,10 @@ echo "Resolved version to $resolved_version" "$resolver" download-version -v "$resolved_version" -f .app/latest.zip -app-install-file -v "$resolved_version" -f .app/latest.zip +app-install-file \ + -v "$resolved_version" \ + ${prepend_config:+-C "$prepend_config"} \ + ${append_config:+-c "$append_config"} \ + -f .app/latest.zip ok=yes diff --git a/bin/app-ls-apps b/bin/app-ls-apps new file mode 100755 index 0000000..4adc274 --- /dev/null +++ b/bin/app-ls-apps @@ -0,0 +1,27 @@ +#!/bin/bash + +set -e +set -u + +APPSH_HOME=$(cd $(dirname "$0")/.. && pwd) + +. $APPSH_HOME/lib/common +# HEADER END + +usage_text() { + echo "usage: $usage_app [dir]" +} + +case $# in + 0) + dir=* + ;; + 1) + dir="$1/*"; shift + ;; + *) + usage + ;; +esac + +find $dir -type d -name .app | sed "s,/\.app$,," diff --git a/docs/app-cat-conf.txt b/docs/app-cat-conf.txt index fe2a5b4..57fe693 100644 --- a/docs/app-cat-conf.txt +++ b/docs/app-cat-conf.txt @@ -68,4 +68,9 @@ SEE ALSO git-config(1) +APP.SH +------ + +Part of the linkman:app[1] suite. + // vim: set ft=asciidoc: diff --git a/docs/app-conf.txt b/docs/app-conf.txt index c686960..3afeda4 100644 --- a/docs/app-conf.txt +++ b/docs/app-conf.txt @@ -20,4 +20,9 @@ DESCRIPTION Interface to the configuration values used by 'app.sh'. Modelled after the 'git-config' command. 'list' is the default command +APP.SH +------ + +Part of the linkman:app[1] suite. + // vim: set ft=asciidoc: diff --git a/docs/app-install-file.txt b/docs/app-install-file.txt new file mode 100644 index 0000000..bb7cc48 --- /dev/null +++ b/docs/app-install-file.txt @@ -0,0 +1,24 @@ +app-install-file(1) +=================== + +NAME +---- +app-install-file - Low-level installation of an app + +SYNOPSIS +-------- +[verse] +'app-operator-pid' ... + +TODOs +----- + +Tests for prepending and appending configuration:: + Missing. + +APP.SH +------ + +Part of the linkman:app[1] suite. + +// vim: set ft=asciidoc: diff --git a/docs/app-operator-pid.txt b/docs/app-operator-pid.txt new file mode 100644 index 0000000..9e0a454 --- /dev/null +++ b/docs/app-operator-pid.txt @@ -0,0 +1,27 @@ +app-operator-pid(1) +=================== + +NAME +---- +app-operator-pid - Controls the running instance of the app + +SYNOPSIS +-------- +[verse] +'app-operator-pid' ... + +TODOs +----- + +Support configurable signal to send on shutdown:: + TERM might be exessive for some apps. + +Tests for app.pid_management=launcher:: + Missing. + +APP.SH +------ + +Part of the linkman:app[1] suite. + +// vim: set ft=asciidoc: diff --git a/docs/app.txt b/docs/app.txt index c578c5d..9ab0ba7 100644 --- a/docs/app.txt +++ b/docs/app.txt @@ -10,28 +10,37 @@ SYNOPSIS [verse] 'app' +DOCUMENTATION +------------- + QUICK START ~~~~~~~~~~~ - $ app init -d my-app maven org.example:my-app:1.0-SNAPSHOT - $ cd my-app - $ app start - $ app conf set app.version 1.0 - $ app upgrade - $ app restart +------------------------------------------------------------------------ +$ app init -d my-app maven org.example:my-app:1.0-SNAPSHOT +$ cd my-app +$ app start +$ app conf set app.version 1.0 +$ app upgrade +$ app restart +------------------------------------------------------------------------ INSTALLING AN APPLICATION ~~~~~~~~~~~~~~~~~~~~~~~~~ This resolved and downloads an appliaction from a Maven repository: - $ app init -d my-app maven org.example:my-app:1.0-SNAPSHOT +------------------------------------------------------------------------ +$ app init -d my-app maven org.example:my-app:1.0-SNAPSHOT +------------------------------------------------------------------------ By default it will download from the central repository, but this is not always what you want. To get it to use another repository give the `-r` option: - $ app init -d my-app maven -f http://repo.example.org/snapshots org.example:my-app:1.0-SNAPSHOT +------------------------------------------------------------------------ +$ app init -d my-app maven -f http://repo.example.org/snapshots org.example:my-app:1.0-SNAPSHOT +------------------------------------------------------------------------ UPGRADING AN APPLICATION ~~~~~~~~~~~~~~~~~~~~~~~~ @@ -40,7 +49,9 @@ If your application is configured with the Maven resolver and the version is a SNAPSHOT version, you can use this to upgrade your application through a cron job: - $ app upgrade +------------------------------------------------------------------------ +$ app upgrade +------------------------------------------------------------------------ With the resolver will try to resolve `app.version` to the latest version. If it's change it will automatically download and install the @@ -49,12 +60,34 @@ latest version. CHANGING VERSION OF AN APPLICATION ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - $ app conf set app.version 1.0 - $ app sync-version +------------------------------------------------------------------------ +$ app conf set app.version 1.0 +$ app sync-version +------------------------------------------------------------------------ `app-sync-version` will first run the resolver to resolve the version and if that has changed, it will download and install the new version. +CREATING APPS +------------- + +TODO + +CREATING HOOKS +~~~~~~~~~~~~~~ + +TODO + +CREATING LAUNCHERS +~~~~~~~~~~~~~~~~~~ + +Trick when you don't know why your app won't start: + +------------------------------------------------------------------------ +exec 1>/tmp/myapp.out +exec 2>/tmp/myapp.err +------------------------------------------------------------------------ + TODOs ----- @@ -68,8 +101,10 @@ TODOs SEE ALSO -------- -linkman:app-conf[1], linkman:app-cat-conf[1], -linkman:appinternals[1], +linkman:app-conf[1], +linkman:app-install-file[1], +linkman:app-operator-pid[1], +linkman:appinternals[1] // vim: set ft=asciidoc: diff --git a/docs/appinternals.txt b/docs/appinternals.txt index 9291fa0..ce19923 100644 --- a/docs/appinternals.txt +++ b/docs/appinternals.txt @@ -33,6 +33,14 @@ ENVIRONMENT VARIABLES --------------------- `APPSH_HOME`:: + .. + `APP_HOME`:: + .. + +APP.SH +------ + +Part of the linkman:app[1] suite. // vim: set ft=asciidoc: diff --git a/lib/common b/lib/common index 663bf45..b52da43 100755 --- a/lib/common +++ b/lib/common @@ -208,7 +208,8 @@ _get_config_file_user() { } _get_config_file_app() { - eval $1=".app/config" + local home= + eval $1="${APP_HOME-.}/.app/config" } grep_path() { diff --git a/libexec/app-install-file b/libexec/app-install-file index e2707a0..db9432b 100755 --- a/libexec/app-install-file +++ b/libexec/app-install-file @@ -9,13 +9,15 @@ APPSH_HOME=$(cd $(dirname "$0")/.. && pwd) # HEADER END usage_text() { - echo "usage: $0 -v -f " + echo "usage: $0 -v -f [-C ] [-c ]" } version= file= +prepend_config= +append_config= -while getopts "v:f:" opt +while getopts "v:f:C:c:" opt do case $opt in v) @@ -28,6 +30,16 @@ do shift 2 OPTIND=1 ;; + C) + prepend_config=$OPTARG + shift 2 + OPTIND=1 + ;; + c) + append_config=$OPTARG + shift 2 + OPTIND=1 + ;; esac done @@ -53,12 +65,24 @@ then exit 1 fi +if [ -n "$prepend_config" ] +then + debug "Prepending config from $prepend_config" + app-conf import "$prepend_config" +fi + if [ -r versions/$version/app.config ] then debug "Importing config from package" app-conf import versions/$version/app.config fi +if [ -n "$append_config" ] +then + debug "Appending config from $append_config" + app-conf import "$append_config" +fi + app-run-hook -v "$version" -h pre-install app-set-version -v "$version" diff --git a/libexec/app-operator-pid b/libexec/app-operator-pid index db1da1f..71871de 100755 --- a/libexec/app-operator-pid +++ b/libexec/app-operator-pid @@ -23,7 +23,7 @@ do_status() { } find_launcher() { - launcher=`app-conf get app.launcher` + local launcher=`app-conf get app.launcher` if [ ! -z "$launcher" ] then @@ -59,8 +59,34 @@ find_launcher() { echo $launcher } +find_pid_management() { + pid_management=`app-conf get app.pid_management` + + if [[ $pid_management == "" ]] + then + echo "appsh" + return + fi + + case "$pid_management" in + launcher) + echo "$pid_management" + ;; + *) + fatal "Invalid app.pid_management: $pid_management" + ;; + esac +} + command_start() { launcher=`find_launcher` + set -x + echo pwd=`pwd` + pid_management=`find_pid_management` + + debug "launcher=$launcher" + debug "pid_management=$pid_management" + debug "pwd=`pwd`" case `do_status` in running) @@ -69,12 +95,37 @@ command_start() { ;; esac - echo "Starting app with $launcher, pwd=`pwd`" - $launcher <&- 1<&- 2<&- & - + echo "Starting app..." + $launcher <&- 1>&- 2>&- & + PID=$! - echo "Application launched as $PID" - echo $PID > $pid_file + + case "$pid_management" in + appsh) + echo "Application launched as $PID" + echo $PID > $pid_file + ;; + launcher) + launch_timeout=`app conf get app.launch_timeout` + if [[ ! $launch_timeout =~ [0-9] ]] + then + launch_timeout=10 + fi + # the PID file is managed by the launcher, so wait for it to show up + for ((x = 0; x < "$launch_timeout"; x++)) + do + echo "Waiting for PID to show up..." + sleep 1 + if [ -r $pid_file ] + then + return 0 + fi + done + + echo "Appliation failed to start" + return 1 + ;; + esac return 0 } @@ -94,7 +145,7 @@ command_stop() { ;; esac - echo -n "Sending kill TERM to $PID, waiting for shutdown" + echo -n "Sending TERM to $PID, waiting for shutdown" kill -TERM $PID for i in {1..10} -- cgit v1.2.3