#!/usr/bin/env bash # Copyright 2010-2012 Thomas Schoebel-Theuer / 1&1 Internet AG # # Email: tst@1und1.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 2 # 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, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. if (( !noecho )); then echo "Sourcing lib.sh" fi # this may be later overridden by distros / install scripts / etc # $sript_dir is assumed to be already set by the caller base_dir="$(cd "$script_dir/.."; pwd)" bin_dir="$base_dir/src" module_dir="$script_dir/modules" download_dir="$base_dir/downloads" mkdir -p "$download_dir" || exit -1 [ -x $bin_dir/bins.exe ] || \ (cd $base_dir && ./configure && make) ||\ { echo "Could not make binaries. Sorry." ; exit -1; } ##################################################################### # general error exit function function lib_callstack { local argv_index=0 i for i in ${!FUNCNAME[*]}; do local j args= argc=${BASH_ARGC[$i]} if [ ${argc:-0} -gt 0 ]; then local args for j in $(seq 1 1 $argc); do args='"'"${BASH_ARGV[$argv_index]}"'" '"$args" let argv_index+=1 done fi echo ${BASH_SOURCE[(($i + 1))]:-"stdin"}:${BASH_LINENO[$i]} ${FUNCNAME[$i]} $args done } function lib_exit { local rc=$1 msg="$2" # to avoid recursion if [ -n "$lib_exit_recursion" ];then echo "recursion!!!" >&2 printf "\nstack:\n" >&2 lib_callstack >&2 exit $rc fi if [ -n "$msg" ];then echo " $msg" >&2 fi export lib_exit_recursion=1 if [ ${#main_error_recovery_functions[*]} -ge 0 ]; then local func args for func in "${!main_error_recovery_functions[@]}"; do args="${main_error_recovery_functions[$func]}" if [ -n "$args" ];then echo " calling error recovery $func" >&2 $func $args || exit 1 fi done fi printf "\nstack:\n" >&2 lib_callstack >&2 exit $rc } ##################################################################### # helper to generate verbose messages function lib_vmsg { if (( verbose_script )); then echo "$*" fi } ##################################################################### # helper for prevention of script failures due to missing tools function check_installed { local check_list="$1" i for i in $check_list; do if ! which $i >/dev/null 2>&1; then echo "Sorry, program '$i' is not installed." exit -1 fi done } check_always_list="basename dirname which pwd mkdir rmdir rm cat ls sort ssh scp nice sed awk" check_installed "$check_always_list" ##################################################################### # helper for sourcing other config files (may reside in parents of cwd) function source_config { local name="$1" local setup_dir=$(pwd) local limit=0 until [ -r $setup_dir/$name.conf ]; do setup_dir="$(cd $setup_dir/..; pwd)" (( limit++ > 20 )) && { echo "No parent dir found for (potential) config file $name.conf."; return 1; } done local setup=$setup_dir/$name.conf echo "Sourcing config file $setup" shopt -u nullglob source $setup || exit $? return 0 } ##################################################################### # abstracting access to remote hosts function lib_remote_opt { local ssh_opt="$1" shift local host="$1" shift ssh $ssh_opt -n root@"$host" "$@" } function remote { lib_remote_opt "" "$@" } function lib_remote_all_idfile { lib_remote_all_opt "$main_ssh_idfile_opt" "$@" } function lib_remote_all_opt { local ssh_opt="$1" shift local host_all="$1" host shift local cmd="$@" for host in $host_all; do lib_remote_opt "$ssh_opt" "$host" "$cmd" \ || { rc=$?; echo " $cmd cmd failed on host $host" >&2; return $rc; } done } function remote_all { lib_remote_all_opt "" "$@" } function lib_remote_idfile { lib_remote_opt "$main_ssh_idfile_opt" "$@" } function remote_all_noreturn { local host_all="$1" host shift for host in $host_all; do remote "$host" "$@" done } function lib_check_access_to_remote_hosts { local ssh_opt="$1" shift local hostlist="$@" if (( verbose_script )); then echo " testing access as root to hosts $hostlist" fi lib_remote_all_opt "$ssh_opt" "$hostlist" hostname || lib_exit 1 } # The pid of the started program will be returned in the variable named by # $3. # The names of the script which is executed on the remote host will be returned # in the variable namend by $4 # The name of the (remote) outputfile of the script is the script name # extended with .out # stdout resp. stderr are kept in files named