190 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			190 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| 
								 | 
							
								#!/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
							 |