From a961a20a1b9809a4898c50e4dee2994470536473 Mon Sep 17 00:00:00 2001 From: casjay Date: Fri, 10 Jul 2026 12:12:43 -0400 Subject: [PATCH] =?UTF-8?q?=F0=9F=93=9D=20Migrate=20/var/lib/srv=20docker?= =?UTF-8?q?=20paths=20to=20/srv=20in=20README=20=F0=9F=93=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update volume mount examples and dockerHome variable from the old /var/lib/srv/$USER/docker layout to /srv/$USER/docker. - README.md: update volume path references to /srv/$USER/docker README.md rootfs/usr/local/bin/copy rootfs/usr/local/bin/healthcheck rootfs/usr/local/bin/symlink --- README.md | 8 +- rootfs/usr/local/bin/copy | 112 +++++++------- rootfs/usr/local/bin/healthcheck | 249 +++++++++++++++++++++++++++++++ rootfs/usr/local/bin/symlink | 112 +++++++------- 4 files changed, 365 insertions(+), 116 deletions(-) create mode 100755 rootfs/usr/local/bin/healthcheck diff --git a/README.md b/README.md index fba2c13..2a8ee5a 100644 --- a/README.md +++ b/README.md @@ -19,8 +19,8 @@ dockermgr update enclosed ## Install and run container ```shell -dockerHome="/var/lib/srv/$USER/docker/casjaysdevdocker/enclosed/enclosed/latest/rootfs" -mkdir -p "/var/lib/srv/$USER/docker/enclosed/rootfs" +dockerHome="/srv/$USER/docker/casjaysdevdocker/enclosed/enclosed/latest/rootfs" +mkdir -p "/srv/$USER/docker/enclosed/rootfs" git clone "https://github.com/dockermgr/enclosed" "$HOME/.local/share/CasjaysDev/dockermgr/enclosed" cp -Rfva "$HOME/.local/share/CasjaysDev/dockermgr/enclosed/rootfs/." "$dockerHome/" docker run -d \ @@ -47,8 +47,8 @@ services: - TZ=America/New_York - HOSTNAME=enclosed volumes: - - "/var/lib/srv/$USER/docker/casjaysdevdocker/enclosed/enclosed/latest/rootfs/data:/data:z" - - "/var/lib/srv/$USER/docker/casjaysdevdocker/enclosed/enclosed/latest/rootfs/config:/config:z" + - "/srv/$USER/docker/casjaysdevdocker/enclosed/enclosed/latest/rootfs/data:/data:z" + - "/srv/$USER/docker/casjaysdevdocker/enclosed/enclosed/latest/rootfs/config:/config:z" ports: - 80:80 restart: always diff --git a/rootfs/usr/local/bin/copy b/rootfs/usr/local/bin/copy index 8227966..e9878d8 100755 --- a/rootfs/usr/local/bin/copy +++ b/rootfs/usr/local/bin/copy @@ -1,78 +1,78 @@ -#!/usr/bin/env bash -# shellcheck shell=bash -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -##@Version : 202408102055-git +#!/usr/bin/env sh +# shellcheck shell=sh +# - - - - - - - - - - - - - - - - - - - - - - - - - +##@Version : 202605051306-git # @@Author : Jason Hempstead # @@Contact : jason@casjaysdev.pro -# @@License : LICENSE.md +# @@License : WTFPL # @@ReadME : copy --help -# @@Copyright : Copyright: (c) 2024 Jason Hempstead, Casjays Developments -# @@Created : Saturday, Aug 10, 2024 20:55 EDT +# @@Copyright : Copyright: (c) 2026 Jason Hempstead, Casjays Developments +# @@Created : Tuesday, May 05, 2026 13:06 EDT # @@File : copy # @@Description : copies a file and shows progress -# @@Changelog : New script +# @@Changelog : Refactored for self-contained operation # @@TODO : Better documentation # @@Other : # @@Resource : # @@Terminal App : no # @@sudo/root : no -# @@Template : shell/bash -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# shellcheck disable=SC2016 -# shellcheck disable=SC2031 -# shellcheck disable=SC2120 -# shellcheck disable=SC2155 -# shellcheck disable=SC2199 -# shellcheck disable=SC2317 -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# script variables -APPNAME="$(basename "$0" 2>/dev/null)" -VERSION="202408102055-git" -RUN_USER="$USER" -SET_UID="$(id -u)" -SCRIPT_SRC_DIR="${BASH_SOURCE%/*}" -COPY_CWD="$(realpath "$PWD")" -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# script functions -if [ "$SHOW_RAW" != "true" ]; then - __printf_color() { printf "%b" "$(tput setaf "${2:-$DEFAULT_COLOR}" 2>/dev/null)" "$1\n" "$(tput sgr0 2>/dev/null)"; } +# @@Template : shell/sh +# - - - - - - - - - - - - - - - - - - - - - - - - - +# shellcheck disable=SC1001,SC1003,SC2001,SC2003,SC2016,SC2031,SC2090,SC2115,SC2120,SC2155,SC2199,SC2229,SC2317,SC2329 +# - - - - - - - - - - - - - - - - - - - - - - - - - +APPNAME="$(basename -- "$0" 2>/dev/null)" +# - - - - - - - - - - - - - - - - - - - - - - - - - +# colorization +if [ -n "$NO_COLOR" ]; then + __printf_color() { printf '%b' "$1\n" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; } else - # Disable colorization - __printf_color() { printf '%b\n' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; } + __printf_color() { { [ -z "$2" ] || DEFAULT_COLOR=$2; } && printf "%b" "$(tput setaf "$DEFAULT_COLOR" 2>/dev/null)" "$1\n" "$(tput sgr0 2>/dev/null)"; } fi -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# check for command -__cmd_exists() { which $1 >/dev/null 2>&1 || return 1; } -__function_exists() { builtin type $1 >/dev/null 2>&1 || return 1; } -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +# - - - - - - - - - - - - - - - - - - - - - - - - - +__unlink() { [ -L "$1" ] && rm -f -- "$1" >/dev/null; } +# - - - - - - - - - - - - - - - - - - - - - - - - - # custom functions - -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# Define Variables -DEFAULT_COLOR="7" -COPY_EXIT_STATUS=0 -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# Main application -{ [ $# -eq 2 ] || [ "$1" = "--help" ]; } || { __printf_color "Usage: $APPNAME fromFile toFile" && exit 1; } -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -is_link="$(ls -la "$2" 2>/dev/null | awk '{print $NF}')" -if [ "$1" != "$is_link" ]; then +__copy() { + exitCode=0 if [ -d "$1" ]; then + __printf_color "Copying $1/* to $2/" + __unlink "$2" mkdir -p "$2" - cp -Rf "$1/." "$2/" - COPY_EXIT_STATUS=$? - elif [ -e "$1" ]; then + for f in "$1"/* "$1"/.[!.]* "$1"/..?*; do + [ -e "$f" ] || [ -L "$f" ] || continue + base=$(basename -- "$f") + __copy "$f" "$2/$base" || exitCode=$? + done + elif [ -f "$1" ] || [ -L "$1" ]; then + __printf_color "Copying $1 to $2" + __unlink "$2" cp -Rf "$1" "$2" - COPY_EXIT_STATUS=$? - else - COPY_EXIT_STATUS=2 + exitCode=$? fi + return $exitCode +} +# - - - - - - - - - - - - - - - - - - - - - - - - - +# Define variables +DEFAULT_COLOR="254" +COPY_EXIT_STATUS=0 +# - - - - - - - - - - - - - - - - - - - - - - - - - +# Main application +if [ $# -ne 2 ]; then + __printf_color "USAGE: $APPNAME to from" "1" >&2 + COPY_EXIT_STATUS=1 +elif [ ! -e "$1" ]; then + __printf_color "$1 does not exist" >&2 + COPY_EXIT_STATUS=2 +else + __printf_color "Copying $1 to $2" "4" + __copy "$1" "$2" >/dev/null + COPY_EXIT_STATUS=$? fi -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +# - - - - - - - - - - - - - - - - - - - - - - - - - # End application -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +# - - - - - - - - - - - - - - - - - - - - - - - - - # lets exit with code -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +# - - - - - - - - - - - - - - - - - - - - - - - - - exit $COPY_EXIT_STATUS -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +# - - - - - - - - - - - - - - - - - - - - - - - - - # ex: ts=2 sw=2 et filetype=sh diff --git a/rootfs/usr/local/bin/healthcheck b/rootfs/usr/local/bin/healthcheck new file mode 100755 index 0000000..8dab380 --- /dev/null +++ b/rootfs/usr/local/bin/healthcheck @@ -0,0 +1,249 @@ +#!/usr/bin/env sh +# shellcheck shell=sh +# - - - - - - - - - - - - - - - - - - - - - - - - - +##@Version : 202605051654-git +# @@Author : Jason Hempstead +# @@Contact : jason@casjaysdev.pro +# @@License : WTFPL +# @@ReadME : healthcheck --help +# @@Copyright : Copyright: (c) 2026 Jason Hempstead, Casjays Developments +# @@Created : Tuesday, May 05, 2026 16:54 EDT +# @@File : healthcheck +# @@Description : Docker container healthcheck — HTTP/TCP/process/file checks +# @@Changelog : Rewrote as a real Docker HEALTHCHECK probe +# @@TODO : Better documentation +# @@Other : +# @@Resource : +# @@Terminal App : no +# @@sudo/root : no +# @@Template : shell/sh +# - - - - - - - - - - - - - - - - - - - - - - - - - +# shellcheck disable=SC1001,SC1003,SC2001,SC2003,SC2016,SC2031,SC2090,SC2115,SC2120,SC2155,SC2199,SC2229,SC2317,SC2329 +# - - - - - - - - - - - - - - - - - - - - - - - - - +APPNAME="$(basename -- "$0" 2>/dev/null)" +VERSION="202605051654-git" +# - - - - - - - - - - - - - - - - - - - - - - - - - +# Defaults (env vars override built-ins, CLI flags override env vars) +HEALTHCHECK_URL="${HEALTHCHECK_URL:-}" +HEALTHCHECK_HTTP_STATUS="${HEALTHCHECK_HTTP_STATUS:-2,3}" +HEALTHCHECK_HOST="${HEALTHCHECK_HOST:-127.0.0.1}" +HEALTHCHECK_PORT="${HEALTHCHECK_PORT:-}" +HEALTHCHECK_PROCESS="${HEALTHCHECK_PROCESS:-}" +HEALTHCHECK_FILE="${HEALTHCHECK_FILE:-}" +HEALTHCHECK_FILE_MAX_AGE="${HEALTHCHECK_FILE_MAX_AGE:-}" +HEALTHCHECK_TIMEOUT="${HEALTHCHECK_TIMEOUT:-5}" +HEALTHCHECK_VERBOSE="${HEALTHCHECK_VERBOSE:-}" +# - - - - - - - - - - - - - - - - - - - - - - - - - +__cmd_exists() { command -v "$1" >/dev/null 2>&1; } +__log() { [ -n "$HEALTHCHECK_VERBOSE" ] && printf '%s\n' "$*" >&2; return 0; } +__fail() { printf 'UNHEALTHY: %s\n' "$*" >&2; exit 1; } +# - - - - - - - - - - - - - - - - - - - - - - - - - +__usage() { + cat <&2; __usage >&2; exit 1 ;; + *) printf 'Unexpected argument: %s\n' "$1" >&2; exit 1 ;; + esac +done +# - - - - - - - - - - - - - - - - - - - - - - - - - +# Individual checks — each prints why it failed and exits 1 on failure +__trim() { printf '%s' "$1" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//'; } + +__check_one_http() { + url="$1"; accepted="$2"; timeout="$3" + if __cmd_exists curl; then + code="$(curl -ksSL -o /dev/null -w '%{http_code}' --max-time "$timeout" "$url" 2>/dev/null)" \ + || __fail "HTTP request to $url failed (curl error)" + elif __cmd_exists wget; then + code="$(wget -q -S --spider --timeout="$timeout" --tries=1 "$url" 2>&1 \ + | awk '/^ HTTP\// {c=$2} END {print c+0}')" + [ "$code" -gt 0 ] 2>/dev/null || __fail "HTTP request to $url failed (wget error)" + else + __fail "HTTP check requires curl or wget" + fi + IFS=',' + for prefix in $accepted; do + case "$code" in + "$prefix"*) unset IFS; __log "HTTP ok: $url -> $code"; return 0 ;; + esac + done + unset IFS + __fail "HTTP $url returned $code (expected prefix in: $accepted)" +} + +__check_http() { + urls="$1"; accepted="$2"; timeout="$3" + __log "HTTP: urls=$urls (timeout=${timeout}s, accept=${accepted})" + IFS=',' + for u in $urls; do + unset IFS + u="$(__trim "$u")" + [ -n "$u" ] || { IFS=','; continue; } + __check_one_http "$u" "$accepted" "$timeout" + IFS=',' + done + unset IFS + return 0 +} + +__check_one_tcp() { + host="$1"; port="$2"; timeout="$3" + if __cmd_exists nc; then + nc -z -w "$timeout" "$host" "$port" >/dev/null 2>&1 && { __log "TCP ok: $host:$port"; return 0; } + fi + if __cmd_exists ncat; then + ncat -z -w "${timeout}s" "$host" "$port" >/dev/null 2>&1 && { __log "TCP ok (ncat): $host:$port"; return 0; } + fi + # Last resort: bash /dev/tcp (only if bash is available; sh-only systems skip) + if __cmd_exists bash; then + bash -c "exec 3<>/dev/tcp/$host/$port" >/dev/null 2>&1 && { __log "TCP ok (bash): $host:$port"; return 0; } + fi + return 1 +} + +__check_tcp() { + host="$1"; ports="$2"; timeout="$3" + __log "TCP: host=$host ports=$ports (timeout=${timeout}s)" + IFS=',' + for p in $ports; do + unset IFS + p="$(__trim "$p")" + [ -n "$p" ] || { IFS=','; continue; } + __check_one_tcp "$host" "$p" "$timeout" || __fail "TCP $host:$p not reachable" + IFS=',' + done + unset IFS + return 0 +} + +__check_one_process() { + pattern="$1" + if __cmd_exists pgrep; then + # Match against process name (not full cmdline) so our own argv doesn't self-match + pgrep -- "$pattern" >/dev/null 2>&1 && return 0 + else + # Portable fallback: ps -o comm= prints just the command name + ps -e -o comm= 2>/dev/null | grep -v -e "^grep$" -e "^$APPNAME$" | grep -q -- "$pattern" && return 0 + fi + return 1 +} + +__check_process() { + patterns="$1" + __log "Process: patterns=$patterns" + IFS=',' + for p in $patterns; do + unset IFS + p="$(__trim "$p")" + [ -n "$p" ] || { IFS=','; continue; } + __check_one_process "$p" || __fail "Process not running: $p" + __log "Process ok: $p" + IFS=',' + done + unset IFS + return 0 +} + +__check_one_file() { + path="$1"; max_age="$2" + [ -e "$path" ] || __fail "File not found: $path" + if [ -n "$max_age" ]; then + now="$(date +%s)" + mtime="$(stat -c %Y "$path" 2>/dev/null || stat -f %m "$path" 2>/dev/null \ + || perl -e 'print((stat(shift))[9])' "$path" 2>/dev/null)" + [ -n "$mtime" ] || __fail "Cannot determine mtime of $path" + age=$(( now - mtime )) + [ "$age" -le "$max_age" ] || __fail "File $path is stale (age=${age}s, max=${max_age}s)" + fi + __log "File ok: $path" + return 0 +} + +__check_file() { + paths="$1"; max_age="$2" + __log "File: paths=$paths max_age=${max_age:-none}" + IFS=',' + for f in $paths; do + unset IFS + f="$(__trim "$f")" + [ -n "$f" ] || { IFS=','; continue; } + __check_one_file "$f" "$max_age" + IFS=',' + done + unset IFS + return 0 +} +# - - - - - - - - - - - - - - - - - - - - - - - - - +# Run checks +ran_any=0 +[ -n "$HEALTHCHECK_URL" ] && { __check_http "$HEALTHCHECK_URL" "$HEALTHCHECK_HTTP_STATUS" "$HEALTHCHECK_TIMEOUT"; ran_any=1; } +[ -n "$HEALTHCHECK_PORT" ] && { __check_tcp "$HEALTHCHECK_HOST" "$HEALTHCHECK_PORT" "$HEALTHCHECK_TIMEOUT"; ran_any=1; } +[ -n "$HEALTHCHECK_PROCESS" ] && { __check_process "$HEALTHCHECK_PROCESS"; ran_any=1; } +[ -n "$HEALTHCHECK_FILE" ] && { __check_file "$HEALTHCHECK_FILE" "$HEALTHCHECK_FILE_MAX_AGE"; ran_any=1; } + +[ "$ran_any" -eq 1 ] || __fail "no checks configured (set HEALTHCHECK_URL/PORT/PROCESS/FILE or pass --url/--port/--process/--file)" + +__log "All checks passed" +exit 0 +# - - - - - - - - - - - - - - - - - - - - - - - - - +# ex: ts=2 sw=2 et filetype=sh diff --git a/rootfs/usr/local/bin/symlink b/rootfs/usr/local/bin/symlink index 8bfb03e..ac2db15 100755 --- a/rootfs/usr/local/bin/symlink +++ b/rootfs/usr/local/bin/symlink @@ -1,13 +1,13 @@ -#!/usr/bin/env bash -# shellcheck shell=bash -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -##@Version : 202408102055-git +#!/usr/bin/env sh +# shellcheck shell=sh +# - - - - - - - - - - - - - - - - - - - - - - - - - +##@Version : 202605051306-git # @@Author : Jason Hempstead # @@Contact : jason@casjaysdev.pro -# @@License : LICENSE.md +# @@License : WTFPL # @@ReadME : symlink --help -# @@Copyright : Copyright: (c) 2024 Jason Hempstead, Casjays Developments -# @@Created : Saturday, Aug 10, 2024 20:55 EDT +# @@Copyright : Copyright: (c) 2026 Jason Hempstead, Casjays Developments +# @@Created : Tuesday, May 05, 2026 13:06 EDT # @@File : symlink # @@Description : # @@Changelog : New script @@ -16,62 +16,62 @@ # @@Resource : # @@Terminal App : no # @@sudo/root : no -# @@Template : shell/bash -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# shellcheck disable=SC2016 -# shellcheck disable=SC2031 -# shellcheck disable=SC2120 -# shellcheck disable=SC2155 -# shellcheck disable=SC2199 -# shellcheck disable=SC2317 -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# script variables -APPNAME="$(basename "$0" 2>/dev/null)" -VERSION="202408102055-git" -RUN_USER="$USER" -SET_UID="$(id -u)" -SCRIPT_SRC_DIR="${BASH_SOURCE%/*}" -SYMLINK_CWD="$(realpath "$PWD")" -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# script functions -if [ "$SHOW_RAW" != "true" ]; then - __printf_color() { printf "%b" "$(tput setaf "${2:-$DEFAULT_COLOR}" 2>/dev/null)" "$1\n" "$(tput sgr0 2>/dev/null)"; } +# @@Template : shell/sh +# - - - - - - - - - - - - - - - - - - - - - - - - - +# shellcheck disable=SC1001,SC1003,SC2001,SC2003,SC2016,SC2031,SC2090,SC2115,SC2120,SC2155,SC2199,SC2229,SC2317,SC2329 +# - - - - - - - - - - - - - - - - - - - - - - - - - +APPNAME="$(basename -- "$0" 2>/dev/null)" +# - - - - - - - - - - - - - - - - - - - - - - - - - +# colorization +if [ -n "$NO_COLOR" ]; then + __printf_color() { printf '%b' "$1\n" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; } else - # Disable colorization - __printf_color() { printf '%b\n' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; } + __printf_color() { { [ -z "$2" ] || DEFAULT_COLOR=$2; } && printf "%b" "$(tput setaf "$DEFAULT_COLOR" 2>/dev/null)" "$1\n" "$(tput sgr0 2>/dev/null)"; } fi -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# check for command -__cmd_exists() { which $1 >/dev/null 2>&1 || return 1; } -__function_exists() { builtin type $1 >/dev/null 2>&1 || return 1; } -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +# - - - - - - - - - - - - - - - - - - - - - - - - - +__unlink() { [ -L "$1" ] && rm -f -- "$1" >/dev/null; } +# - - - - - - - - - - - - - - - - - - - - - - - - - # custom functions - -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# Define Variables -DEFAULT_COLOR="7" -SYMLINK_EXIT_STATUS=0 -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# Main application -{ [ $# -eq 2 ] || [ "$1" = "--help" ]; } || { __printf_color "Usage: $APPNAME fromFile toFile" && exit 1; } -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -is_link="$(ls -la "$2" 2>/dev/null | awk '{print $NF}')" -if [ "$1" != "$is_link" ]; then - if [ -L "$2" ]; then - unlink "$2" - elif [ -e "$2" ]; then - rm -Rf "$2" - fi - if [ -e "$1" ]; then +__ln_sf() { + exitCode=0 + if [ -d "$1" ] && [ ! -L "$1" ]; then + __printf_color "symlinking contents of $1 into $2/" "4" + __unlink "$2" + mkdir -p "$2" + for f in "$1"/* "$1"/.[!.]* "$1"/..?*; do + [ -e "$f" ] || [ -L "$f" ] || continue + base=$(basename -- "$f") + __ln_sf "$f" "$2/$base" || exitCode=$? + done + else + __printf_color "symlinking $2 to $1" "4" + __unlink "$2" ln -sf "$1" "$2" - SYMLINK_EXIT_STATUS=$? + exitCode=$? fi + return $exitCode +} +# - - - - - - - - - - - - - - - - - - - - - - - - - +# Define variables +DEFAULT_COLOR="254" +SYMLINK_EXIT_STATUS=0 +# - - - - - - - - - - - - - - - - - - - - - - - - - +# Main application +if [ $# -ne 2 ]; then + __printf_color "USAGE: $APPNAME from to" "2" >&2 + SYMLINK_EXIT_STATUS=1 +elif [ ! -e "$1" ]; then + __printf_color "$1 does not exist" >&2 + SYMLINK_EXIT_STATUS=2 +else + __ln_sf "$1" "$2" >/dev/null + SYMLINK_EXIT_STATUS=$? fi -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +# - - - - - - - - - - - - - - - - - - - - - - - - - # End application -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +# - - - - - - - - - - - - - - - - - - - - - - - - - # lets exit with code -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +# - - - - - - - - - - - - - - - - - - - - - - - - - exit $SYMLINK_EXIT_STATUS -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +# - - - - - - - - - - - - - - - - - - - - - - - - - # ex: ts=2 sw=2 et filetype=sh