commit 1a40e98b5f5a44829d824139ad1c936ead61ba55 Author: Aaron Johnon Date: Tue Aug 10 20:45:24 2021 -0500 Added pre-existing scripts diff --git a/example_configs/httpcheck_telegram b/example_configs/httpcheck_telegram new file mode 100644 index 0000000..6f9154b --- /dev/null +++ b/example_configs/httpcheck_telegram @@ -0,0 +1,7 @@ +HEADER="HTTP/S Checker" #Header for the start of outgoing messages from the bot +CHATID="5555555" #Chat ID for the Telegram room/conversation with bot +KEY="THISISAUNIQUEANDPRIVATEKEY" #Your bot's API key +CHKLIST="${HOME}/.site_check" #A file containing a list of sites/URLs to check +DB="/tmp/.httpcheck.sqlite" #Location of SQLite3 database +MAX_COUNT=10 #Max number of 'count' before alert becomes true + diff --git a/http_check_telegram b/http_check_telegram new file mode 100755 index 0000000..6c1ffd3 --- /dev/null +++ b/http_check_telegram @@ -0,0 +1,183 @@ +#!/bin/sh + +PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin +CONFIG=$1 + +#Alias DB command for easy future adjustments +SQL='sqlite3' +alias sql="$SQL" + +# Check for dependencies +if ! which $SQL >/dev/null 2>&1; then + printf '%s\n' "ERROR 12: Missing dependency -- '$SQL' command not found." >&2 + exit 12 +fi +if ! which curl >/dev/null 2>&1; then + printf '%s\n' "ERROR 12: Missing dependency -- 'curl' command not found." >&2 + exit 12 +fi + +# BEGIN CONFIG CHECK +### Provides KEY, CHATID, CHKLIST +if [ -n "$CONFIG" ]; then + if [ -f "$CONFIG" ]; then + . $CONFIG #Source config file + else + printf '%s\n' "$CONFIG: File does not exist." >&2 + exit 10 + fi +else + if [ -f ".httpcheck_telegram" ]; then + . .httpcheck_telegram #Source config file + else + printf '%s\n' "No configuration file found." >&2 + exit 10 + fi +fi +# Check if config was loaded by examining all configuration variables, exit if not +if [ -z "$KEY" ]; then + printf '%s\n' "Configuration not set correctly: KEY not set" >&2 + ERROR11=true +fi +if [ -z "$CHATID" ]; then + printf '%s\n' "Configuration not set correctly: CHATID not set" >&2 + ERROR11=true +fi +if [ -z "$CHKLIST" ]; then + printf '%s\n' "Configuration not set correctly: CHKLIST not set" >&2 + ERROR11=true +fi +if [ -z "$DB" ]; then + printf '%s\n' "Configuration not set correctly: DB not set" >&2 + ERROR11=true +fi +if [ -z "$MAX_COUNT" ]; then + printf '%s\n' "Configuration not set correctly: MAX_COUNT not set" >&2 + ERROR11=true +fi +[ "$ERROR11" = "true" ] && exit 11 +# END CONFIG CHECK + +#DB functions +db_create() { + sql $DB "CREATE TABLE problem ( + site TEXT UNIQUE NOT NULL, + count INT NOT NULL DEFAULT 0, + alert INT NOT NULL DEFAULT 0, + sent INT NOT NULL DEFAULT 0 + );" +} +db_addsite() { + sql $DB "INSERT OR IGNORE INTO problem (site) VALUES('$1');" +} +db_inc() { + sql $DB "UPDATE problem SET count = count + 1 WHERE site = '$1' AND count < $MAX_COUNT;" + if [ $(sql $DB "SELECT count FROM problem WHERE site = '$1';") -ge $MAX_COUNT ]; then + sql $DB "UPDATE problem SET alert = 1 WHERE site = '$1';" + fi +} +db_dec() { + sql $DB "UPDATE problem SET count = count - 1 WHERE site = '$1' AND count > 0;" + if [ $(sql $DB "SELECT count FROM problem WHERE site = '$1';") -le 0 ]; then + sql $DB "UPDATE problem SET alert = 0 WHERE site = '$1';" + fi +} + + +TIME="10" +URL="https://api.telegram.org/bot$KEY/sendMessage" + +#Telegram message function +send_message() { + curl -s --max-time $TIME -d "chat_id=${CHATID}&disable_web_page_preview=1&text=$1" $URL >/dev/null +} + +get_http_code() { + if host $(printf '%s\n' $1 | awk '{gsub("https?://|/.*","")}1') 2>&1 >/dev/null; then + curl -sILk --max-time $TIME $1 | grep HTTP | tail -n 1 | grep -Eo '[0-9]{3}' || printf '%s\n' 999 + else + printf '%s\n' 000 + fi +} + +print_time() { + date '+%Y-%m-%d %H:%M:%S' +} + +# Prepare message header +#MSG="${HEADER}%0AProblems Found:" +FAILURE=false + +# Create database if it doesn't exist +if [ -f $DB ]; then + printf '%s\n' "Database found: $DB" +else + printf '%s' "Database not found at '$DB'\nCreating DB ... " + if db_create; then + printf '%s\n' "DONE" + else + printf '%s\n' "FAILED" + printf '%s\n' "Database creation failed!" >&2 + exit 13 + fi +fi + +# Check HTTP codes +for site in $(grep -v "^#\|^$" $CHKLIST | sort | uniq); do + db_addsite $site + respcode=$(get_http_code $site) + case $respcode in + 000) + printf '%s\n' "[$(print_time)]: PROBLEM -- $site: DNS record not found" >&2 + db_inc $site + #MSG="${MSG}%0A%0A %2B ${site}%0A DNS record not found" + #FAILURE=true + ;; + 200) + printf '%s\n' "[$(print_time)]: OK -- $site returns $respcode" + db_dec $site + ;; + 999) + printf '%s\n' "[$(print_time)]: PROBLEM -- $site caused general cURL failure" >&2 + db_inc $site + ;; + *) + printf '%s\n' "[$(print_time)]: PROBLEM -- $site returns $respcode" >&2 + db_inc $site + #MSG="${MSG}%0A%0A %2B ${site}%0A Responding ${respcode}" + #FAILURE=true + ;; + esac +done || exit 2 + +### # Send compiled message if any problems were found +### if [ "$FAILURE" = "true" ]; then +### send_message "$MSG" && printf '%s\n' "Problems found. Message sent via Telegram bot" >&2 || printf '%s\n' "Problems found. Message sending has failed" +### fi + +# Find down sites without sent alerts +unsent=$(sql $DB "SELECT count(*) FROM problem WHERE alert = 1 AND sent = 0;") +cleared=$(sql $DB "SELECT count(*) FROM problem WHERE alert = 0 AND sent = 1;") +down=$(sql $DB "SELECT count(*) FROM problem WHERE alert = 1;") +downlist=$(sql $DB "SELECT site FROM problem WHERE alert = 1;" | perl -p -e 's/\n/%0A/g') + +# If ANY sites have unsent alerts, send a list of ALL sites in 'alert' state +if [ $unsent -gt 0 ]; then + ALERT="${HEADER}%0ASites Down:%0A${downlist}" + send_message "$ALERT" && printf '%s\n' "Problems found. Message sent via Telegram bot" >&2 || printf '%s\n' "Problems found. Message sending has failed" + sql $DB "UPDATE problem SET sent = 1 WHERE sent = 0 AND alert = 1;" #Prevents resending messages +fi + +# If ALL sites have cleared alerts, send an all-clear +if [ $cleared -gt 0 ]; then + clearlist=$(sql $DB "SELECT site FROM problem WHERE alert = 0 AND sent = 1;" | perl -p -e 's/\n/%0A/g') + CLEARED="${HEADER}%0AThese HTTP alerts have cleared:%0A${clearlist}" + if [ $down -gt 0 ]; then + CLEARED="${CLEARED}%0ASites still down:%0A${downlist}" + fi + send_message "$CLEARED" && printf '%s\n' "A site's alert status has cleared. Message sent via Telegram bot" >&2 || printf '%s\n' "A site's alert status has cleared. Message sending has failed" + sql $DB "UPDATE problem SET sent = 0 WHERE sent = 1 AND alert = 0;" #Prevents resending messages +fi + +exit 0 + diff --git a/postgres_backup.sh b/postgres_backup.sh new file mode 100755 index 0000000..eb4f642 --- /dev/null +++ b/postgres_backup.sh @@ -0,0 +1,149 @@ +#!/usr/bin/env sh + +# Usage: +# postgres_backup.sh [man] //Manual backup, full output +# postgres_backup.sh auto //Auto backup (separate backup location, only outputs STDERR messages) + +# CONFIG +### Example Config File ############ +### +### PORT=5432 +### DIR=/var/lib/pgsql/backup +### COMPRESSION=zstd +### COMP_LEVEL=14 +### THREADS=2 +### +#################################### +# +# Load config file: +if [ ! -f ${HOME}/.postgres_backup.conf ]; then + echo "ERROR 10: Configuration file not found" + exit 10 +fi +source ${HOME}/.postgres_backup.conf + + +## Check if automated, set appropriate directory +if [ "$1" = "auto" ]; then + AUTO="true" + DIR=${DIR}/auto +else + AUTO="false" + DIR=${DIR}/manual +fi + +## Define message commands +msg_show() { + [ "$AUTO" = "false" ] && printf "$1" +} +msg_check() { + [ "$AUTO" = "false" ] && printf '%-70s %s' "$1" # | sed s/\ \ /../g +} +get_size() { + tsize=$(find $1 -prune -printf '%s\n') + [ $tsize -lt 1024 ] && tsize="$tsize B" || tsize=$(numfmt --to=iec-i --suffix=B --format='%.3f' <<<$tsize | sed -r 's/([A-Z])/ \1/') + printf "$tsize" +} + +## Sanity check +pass="$(tput bold)$(tput setaf 2)OK$(tput sgr0)\n" +fail="$(tput bold)$(tput setaf 1)FAIL$(tput sgr0)\n" + +msg_show "=== $(tput bold)Config Sanity Check$(tput sgr0)\n" + +msg_check "PostgreSQL server port: $(tput bold)${PORT}$(tput sgr0)" +if [ $PORT -lt 65536 -a $PORT -gt 0 ] 2>/dev/null; then + msg_show "$pass" +else + msg_show "$fail" + echo "ERROR 11: PORT configuration not a valid port number" >&2 + exit 11 +fi +msg_check "Backup directory: $(tput bold)${DIR}$(tput sgr0)" +if [ -d "$DIR" ]; then + msg_show "$pass" +else + msg_show "$fail" + echo "ERROR 12: Backup directory does not exist" >&2 + exit 12 +fi +msg_check "Compression type: $(tput bold)${COMPRESSION}$(tput sgr0)" +case $COMPRESSION in + xz) + msg_show "$pass" + msg_check "Compression level: $(tput bold)${COMP_LEVEL}$(tput sgr0)" + if [ $(sed s/e// <<< $COMP_LEVEL) -lt 10 -a $(sed s/e// <<< $COMP_LEVEL) -gt 0 ] 2>/dev/null; then + msg_show "$pass" + else + msg_show "$fail" + echo "ERROR 14: Compression level not valid" >&2 + exit 14 + fi + ;; + zstd) + msg_show "$pass" + msg_check "Compression level: $(tput bold)${COMP_LEVEL}$(tput sgr0)" + if [ $COMP_LEVEL -lt 20 -a $COMP_LEVEL -gt 0 ] 2>/dev/null; then + msg_show "$pass" + else + msg_show "$fail" + echo "ERROR 14: Compression level not valid" >&2 + exit 14 + fi + ;; + *) + msg_show "$fail" + echo "ERROR 13: Compression not configured correctly" >&2 + exit 13 + ;; +esac +msg_check "Thread count: $(tput bold)${THREADS}$(tput sgr0)" +if [ $THREADS -eq $THREADS -a $THREADS -gt -1 ] 2>/dev/null; then + msg_show "$pass" + [ $THREADS -gt $(nproc) ] 2>/dev/null && msg_show "$(tput setaf 3)$(tput bold)WARN:$(tput sgr0) THREADS is set higher than CPU count!\n" +else + msg_show "$fail" + echo "ERROR 15: Thread count is not a valid positive integer" >&2 + exit 15 +fi +## End sanity check + + +## Set date for timestamp +DATE=$(date +%Y%m%d-%H%M) +msg_show "Timestamp set to $(tput bold)${DATE}$(tput sgr0)\n" + +## Get list of DBs +list_db=$(psql -p${PORT} -U postgres -t -c 'select datname from pg_database;' | grep -v 'template0\|template1\|postgres' | sed '/^$/d') + +## Set compression parameters +case $COMPRESSION in + xz) + compress="xz -T${THREADS} -${COMP_LEVEL} -" + comp_ext="xz" + ;; + zstd) + compress="zstd -T${THREADS} -${COMP_LEVEL} -z -" + comp_ext="zst" + ;; + *) + echo "ERROR 13: Compression not configured correctly!" >&2 + exit 13 + ;; +esac + +msg_show "\nStarting backup procedures...\n\n" + +## Backup globals +target="${DIR}/globals_${DATE}.dmp.${comp_ext}" +pg_dumpall -p${PORT} -g | eval $compress > ${DIR}/globals_${DATE}.dmp.${comp_ext} +msg_show "Backed up $(tput setaf 2)$(tput bold)globals$(tput sgr0) as $(tput setaf 3)${target}$(tput sgr0) [$(tput setaf 2)$(get_size $target)$(tput sgr0)] using $(tput bold)${compress}$(tput sgr0)\n" + +for db in $list_db; do + target="${DIR}/${db}_${DATE}.dmp.${comp_ext}" + pg_dump -O $db | eval $compress > $target + msg_show "Backed up $(tput setaf 2)$(tput bold)${db}$(tput sgr0) as $(tput setaf 3)${target}$(tput sgr0) [$(tput setaf 2)$(get_size $target)$(tput sgr0)] using $(tput bold)${compress}$(tput sgr0)\n" +done + +exit 0 + diff --git a/provision_new_server.sh b/provision_new_server.sh new file mode 100755 index 0000000..c370665 --- /dev/null +++ b/provision_new_server.sh @@ -0,0 +1,107 @@ +#!/usr/bin/env sh +#Author: Aaron Johnson +#Comment: This script is not intended to be portable or fail-safe, and is used in my personal provisioning process. + +name_old=$(cat /etc/hostname) +#Below command preserved in case it is needed to add older OS support +#ipadd_old=$(ifconfig | awk '/inet6/{next;} /127.0.0.1/{next;} /inet/{print $2;}' | grep 172.23) +cidr_old=$(ip a | awk '/inet6/{next;} /127.0.0.1/{next;} /inet/{print $2;}' | grep 172.23) +ipadd_old=$(echo $cidr_old | awk -F '/' '{print $1}') +ipc_present=false + +# Get user input +echo "Enter new host information." +read -p "Hostname [$name_old]: " name +read -p "IP address (CIDR format) [$cidr_old]: " cidr +# Input sanity check +if [ -z "$name" ]; then + name=$name_old +fi +if [ -z "$cidr" ]; then + cidr=$cidr_old +fi +## Validate CIDR +n='([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])' +m='([0-9]|[12][0-9]|3[012])' +if ! echo $cidr | grep -E "^$n(\.$n){3}/$m$" &>/dev/null; then + printf "\nCIDR input is not valid!\n" + exit 12 +fi +# End input sanity check + +# Test if 'ipcalc' utility is available +which ipcalc &>/dev/null && ipc_present=true + +ipadd=$(echo $cidr | awk -F '/' '{print $1}') +echo +printf "Review these changes carefully!\n\n" +if [ "$ipc_present" = true ]; then + snm=$(ipcalc $cidr | grep Netmask | grep -Eo "($n.){3}$n") + snm_old=$(ipcalc $cidr_old | grep Netmask | grep -Eo "($n.){3}$n") + printf "+,CURRENT,PENDING\nHostname:,$name_old,$name\nAddress:,$ipadd_old,$ipadd\nCIDR:,$cidr_old,$cidr\nNetmask:,$snm_old,$snm" | column -s, -t +else + printf "+,CURRENT,PENDING\nHostname:,$name_old,$name\nAddress:,$ipadd_old,$ipadd\nCIDR:,$cidr_old,$cidr" | column -s, -t +fi +echo +read -p "Are you sure you want to apply the changes above? (y/N)" -n 1 -r +if echo $REPLY | grep -Eq '^[Yy]$'; then + printf "\n Continuing...\n\n" +else + printf "\n ABORT\n" + exit 13 +fi + +# Update /etc/hostname +printf "Update hostname... " +echo $name > /etc/hostname && printf "DONE\n" || exit 1 + +# Update /etc/hosts +printf "Update /etc/hosts... " +sed -i "/^127.0.0.1/s/.*/127.0.0.1\tlocalhost localhost.localdomain/" /etc/hosts && \ +sed -i "/^127.0.1.1/s/.*/127.0.1.1\t$(echo $name | awk -F . '{print $1}') $name/" /etc/hosts &&\ +printf "DONE\n" || exit 1 + +# Update Zabbix Agent +printf "Update Zabbix Agent... " +sed -i "s/${name_old}/${name}/g" /etc/zabbix/zabbix_agentd.conf && printf "DONE\n" || exit 1 + +# Update IP address +printf "Update IP address... " +if $(uname -r | grep -E 'el8' &>/dev/null); then + printf "CentOS 8... " + nmcli con mod ens18 ipv4.addresses $cidr && printf "DONE\n" || exit 1 +elif $(uname -r | grep 'arch' &>/dev/null); then + printf "Arch Linux... " + sed -i "s_${cidr_old}_${cidr}_g" /etc/netctl/ens18 && printf "DONE\n" || exit 1 +else + printf "FAIL\n\nOS distribution not supported! Update IP address manually before rebooting!\n\n" +fi + +# Update SSH host keys +if [ -f /etc/ssh/ssh_host_rsa_key ]; then + printf "Found old keys. Removing... " + rm /etc/ssh/ssh*key* && printf "DONE\n" || exit 1 +fi +printf "Regenerating host keys... " +ssh-keygen -A >/dev/null && printf "DONE\n" || exit 1 + +# Remove script after success +if [ -f /root/provision_new_server.sh ]; then + printf "Removing this script from /root... " + unlink /root/provision_new_server.sh || exit 1 + printf "DONE\n" + printf " (This script can still be found in /opt/prov/bin)\n" +fi + +printf "\nReboot to apply all changes.\n\n" + +read -p "Would you like to reboot now? (y/N)" -n 1 -r +if echo $REPLY | grep -Eq '^[Yy]$'; then + printf "\n Rebooting...\n\n" + shutdown -r now + exit 42 +else + printf "\nReboot has been deferred.\n" + exit 0 +fi +