Skip to content

Instantly share code, notes, and snippets.

@JM1
Last active March 25, 2023 19:40
Show Gist options
  • Save JM1/ab8c3beea108ea14a6b8955050f36357 to your computer and use it in GitHub Desktop.
Save JM1/ab8c3beea108ea14a6b8955050f36357 to your computer and use it in GitHub Desktop.
#!/bin/sh
# vim:set tabstop=8 shiftwidth=4 expandtab:
# kate: space-indent on; indent-width 4;
# shellcheck disable=SC2039
#
# Copyright (c) 2016-2022 Jakob Meng, <jakobmeng@web.de>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# NOTE: declare local variables first and initialize them later because return code of "local ..." is always 0
set -e
#set -x
prg=$(basename "$0")
version() {
cat << ____EOF
$prg version 0.5
Copyright (c) 2016-2022 Jakob Meng, <jakobmeng@web.de>
____EOF
}
help() {
cat << ____EOF
Usage: $prg [OPTIONS] COMMAND [arg...]
$prg [ --help | -v | --version ]
A helper script for docker.
Options:
-h, --help Print usage
-v, --version Print version information and quit
Commands:
attach Attach to a running container
db_add_tag Add tag for (all) images stored in database
db_build Build (all) images stored in database
db_example Show database example
db_pull Pull (all) images stored in database from Docker Hub
db_push Push (all) images stored in database to Docker Hub
rm Remove one or more containers
rmi Remove one or more images
save Save one or more images to a tar archive (streamed to STDOUT by default)
start Start one or more stopped containers
stop Stop one or more running containers
try_attach Try to attach to a running container else run new process in a container first
try_exec Try to run a new process in an existing container else run and pause a container first
help Print usage
Run '$prg COMMAND --help' for more information on a command.
____EOF
}
stderr() {
local _msg
while read -r _msg
do
echo "$_msg" 1>&2
done
}
error() {
stderr << ____EOF
ERROR: $*
____EOF
}
warn() {
stderr << ____EOF
WARN: $*
____EOF
}
attach() {
help() {
cat << ________EOF
Usage: $prg attach [OPTIONS] [CONTAINER]
Attach to a running container
Options:
--debug Print commands issued by $prg
-l, --latest Attach to latest created container
-o OPTION Pass additional options to docker
-h, --help Print usage
________EOF
}
local _latest="no"
local _options=""
local _ctnr=""
local _debug=""
if [ $# -eq 0 ]; then
stderr << ________EOF
"$prg attach" requires at least 1 argument(s).
See '$prg attach --help'.
Usage: $prg attach [OPTIONS] [CONTAINER]
Attach to a running container
________EOF
return 255
fi
while [ -n "$1" ]; do
case "$1" in
"--debug")
_debug="yes"
;;
"-l"|"--latest")
_latest="yes"
;;
"-o")
if [ -z "$2" ]; then
error "flag is missing arg: -o"
return 255
fi
_options="$_options $2"
shift
;;
"-h"|"--help")
help
return 0
;;
-*)
error "unknown flag: $1"
return 255
;;
*)
if [ -n "$_ctnr" ]; then
error "CONTAINER has already been set to $_ctnr."
return 255
fi
_ctnr="$1"
;;
esac
shift
done
local _cmd="docker attach "
_cmd="$_cmd $_options"
if [ "$_latest" = "yes" ]; then
local _lc
_lc="$(docker ps -q -l)"
if [ "$_lc" = "" ]; then
error "No container found."
return 255
fi
if [ "$_ctnr" != "" ]; then
error "CONTAINER and flag '-l' are mutual exclusive."
return 255
fi
_ctnr="$_lc"
fi
if [ "$_ctnr" = "" ]; then
error "No container specified."
return 255
fi
_cmd="$_cmd $_ctnr "
(
[ "$_debug" = "yes" ] && set -x
# shellcheck disable=2086
eval $_cmd
)
}
_test_db() {
local _db="$1"
if [ -z "$_db" ]; then
error "No image database given."
return 255
fi
if [ ! -e "$_db" ]; then
error "Database '$_db' does not exist."
return 255
fi
if ! which jq >/dev/null 2>&1; then
error "'jq' not found. On Debian or its derivatives run: sudo apt-get install jq"
return 255
fi
if ! jq -e . >/dev/null 2>&1 "$_db"; then
error "Failed to parse Database '$_db'."
return 255
fi
return 0
}
_foreach_image_in_db() {
local _db="$1"
local _included_images="$2"
local _f="$3"
shift 3
local _f_args
_f_args=$(printf " '%s'" "$@")
local _db_length
_db_length="$(jq '.|length' "$_db")"
#if [ "$_db_length" -eq 0 ]; then
# error "Database is empty."
# return 255
#fi
(
local _db_directory
_db_directory="$(dirname "$(readlink -e "$_db")")"
cd "$_db_directory" # allows shorter relative paths in db
for i in $(seq 0 $(("$_db_length"-1))); do
local _entry
_entry="$(jq ".[$i]" "$_db")"
local _user
local _name
local _tag
local _path
local _add
local _pull
for key in user name tag path add pull; do
if echo "$_entry" | jq -e "has(\"$key\")" >/dev/null; then
local _tmp;
_tmp="$(echo "$_entry" | jq --raw-output ".[\"$key\"]")"
eval _$key="\$_tmp" # \$_tmp is required to not eval contents of _tmp
else
eval _$key=""
fi
done
if [ -z "$_user" ]; then
error "Image tag name is missing <user> in <user>/<name>:<tag>"
return 255
fi
if [ -z "$_name" ]; then
error "Image tag name is missing <name> in <user>/<name>:<tag>"
return 255
fi
if [ -z "$_tag" ]; then
warn "Image tag name is missing <tag> in <user>/<name>:<tag>, falling back to tag 'latest'"
_tag="latest"
fi
if [ -z "$_pull" ]; then
_pull="false"
elif [ "$_pull" != "true" ] && [ "$_pull" != "false" ]; then
error "Key 'pull' must be 'true' or 'false'"
return 255
fi
if [ -n "$_included_images" ] && ! (
(echo "$_included_images" | grep -w "$_name" >/dev/null) ||
(echo "$_included_images" | grep -w "$_user/$_name" >/dev/null) ||
(echo "$_included_images" | grep -w "$_user/$_name:$_tag" >/dev/null)
); then
continue
fi
if [ -n "$_add" ]; then
# json to string list
local _add_length
_add_length="$(echo "$_add" | jq '.|length')"
local _tmp=""
for j in $(seq 0 $(("$_add_length"-1))); do
local _add_entry
_add_entry="$(echo "$_add" | jq --raw-output ".[$j]")"
_tmp="$_tmp '$_add_entry'"
done
_add="$_tmp"
fi
eval set -- "$_f_args"
$_f "$_user" "$_name" "$_tag" "$_path" "$_add" "$_pull" "$@"
set --
done
)
}
db_add_tag() {
help() {
cat << ________EOF
Usage: $prg db_add_tag [OPTIONS] DB TAG [IMAGE...]
Add tag for (all) images stored in database
Options:
--source-tag TAG Override tag from database
--debug Print commands issued by $prg
-h, --help Print usage
________EOF
}
local _source_tag=""
local _db=""
local _target_tag=""
local _imgs=""
local _debug=""
if [ $# -le 1 ]; then
stderr << ________EOF
"$prg db_add_tag" requires at least 2 argument(s).
See '$prg db_add_tag --help'.
Usage: $prg db_add_tag [OPTIONS] DB TAG [IMAGE...]
Add tag for (all) images stored in database
________EOF
return 255
fi
while [ -n "$1" ]; do
case "$1" in
"--source-tag")
if [ -z "$2" ]; then
error "flag is missing arg: --source-tag"
return 255
fi
_source_tag="$2"
shift
;;
"--debug")
_debug="yes"
;;
"-h"|"--help")
help
return 0
;;
-*)
error "unknown flag: $1"
return 255
;;
*)
if [ -z "$2" ]; then
error "missing DB arg"
return 255
fi
_db="$1"
_target_tag="$2"
shift 2
_imgs="$*"
set -- 'FOR_NEXT_SHIFT_ONLY'
;;
esac
shift
done
add_tag() {
local _user="$1"
local _name="$2"
local _tag="$3"
local _path="$4"
local _add="$5"
local _pull="$6"
local _src_tag="$7"
local _tgt_tag="$8"
if [ -n "$_src_tag" ]; then
_tag="$_src_tag"
fi
echo "Adding $_user/$_name:$_tgt_tag to $_user/$_name:$_tag"
docker tag "$_user/$_name:$_tag" "$_user/$_name:$_tgt_tag"
}
_test_db "$_db"
_foreach_image_in_db "$_db" "$_imgs" add_tag "$_source_tag" "$_target_tag"
}
db_build() {
help() {
cat << ________EOF
Usage: $prg db_build [OPTIONS] DB [IMAGE...]
Build (all) images stored in database
Options:
--tag TAG Override tag from database
--force Do not use cache and pull newer version of the image
--debug Print commands issued by $prg
-h, --help Print usage
________EOF
}
local _tag=""
local _force=""
local _db=""
local _imgs=""
local _debug=""
if [ $# -eq 0 ]; then
stderr << ________EOF
"$prg db_build" requires at least 1 argument(s).
See '$prg db_build --help'.
Usage: $prg db_build [OPTIONS] DB [IMAGE...]
Build (all) images stored in database
________EOF
return 255
fi
while [ -n "$1" ]; do
case "$1" in
"--tag")
if [ -z "$2" ]; then
error "flag is missing arg: --tag"
return 255
fi
_tag="$2"
shift
;;
"--force")
_force="yes"
;;
"--debug")
_debug="yes"
;;
"-h"|"--help")
help
return 0
;;
-*)
error "unknown flag: $1"
return 255
;;
*)
_db="$1"
shift
_imgs="$*"
set -- 'FOR_NEXT_SHIFT_ONLY'
;;
esac
shift
done
build_image() {
local _user="$1"
local _name="$2"
local _tag="$3"
local _path="$4"
local _add="$5"
local _pull="$6"
local _override_tag="$7"
local _force="$8"
if [ -n "$_override_tag" ]; then
_tag="$_override_tag"
fi
[ -n "$_pull" ] || return 255 # assert
local _no_cache=false
if [ "$_force" = "yes" ]; then
_pull=true
_no_cache=true
fi
local _fail=no
local _tmpdir=""
if [ -n "$_add" ]; then
_tmpdir="$(mktemp --tmpdir --directory "docker_build_img_$(date +%Y%m%d%H%M%S).XXXXXX")"
fi
set +e # workaround for https://stackoverflow.com/a/19789651/6490710
(
set -e
if [ -n "$_add" ]; then
eval set -- "$_add"
for req in \
"$_path"/* \
"$_path"/.[^.]* \
"$@" \
; do
cp -ran "$req" "$_tmpdir/"
done
set --
cd "$_tmpdir"
else
cd "$_path"
fi
echo "Building $_user/$_name:$_tag in $PWD"
docker build --pull=$_pull --no-cache=$_no_cache -t "$_user/$_name:$_tag" .
)
local errc=$?
set -e
[ $errc -ne 0 ] && _fail=yes
# first remove temporary dir and ...
if [ -n "$_tmpdir" ] && [ -d "$_tmpdir" ]; then
command rm -r "$_tmpdir" # command rm and not function rm
fi
# ... then return on error
if [ "$_fail" = "yes" ]; then
return 255
fi
}
_test_db "$_db"
_foreach_image_in_db "$_db" "$_imgs" build_image "$_tag" "$_force"
}
db_example() {
help() {
cat << ________EOF
Usage: $prg db_example [OPTIONS]
Show database example
Options:
-h, --help Print usage
________EOF
}
while [ -n "$1" ]; do
case "$1" in
"-h"|"--help")
help
return 0
;;
*)
error "unknown flag: $1"
return 255
;;
esac
shift
done
cat << '____EOF'
[
{ "user": "my-docker-id", "name": "my-debian-image", "tag": "latest", "path": "folder/with/Dockerfile", "pull": "true" },
{ "user": "my-docker-id", "name": "my-other-debian-image", "tag": "latest", "path": "relative/path/to/Dockerfile/directory", "pull": "false" },
{ "user": "my-docker-id", "name": "yet-another-image", "tag": "local", "path": "/absolute/path/to/Dockerfile/directory", "pull": "false",
"add": [ "/external/files/required/by/Dockerfile", "relative/path/to/db.json/" ] }
]
____EOF
return 0
}
db_pull() {
help() {
cat << ________EOF
Usage: $prg db_pull [OPTIONS] DB [IMAGE...]
Pull (all) images stored in database from Docker Hub
Options:
--tag TAG Override tag from database
--debug Print commands issued by $prg
-h, --help Print usage
________EOF
}
local _tag=""
local _db=""
local _imgs=""
local _debug=""
if [ $# -eq 0 ]; then
stderr << ________EOF
"$prg db_pull" requires at least 1 argument(s).
See '$prg db_pull --help'.
Usage: $prg db_pull [OPTIONS] DB [IMAGE...]
Pull (all) images stored in database from Docker Hub
________EOF
return 255
fi
while [ -n "$1" ]; do
case "$1" in
"--tag")
if [ -z "$2" ]; then
error "flag is missing arg: --tag"
return 255
fi
_tag="$2"
shift
;;
"--debug")
_debug="yes"
;;
"-h"|"--help")
help
return 0
;;
-*)
error "unknown flag: $1"
return 255
;;
*)
_db="$1"
shift
_imgs="$*"
set -- 'FOR_NEXT_SHIFT_ONLY'
;;
esac
shift
done
pull_image() {
local _user="$1"
local _name="$2"
local _tag="$3"
local _path="$4"
local _add="$5"
local _pull="$6"
local _override_tag="$7"
if [ -n "$_override_tag" ]; then
_tag="$_override_tag"
fi
echo "Pulling $_user/$_name:$_tag"
docker pull "$_user/$_name:$_tag"
}
_test_db "$_db"
_foreach_image_in_db "$_db" "$_imgs" pull_image "$_tag"
}
db_push() {
help() {
cat << ________EOF
Usage: $prg db_push [OPTIONS] DB [IMAGE...]
Push (all) images stored in database to Docker Hub
Options:
--tag TAG Override tag from database
--debug Print commands issued by $prg
-h, --help Print usage
________EOF
}
local _tag=""
local _db=""
local _imgs=""
local _debug=""
if [ $# -eq 0 ]; then
stderr << ________EOF
"$prg db_push" requires at least 1 argument(s).
See '$prg db_push --help'.
Usage: $prg db_push [OPTIONS] DB [IMAGE...]
Push (all) images stored in database to Docker Hub
________EOF
return 255
fi
while [ -n "$1" ]; do
case "$1" in
"--tag")
if [ -z "$2" ]; then
error "flag is missing arg: --tag"
return 255
fi
_tag="$2"
shift
;;
"--debug")
_debug="yes"
;;
"-h"|"--help")
help
return 0
;;
-*)
error "unknown flag: $1"
return 255
;;
*)
_db="$1"
shift
_imgs="$*"
set -- 'FOR_NEXT_SHIFT_ONLY'
;;
esac
shift
done
push_image() {
local _user="$1"
local _name="$2"
local _tag="$3"
local _path="$4"
local _add="$5"
local _pull="$6"
local _override_tag="$7"
if [ -n "$_override_tag" ]; then
_tag="$_override_tag"
fi
echo "Pushing $_user/$_name:$_tag"
docker push "$_user/$_name:$_tag"
}
_test_db "$_db"
docker login || {
error "login failed."
return 255
}
_foreach_image_in_db "$_db" "$_imgs" push_image "$_tag"
}
rm() {
help() {
cat << ________EOF
Usage: $prg rm [OPTIONS] [CONTAINER...]
Remove one or more containers
Options:
--debug Print commands issued by $prg
-a, --all Remove all existing containers
-l, --latest Remove latest created container
-o OPTION Pass additional options to docker
-h, --help Print usage
________EOF
}
local _all="no"
local _latest="no"
local _options=""
local _ctnrs=""
local _debug=""
if [ $# -eq 0 ]; then
stderr << ________EOF
"$prg rm" requires at least 1 argument(s).
See '$prg rm --help'.
Usage: $prg rm [OPTIONS] [CONTAINER...]
Remove one or more containers
________EOF
return 255
fi
while [ -n "$1" ]; do
case "$1" in
"--debug")
_debug="yes"
;;
"-a"|"--all")
_all="yes"
;;
"-l"|"--latest")
_latest="yes"
;;
"-o")
if [ -z "$2" ]; then
error "flag is missing arg: -o"
return 255
fi
_options="$_options $2"
shift
;;
"-h"|"--help")
help
return 0
;;
-*)
error "unknown flag: $1"
return 255
;;
*)
_ctnrs="$_ctnrs $*"
set -- 'FOR_NEXT_SHIFT_ONLY'
;;
esac
shift
done
local _cmd="docker rm "
_cmd="$_cmd $_options"
if [ "$_all" = "yes" ]; then
local _leftover
_leftover="$(docker ps -aq)"
[ "$_leftover" != "" ] && _ctnrs="$_ctnrs $_leftover"
fi
if [ "$_latest" = "yes" ]; then
local _leftover
_leftover="$(docker ps -q -l)"
[ "$_leftover" != "" ] && _ctnrs="$_ctnrs $_leftover"
fi
if [ "$(echo "$_ctnrs" | tr -d '[:space:]')" = "" ]; then
echo "No containers found."
return 0
fi
_cmd="$_cmd $_ctnrs "
(
[ "$_debug" = "yes" ] && set -x
# shellcheck disable=2086
eval $_cmd
)
}
rmi() {
help() {
cat << ________EOF
Usage: $prg rmi [OPTIONS] [IMAGE...]
Remove one or more images
Options:
--all Remove all images
--debug Print commands issued by $prg
--untagged Remove all untagged images
-o OPTION Pass additional options to docker
-h, --help Print usage
________EOF
}
local _all="no"
local _untagged="no"
local _options=""
local _imgs=""
local _debug=""
if [ $# -eq 0 ]; then
stderr << ________EOF
"$prg rmi" requires at least 1 argument(s).
See '$prg rmi --help'.
Usage: $prg rmi [OPTIONS] [IMAGE...]
Remove one or more images
________EOF
return 255
fi
while [ -n "$1" ]; do
case "$1" in
"--all")
_all="yes"
;;
"--debug")
_debug="yes"
;;
"--untagged")
_untagged="yes"
;;
"-o")
if [ -z "$2" ]; then
error "flag is missing arg: -o"
return 255
fi
_options="$_options $2"
shift
;;
"-h"|"--help")
help
return 0
;;
-*)
error "unknown flag: $1"
return 255
;;
*)
_imgs="$_imgs $*"
set -- 'FOR_NEXT_SHIFT_ONLY'
;;
esac
shift
done
if [ "$_all" = "yes" ]; then
docker image prune --force
fi
local _cmd="docker rmi "
_cmd="$_cmd $_options"
if [ "$_all" = "yes" ]; then
local _ui
_ui="$(docker images | tail -n +2 | grep -v "^<none>" | awk '{ print $1 ":" $2 }' | grep -v -e '.*\:<none>$')"
if [ "$_ui" = "" ] && [ "$_imgs" = "" ]; then
return 0
fi
_imgs="$_imgs $_ui"
fi
if [ "$_untagged" = "yes" ] || [ "$_all" = "yes" ]; then
#Ref.: http://jimhoskins.com/2013/07/27/remove-untagged-docker-images.html
local _ui
_ui="$(docker images | tail -n +2 | grep "^<none>" | awk '{ print $3 }')"
if [ "$_ui" = "" ] && [ "$_imgs" = "" ]; then
return 0
fi
_imgs="$_imgs $_ui"
fi
if [ "$_imgs" = "" ]; then
error "No images specified."
return 255
fi
_cmd="$_cmd $_imgs "
(
[ "$_debug" = "yes" ] && set -x
# shellcheck disable=2086
eval $_cmd
)
}
save() {
help() {
cat << ________EOF
Usage: $prg save [OPTIONS] [IMAGE...]
Save one or more images to a tar archive (streamed to STDOUT by default)
Options:
--debug Print commands issued by $prg
-a, --all Save all available images
--tagged Only save tagged images
-o OPTION Pass additional options to docker
-h, --help Print usage
________EOF
}
local _all="no"
local _tagged="no"
local _options=""
local _imgs=""
local _debug=""
if [ $# -eq 0 ]; then
stderr << ________EOF
"$prg save" requires at least 1 argument(s).
See '$prg save --help'.
Usage: $prg save [OPTIONS] [IMAGE...]
Save one or more images to a tar archive (streamed to STDOUT by default)
________EOF
return 255
fi
while [ -n "$1" ]; do
case "$1" in
"--debug")
_debug="yes"
;;
"-a"|"--all")
_all="yes"
;;
"--tagged")
_tagged="yes"
;;
"-o")
if [ -z "$2" ]; then
error "flag is missing arg: -o"
return 255
fi
_options="$_options $2"
shift
;;
"-h"|"--help")
help
return 0
;;
-*)
error "unknown flag: $1"
return 255
;;
*)
_imgs="$_imgs $*"
set -- 'FOR_NEXT_SHIFT_ONLY'
;;
esac
shift
done
local _cmd="docker save "
_cmd="$_cmd $_options"
if [ "$_all" = "yes" ]; then
local _ai
_ai="$(docker images -q | uniq)"
if [ "$_ai" = "" ]; then
error "No images found."
return 255
fi
_imgs="$_imgs $_ai"
fi
if [ "$_tagged" = "yes" ] && [ "$_all" = "no" ]; then
local _ti
_ti="$(docker images | tail -n +2 | grep -v "^<none>" | awk '{ print $1 ":" $2 }' | grep -v -e '.*\:<none>$')"
_imgs="$_imgs $_ti"
fi
if [ "$_imgs" = "" ]; then
error "No image specified."
return 255
fi
_cmd="$_cmd $_imgs "
(
[ "$_debug" = "yes" ] && set -x
# shellcheck disable=2086
eval $_cmd
)
}
start() {
help() {
cat << ________EOF
Usage: $prg start [OPTIONS] [CONTAINER...]
Start one or more containers
Options:
--debug Print commands issued by $prg
-a, --all Start all containers
-l, --latest Start latest created container
-o OPTION Pass additional options to docker
-h, --help Print usage
________EOF
}
local _all="no"
local _latest="no"
local _options=""
local _ctnrs=""
local _debug=""
if [ $# -eq 0 ]; then
stderr << ________EOF
"$prg start" requires at least 1 argument(s).
See '$prg start --help'.
Usage: $prg start [OPTIONS] [CONTAINER...]
Start one or more containers
________EOF
return 255
fi
while [ -n "$1" ]; do
case "$1" in
"--debug")
_debug="yes"
;;
"-a"|"--all")
_all="yes"
;;
"-l"|"--latest")
_latest="yes"
;;
"-o")
if [ -z "$2" ]; then
error "flag is missing arg: -o"
return 255
fi
_options="$_options $2"
shift
;;
"-h"|"--help")
help
return 0
;;
-*)
error "unknown flag: $1"
return 255
;;
*)
_ctnrs="$_ctnrs $*"
set -- 'FOR_NEXT_SHIFT_ONLY'
;;
esac
shift
done
local _cmd="docker start "
_cmd="$_cmd $_options"
if [ "$_all" = "yes" ]; then
local _ac
_ac="$(docker ps -q)"
if [ "$_ac" = "" ]; then
error "No container found."
return 255
fi
_ctnrs="$_ctnrs $_ac"
fi
if [ "$_latest" = "yes" ]; then
local _lc
_lc="$(docker ps -q -l)"
if [ "$_lc" = "" ]; then
error "No container found."
return 255
fi
_ctnrs="$_ctnrs $_lc"
fi
if [ "$_ctnrs" = "" ]; then
error "No container specified."
return 255
fi
_cmd="$_cmd $_ctnrs "
(
[ "$_debug" = "yes" ] && set -x
# shellcheck disable=2086
eval $_cmd
)
}
stop() {
help() {
cat << ________EOF
Usage: $prg stop [OPTIONS] [CONTAINER...]
Stop one or more containers
Options:
--debug Print commands issued by $prg
-a, --all Stop all containers
-l, --latest Stop latest created container
-o OPTION Pass additional options to docker
-h, --help Print usage
________EOF
}
local _all="no"
local _latest="no"
local _options=""
local _ctnrs=""
local _debug=""
if [ $# -eq 0 ]; then
stderr << ________EOF
"$prg stop" requires at least 1 argument(s).
See '$prg stop --help'.
Usage: $prg stop [OPTIONS] [CONTAINER...]
Stop one or more containers
________EOF
return 255
fi
while [ -n "$1" ]; do
case "$1" in
"--debug")
_debug="yes"
;;
"-a"|"--all")
_all="yes"
;;
"-l"|"--latest")
_latest="yes"
;;
"-o")
if [ -z "$2" ]; then
error "flag is missing arg: -o"
return 255
fi
_options="$_options $2"
shift
;;
"-h"|"--help")
help
return 0
;;
-*)
error "unknown flag: $1"
return 255
;;
*)
_ctnrs="$_ctnrs $*"
set -- 'FOR_NEXT_SHIFT_ONLY'
;;
esac
shift
done
local _cmd="docker stop "
_cmd="$_cmd $_options"
if [ "$_all" = "yes" ]; then
local _ac
_ac="$(docker ps -q)"
if [ "$_ac" = "" ]; then
error "No container found."
return 255
fi
_ctnrs="$_ctnrs $_ac"
fi
if [ "$_latest" = "yes" ]; then
local _lc
_lc="$(docker ps -q -l)"
if [ "$_lc" = "" ]; then
error "No container found."
return 255
fi
_ctnrs="$_ctnrs $_lc"
fi
if [ "$_ctnrs" = "" ]; then
error "No container specified."
return 255
fi
_cmd="$_cmd $_ctnrs "
(
[ "$_debug" = "yes" ] && set -x
# shellcheck disable=2086
eval $_cmd
)
}
try_attach() {
help() {
cat << ________EOF
Usage: $prg try_attach [OPTIONS] IMAGE [COMMAND] [ARG...]
Try to attach to a running container, if a name is assigned to a container in OPTIONS. If no container with this name is
found, "docker run IMAGE COMMAND ARG..." will be used to start a new process in a container. With "docker attach" the
local standard input, output, and error streams will be attached to the running container.
Accepts the same command line arguments in OPTIONS as "docker run". The following options will be handled by this
command and not passed to "docker run".
Options:
--debug Print commands issued by $prg
-h, --help Print usage
________EOF
}
local _args=""
local _debug=""
local _name=""
if [ $# -eq 0 ]; then
stderr << ________EOF
"$prg try_attach" requires at least 1 argument(s).
See '$prg try_attach --help'.
Usage: $prg try_attach [OPTIONS] IMAGE [COMMAND] [ARG...]
Try to attach to a running container, else use "docker run IMAGE COMMAND ARG..." start a new process in a container
first.
________EOF
return 255
fi
while [ -n "$1" ]; do
case "$1" in
"--debug")
_debug="yes"
;;
"--name")
if [ -z "$2" ]; then
error "flag is missing arg: $1"
return 255
fi
_name="$2"
_args="$_args '$1' '$2'"
shift
;;
"--name="*)
_name="$(echo "$1" | sed -e "s/^--name=//")"
_args="$_args '$1'"
;;
"-h"|"--help")
help
return 0
;;
*)
_args="$_args '$1'"
;;
esac
shift
done
(
[ "$_debug" = "yes" ] && set -x
if [ -z "$_name" ] || [ -z "$(docker container ls -a -q "--filter=name=^$_name\$")" ]; then
# no name given or container does not exist
eval docker run "$_args"
else
# container exists
if [ -z "$(docker container ls -a -q "--filter=name=$_name" --filter=status=running)" ]; then
# container has exited
docker start "$_name"
fi
docker attach "$_name"
fi
)
}
try_exec() {
help() {
cat << ________EOF
Usage: $prg try_exec [OPTIONS] IMAGE COMMAND [ARG...]
When a container with the name assigned in OPTIONS is found, then use "docker exec COMMAND ARG..." to execute a process
in the running container and to attach local standard input, output, and error streams to the running container. If no
container with this name can be found, then "docker run --tty --interactive --detach IMAGE /bin/sh" will be used to run
and detach from a container before running "docker exec".
Options:
--debug Print commands issued by $prg
--exec-option [OPTION...] -- Options passed to "docker exec".
Terminated with double dashes (--).
--run-option [OPTION...] -- Options passed to "docker run".
Terminated with double dashes (--).
-h, --help Print usage
________EOF
}
local _args=""
local _command=""
local _debug=""
local _exec_options=""
local _image=""
local _name=""
local _run_options=""
if [ $# -eq 0 ]; then
stderr << ________EOF
"$prg try_exec" requires at least 1 argument(s).
See '$prg try_exec --help'.
Usage: $prg try_exec [OPTIONS] IMAGE COMMAND [ARG...]
Try to use "docker exec COMMAND ARG..." to a new process in a container. When container has not been started, then run
and detach from a container first.
________EOF
return 255
fi
while [ -n "$1" ]; do
case "$1" in
"--debug")
_debug="yes"
;;
"--exec-option")
if [ -z "$2" ]; then
error "arg is missing terminator (--): $1"
return 255
fi
while [ -n "$2" ]; do
case "$2" in
--)
shift
break
;;
*)
_exec_options="$_exec_options '$2'"
;;
esac
shift
done
;;
"--run-option")
if [ -z "$2" ]; then
error "arg is missing terminator (--): $1"
return 255
fi
while [ -n "$2" ]; do
case "$2" in
"-a"|"--attach"|"--attach="*|"-d"|"--detach"|"--detach="*)
# we want to detach from "docker run"
error "unsupported arg: $1"
return 255
;;
"--name")
if [ -z "$3" ]; then
error "flag is missing arg: $2"
return 255
fi
_name="$3"
shift
;;
"--name="*)
_name="$(echo "$2" | sed -e "s/^--name=//")"
;;
--)
shift
break
;;
*)
_run_options="$_run_options '$2'"
;;
esac
shift
done
;;
"-h"|"--help")
help
return 0
;;
-*)
error "unknown flag: $1"
return 255
;;
*)
if [ -z "$2" ]; then
error "No command specified"
return 255
fi
_image="$1"
_command="$2"
shift 2
while [ -n "$1" ]; do
_args="$_args '$1'"
shift
done
set -- 'FOR_NEXT_SHIFT_ONLY'
;;
esac
shift
done
if [ -z "$_image" ]; then
error "No container image specified."
return 255
fi
# _command cannot be empty
if [ -z "$_name" ]; then
error "No name of the container specified."
return 255
fi
(
[ "$_debug" = "yes" ] && set -x
if [ -z "$(docker container ls -a -q "--filter=name=^$_name\$")" ]; then
# container does not exist
# shellcheck disable=2086
eval docker run --tty --interactive --detach $_run_options --name "$_name" "$_image" /bin/sh
fi
if [ -z "$(docker container ls -a -q "--filter=name=$_name" --filter=status=running)" ]; then
# container has exited
docker start "$_name"
fi
# shellcheck disable=2086
eval docker exec $_exec_options "$_name" "$_command" $_args
)
}
if [ $# -eq 0 ]; then
help
exit 1
fi
while [ -n "$1" ]; do
case "$1" in
"attach"|"db_add_tag"|"db_build"|"db_example"|"db_pull"|"db_push"|\
"rm"|"rmi"|"save"|"start"|"stop"|"try_attach"|"try_exec"|"help")
("$@")
exit $?
;;
"-v"|"--version")
version
exit 0
;;
"-h"|"--help")
help
exit 0
;;
-*)
error "unknown flag: $1"
exit 1
;;
*)
error "unknown command: $1"
exit 1
;;
esac
shift
done
exit $?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment