parent
507783123f
commit
6486d66a9d
1 changed files with 189 additions and 0 deletions
@ -0,0 +1,189 @@ |
||||
#!/bin/bash -e |
||||
|
||||
############################################################################ begin logging |
||||
# check if stdout is a terminal... |
||||
if test -t 1; then |
||||
|
||||
# see if it supports colors... |
||||
ncolors=$(tput colors) |
||||
|
||||
if test -n "$ncolors" && test $ncolors -ge 8; then |
||||
bold="$(tput bold)" |
||||
underline="$(tput smul)" |
||||
standout="$(tput smso)" |
||||
normal="$(tput sgr0)" |
||||
black="$(tput setaf 0)" |
||||
red="$(tput setaf 1)" |
||||
green="$(tput setaf 2)" |
||||
yellow="$(tput setaf 3)" |
||||
blue="$(tput setaf 4)" |
||||
magenta="$(tput setaf 5)" |
||||
cyan="$(tput setaf 6)" |
||||
white="$(tput setaf 7)" |
||||
fi |
||||
fi |
||||
|
||||
append_msg() { |
||||
if test $# -ne 0; then |
||||
echo -n ": ${bold}$*" |
||||
fi |
||||
echo "${normal}" |
||||
} |
||||
|
||||
# write a message |
||||
message() { |
||||
if test $# -eq 0; then |
||||
return |
||||
fi |
||||
echo "${bold}${while}$*${normal}" 1>&2 |
||||
} |
||||
|
||||
# write a success message |
||||
success() { |
||||
echo -n "${bold}${green}success" 1>&2 |
||||
append_msg $* 1>&2 |
||||
} |
||||
|
||||
# write a notice |
||||
notice() { |
||||
echo -n "${bold}${yellow}notice" 1>&2 |
||||
append_msg $* 1>&2 |
||||
} |
||||
|
||||
# write a warning message |
||||
warning() { |
||||
echo -en "${bold}${red}warning" 1>&2 |
||||
append_msg $* 1>&2 |
||||
} |
||||
|
||||
# write error message |
||||
error() { |
||||
echo -en "${bold}${red}error" 1>&2 |
||||
append_msg $* 1>&2 |
||||
} |
||||
|
||||
# run a command, print the result and abort in case of error |
||||
# option: --ignore: ignore the result, continue in case of error |
||||
run() { |
||||
ignore=1 |
||||
while test $# -gt 0; do |
||||
case "$1" in |
||||
(--ignore) ignore=0;; |
||||
(*) break;; |
||||
esac |
||||
shift; |
||||
done |
||||
echo -n "${bold}${yellow}running:${white} $*${normal} … " |
||||
set +e |
||||
result=$($* 2>&1) |
||||
res=$? |
||||
set -e |
||||
if test $res -ne 0; then |
||||
if test $ignore -eq 1; then |
||||
error "failed with return code: $res" |
||||
if test -n "$result"; then |
||||
echo "$result" |
||||
fi |
||||
exit 1 |
||||
else |
||||
warning "ignored return code: $res" |
||||
fi |
||||
else |
||||
success |
||||
fi |
||||
} |
||||
|
||||
############################################################################ error handler |
||||
function traperror() { |
||||
set +x |
||||
local err=($1) # error status |
||||
local line="$2" # LINENO |
||||
local linecallfunc="$3" |
||||
local command="$4" |
||||
local funcstack="$5" |
||||
IFS=" " |
||||
for e in ${err[@]}; do |
||||
if test -n "$e" -a "$e" != "0"; then |
||||
error "line $line - command '$command' exited with status: $e (${err[@]})" |
||||
if [ "${funcstack}" != "main" -o "$linecallfunc" != "0" ]; then |
||||
echo -n " ... error at ${funcstack} " 1>&2 |
||||
if [ "$linecallfunc" != "" ]; then |
||||
echo -n "called at line $linecallfunc" 1>&2 |
||||
fi |
||||
echo |
||||
fi |
||||
exit $e |
||||
fi |
||||
done |
||||
exit 0 |
||||
} |
||||
|
||||
# catch errors |
||||
trap 'traperror "$? ${PIPESTATUS[@]}" $LINENO $BASH_LINENO "$BASH_COMMAND" "${FUNCNAME[@]}" "${FUNCTION}"' ERR SIGINT INT TERM EXIT |
||||
|
||||
|
||||
|
||||
######################################################### commandline parameter evaluation |
||||
exec=0 |
||||
log=0 |
||||
stacks= |
||||
short=0 |
||||
while test $# -gt 0; do |
||||
case "$1" in |
||||
(--help|-h) less <<EOF |
||||
SYNOPSIS |
||||
|
||||
$0 [OPTIONS] [stacks] |
||||
|
||||
OPTIONS |
||||
|
||||
--help, -h show this help |
||||
--log, -l show log command |
||||
--exec, -e show exec command |
||||
--short, -s only show errors |
||||
|
||||
stacks optional space separated list of stacks |
||||
|
||||
DESCRIPTION |
||||
|
||||
Show status of all docker swarm stacks. The problems of docker swarm ps are, that you can only specify one stack to analyze, and then you get too much output. So this command lists all stacks and clearly shows which stacks are running and which stacks have a problem. |
||||
|
||||
EOF |
||||
exit;; |
||||
(--log|-l) log=1;; |
||||
(--exec|-e) exec=1;; |
||||
(--short|-s) short=1;; |
||||
(*) stacks="$*"; break;; |
||||
esac |
||||
if test $# -eq 0; then |
||||
error "missing parameter, try $0 --help"; exit 1 |
||||
fi |
||||
shift; |
||||
done |
||||
|
||||
##################################################################################### Main |
||||
|
||||
stacks=${stacks:-$(docker stack ls --format='{{.Name}}')} |
||||
|
||||
services=$(for stack in ${stacks}; do |
||||
status=$(docker stack ps --no-trunc --filter="desired-state=running" --format="{{.CurrentState}};{{.Name}};{{.Node}};{{.DesiredState}};{{.CurrentState}};{{.ID}};{{.Error}}" ${stack} | sed 's,^[^ ]* ,,') |
||||
IFS=" |
||||
" |
||||
for service in ${status}; do |
||||
time=${service%%;*} |
||||
echo "$(date -d "$(sed 's,about an* ,1 ,' <<<${time})");${service#*;}" |
||||
done |
||||
done | sort -hr) |
||||
|
||||
IFS=" |
||||
" |
||||
for service in ${services}; do |
||||
awk -F';' -v dolog=$log -v doexec=$exec -v doshort=$short ' |
||||
{color="'"${green}"'"} |
||||
$5 ~ /second|minute/ {color="'"${yellow}"'"} |
||||
$5 !~ /^Running/ {printf "'"${red}"'%-15s%-40s%s %s%s\n", $3, $2, $5, $7, "'"${normal}"'"} |
||||
$5 ~ /^Running/ && doshort==0 {printf "%s%-15s%-40s%s%s\n", color, $3, $2, $5, "'"${normal}"'"} |
||||
dolog==1 && (doshort==0 || $5 !~ /^Running/) {printf "ssh %s docker logs -f %s.%s\n", $3, $2, $6} |
||||
doexec==1 && (dohort==0 || $5 !~ /^Running/) {printf "ssh %s docker exec -it %s.%s bash\n", $3, $2, $6} |
||||
' <<<${service} |
||||
done |
Loading…
Reference in new issue