123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241 |
- #!/bin/bash
-
- ffoo import misc
- ffoo import pretty
-
-
- age_of_leaf() {
- #
- # Print age of each filename on STDIN
- #
- local now=$1
- local ctime
- sed 's/.*/"&"/' \
- | xargs stat -c %Z \
- | while read ctime;
- do echo $(($now - $ctime));
- done
- }
-
-
- age_of_tree() {
- #
- # Age of the youngest leaf in the tree
- #
- local now=$(date +%s)
- find -L "$1" \
- | age_of_leaf $now \
- | sort -n \
- | head -1
- }
-
-
- cat_uri() {
- #
- # Cat for URIs
- #
- wget -q $1 -O - || echo "ERROR: $?" >&2
- }
-
-
- has_files() {
- #
- # Directory exists and has at least one file
- #
- test -d "$1" || return 1
- test -e "$1"/* &>/dev/null
- case $? in
- 0) return 0 ;;
- 1) return 1 ;;
- *) return 0 ;;
- esac
- }
-
-
- pids_matching() {
- #
- # Print list of PIDs where command matches regex(es)
- #
- # Note that *comm* field of *ps* is used, which may be
- # truncated, so don't rely on name ending
- #
- local all_pids=""
- local pids=""
- local pfx=""
- local pattern
- for pattern in "$@";
- do
- local pids=$(
- ps -e -o pid= -o comm= \
- | perl -ne "
- chomp;
- s/^ +//;
- my (\$pid, \$comm) = split m/ +/;
- next unless \$comm =~ m/$pattern/;
- print qq/\$pid /;
- "
- )
- debug -v pattern pids
- all_pids="$all_pids$pfx$pids"
- pfx=" "
- done
- debug -v all_pids
- test -n "$all_pids" && echo $all_pids
- }
-
-
- listening_on() {
- #
- # Check if something is listening on local TCP port $1
- #
- local host="localhost"
- local port="$1"
- debug -v host port
- test -n "$port" || usage_is "PORT"
- netstat -ntlp \
- | sed -e 's/ */ /g' \
- | cut -d\ -f 4 \
- | grep -qs :$port\$
- }
-
-
- reachable_by_ping() {
- #
- # Check if host $1 is reachable by ICMP ping
- #
- local host=$1
- debug -v host
- test -n "$host" || usage_is "HOST"
- ping -w 1 $host >& /dev/null
- }
-
-
- reachable_by_ssh() {
- #
- # Check if host $1 is reachable by SSH
- #
- local host=$1
- debug -v host
- test -n "$host" || usage_is "HOST"
- ssh -n -o ConnectTimeout=3 $host -- true >/dev/null 2>&1;
- }
-
-
- reachable_by_tcp() {
- #
- # Check if TCP port $1 on host $2 is reachable (open)
- #
- local port=$1
- local host=$2
- debug -v port host
- test -n "$host" -a -n "$port" || usage_is "PORT HOST"
- nc -w 1 $host $port >/dev/null 2>&1;
- }
-
-
- filter_hosts() {
- #
- # Filter hosts on STDIN, leaving those reachable
- #
- # Default check is by ICMP only, but you can use arguments
- # to enable/disable checks:
- #
- # -t|--tcp PORT enable TCP check on PORT
- # -p|--ping enable ICMP ping (default)
- # -P|--no-ping disable ICMP ping
- # -s|--ssh enable SSH (check by calling `true`)
- # -S|--no-ssh disable SSH
- #
- local ping_fun="reachable_by_ping"
- local ssh_fun=true
- local tcp_fun=true
- # note: here the ^ true builtin acts as placeholder (i.e. no check)
- local tcp_port=0
- while true; do case $1 in
- -t|--tcp) tcp_fun="reachable_by_tcp $2"; shift 2 ;;
- -p|--ping) ping_fun="reachable_by_ping"; shift ;;
- -P|--no-ping) ping_fun=true; shift ;;
- -s|--ssh) ssh_fun="reachable_by_ssh"; shift ;;
- -S|--no-ssh) ssh_fun=true; shift ;;
- "") break ;;
- *) usage_is "[-p|P] [-s|-S] [-t port]"; return 2 ;;
- esac done
- filter $ping_fun | filter $tcp_fun | filter $ssh_fun
- }
-
-
- sort_paths_by_age() {
- #
- # Read paths on STDIN and sort them by age of youngest leaf
- #
- while read path;
- do echo "$(age_of_tree $path) $path"
- done \
- | sort -n \
- | cut -d\ -f 2-
- }
-
-
- wait_until() {
- #
- # Wait until command succeeds (or fails)
- #
- # Repeat calling a command until it succeeds or exits with
- # acceptable status. For example:
- #
- # wait_until -t 90 my_command
- # wait_until -t 90 -d 30 my_expensive_command
- # wait_until -x 7 command_that_should_exit_with_7
- # wait_until -X "-lt 7" command_that_should_exit_with_less_than_7
- # wait_until -e some_bash_builtin
- #
- # Note that polling happens synchronously so if your
- # command blocks for more than specified delay, freequency
- # and timeout cannot be guaranteed. If you need to assure
- # more predictable behavior, limit your command with
- # timeout(1)
- #
- local timeout=10
- local delay=1
- local use_eval=false
- local es_test="-eq 0"
- while true; do case "$1" in
- -x) es_test="-eq $2"; shift; ;;
- -X) es_test="$2"; shift; ;;
- -e) use_eval=true; shift; break ;;
- -d) delay="$2"; shift 2; ;;
- -t) timeout="$2"; shift 2; ;;
- --) shift 1; break; ;;
- *) break; ;;
- esac done
- think "waiting for: $@"
- local elapsed=0
- local start=$(date +%s)
- while true;
- do
- sleep $delay
- local now=$(date +%s)
- local elapsed=$(($now - $start))
- local es=0
- debug "\$@='$@'"
- if $use_eval;
- then
- eval $@;
- es=$?
- else
- $@;
- es=$?
- fi
- debug -v es
- if [ $es $es_test ];
- then
- return 0;
- fi
- if test $elapsed -gt $timeout;
- then
- warn "timeout reached ($elapsed>$timeout) when waiting for ($es $es_test): $@"
- return 1
- fi
- think "waiting for another $delay s"
- done
- }
|