#!/bin/bash ############################################################################### # Scripts installeren. # # Geschreven door Karel Zimmer . # # Auteursrecht (c) 2016-2021 Karel Zimmer. # GNU Algemene Publieke Licentie . # # RelNum=26.05.01 # RelDat=2021-02-24 ############################################################################### ############################################################################### # Global constants ############################################################################### PROGNAME=$(basename "$0") if [[ -z $PROGNAME ]] || [[ $PROGNAME = 'bash' ]] || [[ $PROGNAME = s* ]]; then readonly PROGNAME='kzgetscripts' else readonly PROGNAME fi declare -ir SUCCESS=0 declare -ir ERROR=1 readonly CALLED=$(printf '%s' "$0 $*" | xargs --null) # Terminalattributen ('man terminfo'). Gebruik ${}. readonly BOLD=$(tput bold) readonly NORMAL=$(tput sgr0) readonly RED=${BOLD}$(tput setaf 1) readonly GREEN=${BOLD}$(tput setaf 2) readonly BLUE=${BOLD}$(tput setaf 4) ############################################################################### # Global variables ############################################################################### declare TERMINAL=false ############################################################################### # Functions ############################################################################### check_input() { local text="$PROGNAME: geen opties of argumenten opgeven Voor de nieuwste versie van $PROGNAME én het scriptspakket, gebruik de opdracht: ${BLUE}wget karelzimmer.nl/s bash s${NORMAL} of: ${BLUE}wget -O- karelzimmer.nl/s | bash${NORMAL} of: ${BLUE}curl -L karelzimmer.nl/s | bash${NORMAL} of: ${BLUE}wget karelzimmer.nl/s; bash s${NORMAL} of: ${BLUE}$PROGNAME${NORMAL}" if [[ "$*" ]]; then # Start in grafische modus; Starter: Terminal=true, CLI: optie gui. if [[ "$*" = *-g* ]]; then TERMINAL=true else printf "%s\n" \ "$text" >&2 exit $SUCCESS fi fi clear -x # Terminalemulatie wijzigen als gevolg van een bug in Whiptail's Info Box. TERM=ansi check_user check_on_ac_power } check_on_ac_power() { local -i on_battery=0 local text='' text='De computer gebruikt nu alleen de accu voor de stroomvoorziening. Het is veiliger om de computer op de lader en het stopcontact aan te sluiten.' on_ac_power >/dev/null 2>&1 || on_battery=$? if [[ on_battery -eq 1 ]]; then whiptail --backtitle "$PROGNAME" \ --title 'Waarschuwing' \ --msgbox "$text" \ 10 82 fi } check_sudo_and_dpkg() { check_sudo check_dpkg } check_sudo() { local text='' if ! sudo -n true 2> /dev/null; then while true; do text=' Authenticatie is vereist voor het installeren van pakket kzscripts Voer uw wachtwoord in:' #COMPAT # Ubuntu 12.04 LTS: sudo -S # Ubuntu 14.04 LTS: sudo --stdin # Ubuntu 16.04 LTS: sudo --stdin # Ubuntu 18.04 LTS: sudo --stdin # Ubuntu 20.04 LTS: sudo --stdin #COMPAT # Constructie '3>&1 1>&2 2>&3' om stdout en stderr te wisselen. if printf '%s\n' "$( whiptail --backtitle "$PROGNAME" \ --title 'Authenticatie nodig' \ --ok-button 'Verifiëren' \ --cancel-button 'Annuleren' \ --passwordbox "$text" \ 12 38 \ 3>&1 1>&2 2>&3 )" | sudo -S \ true \ 2> /dev/null; then break else text='Geen of verkeerd wachtwoord ingevoerd, of Annuleren gekozen.' if ! whiptail --backtitle "$PROGNAME" \ --title 'Fout' \ --yes-button 'Opnieuw' \ --no-button 'Stoppen' \ --yesno "$text" \ 10 46; then text='Programma is gestopt door de gebruiker.' whiptail --backtitle "$PROGNAME" \ --title 'Gestopt' \ --infobox "$text" \ 7 44 exit $SUCCESS fi fi done fi } check_dpkg() { local -i wait_for_aptd=10 if ls /snap/core/*/var/cache/debconf/config.dat &> /dev/null; then while sudo fuser \ /var/{lib/{dpkg,apt/lists},cache/apt/archives}/lock \ /var/cache/debconf/config.dat \ /snap/core/*/var/cache/debconf/config.dat \ &> /dev/null; do text="Wacht totdat andere softwarebeheerders klaar zijn (dit kan \ even duren)" whiptail --backtitle "$PROGNAME" \ --title 'Voortgang' \ --infobox "$text" \ 7 75 sleep $wait_for_aptd done else while sudo fuser \ /var/{lib/{dpkg,apt/lists},cache/apt/archives}/lock \ /var/cache/debconf/config.dat \ &> /dev/null; do text="Wacht totdat andere softwarebeheerders klaar zijn (dit kan \ even duren)" whiptail --backtitle "$PROGNAME" \ --title 'Voortgang' \ --infobox "$text" \ 7 75 sleep $wait_for_aptd done fi } check_user() { local text='' text="De huidge gebruiker is geen beheerder (is geen lid van groep sudo). Dit programma heeft beheerdersrechten nodig, en kan nu niet verder. Typ 'exit' om dit venster te sluiten." if ! id --name \ --groups \ "$USER" | grep --quiet \ --word-regexp \ --regexp='sudo'; then whiptail --backtitle "$PROGNAME" \ --title 'Fout' \ --infobox "$text" \ 11 72 exit $SUCCESS fi } create_development_environment() { local ftp_set='set ssl:verify-certificate no' local ftp_from=/httpdocs local ftp_to=$HOME/uploads/karelzimmer.nl/httpdocs local ftp_opts='--delete --verbose' local ftp_cmd="mirror $ftp_opts $ftp_from $ftp_to" local ftp_host=server106.hosting2go.nl local ftp_user=kzimmer local ftp_login=$HOME/.kz-$ftp_host local site_tar=https://karelzimmer.nl/apps/kzscripts/kzscripts.tar.gz local temp_tar='' local text='' local uploads=$HOME/uploads local uploads_old=$HOME/uploads.old # Pull scriptsarchief. text='Download scriptsarchief' whiptail --backtitle "$PROGNAME" \ --title 'Voortgang' \ --infobox "$text" \ 7 28 temp_tar=$(mktemp -t "$PROGNAME-XXXXXXXXXX.tar") wget --output-document="$temp_tar" \ $site_tar |& $LOGCMD text='Pak scriptsarchief uit' whiptail --backtitle "$PROGNAME" \ --title 'Voortgang' \ --infobox "$text" \ 7 27 # Verwijder eerst alle bestanden uit mappen die in het archief voorkomen. tar --list \ --file="$temp_tar" | while IFS= read -r file; do if [[ ${file: -1} = / ]]; then rm --force \ --recursive \ "${HOME:?}/$file"* fi done # Zet alles wat zonet verwijderd is weer neer uit het archief. tar --extract \ --gzip \ --directory="$HOME" \ --file="$temp_tar" |& $LOGCMD rm "$temp_tar" |& $LOGCMD # Installeer alleen voor ontwikkelaar benodigde pakketten. #COMPAT # Ubuntu 12.04 LTS: geen lftp #COMPAT if [[ $(lsb_release --release --short) = '12.04' ]]; then text="Geen deploy mogelijk op Ubuntu 12.04 LTS." whiptail --backtitle "$PROGNAME" \ --title 'Geen deploy' \ --msgbox "$text" \ 7 46 return $SUCCESS fi check_sudo_and_dpkg text='Installeer deploy pakketten (dit kan even duren)' whiptail --backtitle "$PROGNAME" \ --title 'Voortgang' \ --infobox "$text" \ 7 53 sudo apt-get \ install \ --yes \ enscript \ lftp \ shellcheck |& $LOGCMD # Pull website. if ! [[ -f $ftp_login ]]; then text='Authenticatie is vereist voor het downloaden van de website Voer het FTP-wachtwoord in:' # Constructie '3>&1 1>&2 2>&3' om stdout en stderr te wisselen. printf '%s\n' "$( whiptail --backtitle "$PROGNAME" \ --title 'Authenticatie nodig' \ --ok-button 'Verifiëren' \ --cancel-button 'Annuleren' \ --passwordbox "$text" \ 11 38 \ 3>&1 1>&2 2>&3 )" > "$ftp_login" chmod 'u=rw,g=,o=' "$ftp_login" |& $LOGCMD fi text='Download website (dit kan even duren)' whiptail --backtitle "$PROGNAME" \ --title 'Voortgang' \ --infobox "$text" \ 7 42 lftp --user "$ftp_user" \ --password "$(cat "$ftp_login")" \ -e "$ftp_set; $ftp_cmd; exit" \ "$ftp_host" |& $LOGCMD rsync --archive \ --delete \ "$uploads"/ \ "$uploads_old" |& $LOGCMD } init_script() { #COMPAT # Ubuntu 12.04 LTS: logger # Ubuntu 14.04 LTS: logger # Ubuntu 16.04 LTS: systemd-cat # Ubuntu 18.04 LTS: systemd-cat # Ubuntu 20.04 LTS: systemd-cat #COMPAT if command -v systemd &> /dev/null; then LOGCMD="systemd-cat --identifier=$PROGNAME --priority=info" LOGCMD_DEBUG="systemd-cat --identifier=$PROGNAME --priority=debug" CHKLOGCMD="journalctl --all --no-pager --identifier=$PROGNAME \ --since='$(date '+%Y-%m-%d %H:%M:%S')'" else LOGCMD="logger --tag $PROGNAME --priority info" LOGCMD_DEBUG="logger --tag $PROGNAME --priority debug" CHKLOGCMD="grep $PROGNAME /var/log/syslog" fi log "started as $CALLED (from $PWD)" # Script-hardening set -o errexit set -o errtrace set -o nounset set -o pipefail # bash 5.0: trap exit: ${FUNCNAME[0]}: ongebonden variabele # Enable code-stepping: # trap '(read -p "[$BASH_SOURCE:$LINENO] $BASH_COMMAND?")' DEBUG trap 'signal error $LINENO ${FUNCNAME:--} "$BASH_COMMAND" $?' ERR trap 'signal exit $LINENO ${FUNCNAME:--} "$BASH_COMMAND" $?' EXIT trap 'signal sighup $LINENO ${FUNCNAME:--} "$BASH_COMMAND" $?' SIGHUP # 1 trap 'signal sigint $LINENO ${FUNCNAME:--} "$BASH_COMMAND" $?' SIGINT # 2 trap 'signal sigterm $LINENO ${FUNCNAME:--} "$BASH_COMMAND" $?' SIGTERM #15 } install_scriptspackage() { local debname=kzscripts_365_all.deb local current_version='' local installed_version='' local site_deb=https://karelzimmer.nl/apps/kzscripts/$debname local temp_deb='' local text='' local -i dpkg_rc=0 # Bij Live-sessie de universe repo aanzetten. if [[ $HOSTNAME = 'ubuntu' && $USER = 'ubuntu' ]]; then check_sudo_and_dpkg text='Voeg pakketbron toe' whiptail --backtitle "$PROGNAME" \ --title 'Voortgang' \ --infobox "$text" \ 7 24 sudo add-apt-repository \ --yes \ universe |& $LOGCMD check_sudo_and_dpkg text='Ververs pakketlijst' whiptail --backtitle "$PROGNAME" \ --title 'Voortgang' \ --infobox "$text" \ 7 24 sudo apt-get \ update |& $LOGCMD fi # Verwijder het oude scriptspakket. if dpkg --status scripts &> /dev/null; then check_sudo_and_dpkg text='Verwijder scriptspakket (dit kan even duren)' whiptail --backtitle "$PROGNAME" \ --title 'Voortgang' \ --infobox "$text" \ 7 49 sudo apt-get \ remove \ --purge \ --yes \ scripts |& $LOGCMD fi # Verwijder pakket kzscripts als onjuiste versie. if dpkg --status kzscripts &> /dev/null; then installed_version=$( dpkg --list \ kzscripts | grep --word-regexp \ --regexp='kzscripts' | awk '{print $3}' ) current_version=$(echo $debname | awk -F_ '{print $2}') if ! [[ $installed_version = "$current_version" ]]; then check_sudo_and_dpkg text='Verwijder scriptspakket (dit kan even duren)' whiptail --backtitle "$PROGNAME" \ --title 'Voortgang' \ --infobox "$text" \ 7 49 sudo apt-get \ remove \ --purge \ --yes \ kzscripts |& $LOGCMD fi fi # Installeer scriptspakket. check_sudo_and_dpkg text='Download scriptspakket' whiptail --backtitle "$PROGNAME" \ --title 'Voortgang' \ --infobox "$text" \ 7 27 temp_deb=$(mktemp -t "$PROGNAME-XXXXXXXXXX.deb") wget --output-document="$temp_deb" \ $site_deb |& $LOGCMD check_sudo_and_dpkg text='Installeer scriptspakket (dit kan even duren)' whiptail --backtitle "$PROGNAME" \ --title 'Voortgang' \ --infobox "$text" \ 7 50 check_sudo_and_dpkg #COMPAT # Ubuntu 12.04 LTS: dpkg --install PAKKETBESTAND + apt-get --fix-broken # Ubuntu 14.04 LTS: dpkg --install PAKKETBESTAND + apt-get --fix-broken # Ubuntu 16.04 LTS: apt-get install PAKKETBESTAND # Ubuntu 18.04 LTS: apt-get install PAKKETBESTAND # Ubuntu 20.04 LTS: apt-get install PAKKETBESTAND #COMPAT sudo dpkg \ --install \ "$temp_deb" |& $LOGCMD || dpkg_rc=$? if [[ $dpkg_rc -ne 0 ]]; then sudo apt-get \ --fix-broken \ --yes \ install |& $LOGCMD fi rm "$temp_deb" |& $LOGCMD } log() { printf '%b' "$@" |& $LOGCMD } log_debug() { printf '%b' "$@" |& $LOGCMD_DEBUG } process_input() { local karel_full_name='' local ubuntu_full_name='' install_scriptspackage karel_full_name=$( getent passwd karel | awk -F: '{print $5}' | awk -F, '{print $1}' || true ) ubuntu_full_name=$( getent passwd ubuntu | awk -F: '{print $5}' | awk -F, '{print $1}' || true ) # Ben ik een ontwikkelaar? if [[ ($USER = karel && $karel_full_name = 'Karel Zimmer') || ($USER = ubuntu && $ubuntu_full_name = 'Live session user') ]]; then create_development_environment fi } signal() { local signal=${1:-signal?} local -i lineno=${2:-0} local function=${3:-funcname?} local command=${4:-command?} local -i rc=${5:-1} local rc_desc='' local -i rc_desc_signalno=0 local status="${RED}$ERROR/ERROR${NORMAL}" case $rc in 0) rc_desc='successful termination' status="${GREEN}$rc/SUCCESS${NORMAL}" ;; 1) rc_desc='terminated with error' ;; 6[4-9]|7[0-8]) # 64 - 78 rc_desc="open file '/usr/include/sysexits.h' and look for '$rc'" ;; 126) rc_desc='command cannot execute' ;; 127) rc_desc='command not found' ;; 128) rc_desc='invalid argument to exit' ;; 129) # sighup (128+ 1) rc_desc='hangup' ;; 130) # sigint (128+ 2) rc_desc='terminated by control-c' ;; 13[1-9]|14[0-2]) # 131 (128+3) - 142 (128+14) rc_desc_signalno=$((rc - 128)) rc_desc="typ 'trap -l' and look for '$rc_desc_signalno)'" ;; 143) # sigterm (128+15) rc_desc='termination signal' ;; 14[4-9]|1[5-8][0-9]|19[0-2]) # 144 (128+16) - 192 (128+64) rc_desc_signalno=$((rc - 128)) rc_desc="typ 'trap -l' and look for '$rc_desc_signalno)'" ;; 255) rc_desc='exit status out of range' ;; *) rc_desc='unknown error' ;; esac log_debug "signal: $signal, line: $lineno, function: $function, command: \ $command, code: $rc ($rc_desc)" case $signal in error) exit "$rc" ;; exit) signal_exit_cleanup log "ended (code=exited, status=$status)" # Een non-gui script gestart met optie gui. if $TERMINAL; then read -rp "Druk op de Enter-toets om verder te gaan [Enter]: " fi trap - ERR EXIT SIGINT SIGPIPE SIGTERM SIGHUP exit "$rc" ;; sig*) exit "$rc" ;; esac } signal_exit_cleanup() { local error_msg="${RED}Programma $PROGNAME is afgebroken. Om de log te controleren, start een Terminalvenster, en voer uit:${BLUE} $CHKLOGCMD${NORMAL} Als de pakketbeheerder 'apt' foutmeldingen geeft, start dan een nieuw Terminalvenster, en voer uit:${BLUE} sudo apt-get update --fix-missing sudo dpkg --configure --pending sudo apt-get install --fix-broken sudo update-initramfs -u${NORMAL}" if [[ $rc -ne 0 ]]; then printf '%b\n' "$error_msg" fi rm --force s s.{1..99} } term_script() { local text='' text="Volg nu de stappen zoals beschreven in Checklist installatie. Deze Checklist is te vinden op de site https://karelzimmer.nl onder Linux. Typ 'exit' om dit venster te sluiten." whiptail --backtitle "$PROGNAME" \ --title 'Gereed' \ --infobox "$text" \ 12 66 exit $SUCCESS } ############################################################################### # Main line ############################################################################### main() { init_script check_input "$@" process_input term_script } main "$@" # EOF