setup.sh (5202B)
1 #/bin/bash 2 3 # The easiest way to set up services is to run the following as root / su: 4 # $ . <(curl -fsSL {{.HostName}}/setup) 5 6 sermoni=https://{{.HostName}} 7 8 ### Create unique token unless one exists 9 if [ ! -f $HOME/.sermoni-token ]; then 10 TOKEN=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 16 ; echo '') 11 printf "Server name: " 12 read SERVERNAME 13 TOKEN=$TOKEN-$SERVERNAME 14 printf $TOKEN > $HOME/.sermoni-token 15 else 16 TOKEN=$(cat $HOME/.sermoni-token) 17 fi 18 19 ### Install scripts 20 21 # Find the first directory in $PATH 22 IFS=":" read -ra BIN_DIR <<< "$PATH" 23 # TODO: Allow choosing between dirs in $PATH? 24 INSTALL_DIR=$BIN_DIR # Use first path from $PATH 25 26 # sermonicli 27 cat <<- 'EOF' > $INSTALL_DIR/sermonicli 28 #!/bin/bash 29 30 sermoni=https://{{.HostName}} 31 TOKEN="$(cat $HOME/.sermoni-token)" 32 33 # Prompt for password until the correct one is given 34 get_password() { 35 VALIDPW=0 36 while [ $VALIDPW -eq 0 ]; do 37 printf "Password: " 38 read -s PASSWD; echo 39 PASSHASH="$(printf $PASSWD | sha256sum - | awk '{print $1}')" 40 RESPONSE="$(curl -s -H "Pass-Hash: $PASSHASH" $sermoni/services)" 41 if [ -z "$(echo $RESPONSE | grep 'Invalid passphrase')" ]; then 42 VALIDPW=1 43 else 44 echo $RESPONSE 45 echo "Please try again, or press Ctrl+C to exit" 46 fi 47 done 48 } 49 50 # Prompt for services until no service id is given 51 add_services() { 52 echo "Adding new services. Give an empty service ID to exit." 53 while [ true ]; do 54 printf "Service ID (e.g. 'backup-database'): "; read s_id; 55 if [ -z "$s_id" ]; then 56 break 57 fi 58 printf "Service name (e.g. 'Database backup'): "; read s_name; 59 printf "Expectation period (in hours): "; read s_period; 60 printf "Max number of events: "; read s_maxevents; 61 if [ -z "$s_maxevents" ]; then 62 s_maxevents=0 63 fi 64 printf "Service description: "; read s_desc; 65 if [ -z "$s_period" ]; then 66 s_period=0 67 fi 68 payload="{\"token\": \"$TOKEN:$s_id\", \"name\": \"$s_name\", \"maxevents\": $s_maxevents, \"period\": $(($s_period*60*60*1000)), \"description\": \"$s_desc\"}" 69 echo "$payload" 70 curl -s \ 71 -H "Content-Type: application/json" \ 72 -H "Pass-Hash: $PASSHASH" \ 73 -d "$payload" \ 74 $sermoni/services 75 done 76 } 77 78 # Silent for the sake of sermonic. TODO: 'verbose' version 79 report_event() { 80 service="$1"; status="$2"; title="$3"; details="$4" 81 token="$(cat $HOME/.sermoni-token):$service" 82 payload="{\"status\": \"$status\", \"title\": \"$title\", \"details\": \"$details\"}" 83 curl -s \ 84 -H "Content-Type: application/json" \ 85 -H "Service-Token: $token" \ 86 -d "$payload" \ 87 $sermoni/events 88 } 89 90 if [ "$1" == "add" ]; then 91 get_password 92 add_services 93 elif [ "$1" == "report" ]; then 94 report_event "$2" "$3" "$4" "$5" 95 else 96 echo "Usage:" 97 echo " $0 add" 98 echo " Add a new service interactively" 99 echo " $0 report <service ID> <status> <title> <details>" 100 echo " Report an event 'manually'" 101 fi 102 103 EOF 104 105 # sermonic 106 cat <<- 'EOF' > $INSTALL_DIR/sermonic 107 # "sermonicronic" report 108 # SYNTAX 109 # sermonic backup-service /full/path/to/backup-service.sh 110 # BEHAVIOR 111 # - On success, inlude last 10 or so lines of output (for info about files written etc) 112 # OR might want to make that the responsibility of the script being called. 113 # - On error, format the details like cronic does 114 115 # Based on cronic: https://habilis.net/cronic/ 116 117 set -e 118 119 SERVICEID=$1 120 TMP=$(mktemp -d) 121 OUT=$TMP/sermonic.out 122 ERR=$TMP/sermonic.err 123 TRACE=$TMP/sermonic.trace 124 FULLDETAILS=$TMP/sermonic.details 125 126 out() { 127 echo "$@" >> $FULLDETAILS 128 } 129 130 json_escape () { 131 printf '%s' "$1" | python -c 'import json,sys; print(json.dumps(sys.stdin.read()))[1:-1]' 132 } 133 134 set +e 135 # Run all args after first 136 "${@:2}" >$OUT 2>$TRACE 137 RESULT=$? 138 set -e 139 140 # This is just to remove the debug output prefix, I think 141 PATTERN="^${PS4:0:1}\\+${PS4:1}" 142 if grep -aq "$PATTERN" $TRACE 143 then 144 ! grep -av "$PATTERN" $TRACE > $ERR 145 else 146 ERR=$TRACE 147 fi 148 149 if [ $RESULT -ne 0 -o -s "$ERR" ]; then 150 out sermonic detected failure or error output for the service \'$1\' 151 out 152 out FULL COMMAND: 153 out ${@:2} 154 out 155 out RESULT CODE: 156 out $RESULT 157 out 158 out ERROR OUTPUT: 159 out $(cat "$ERR") 160 out 161 out STANDARD OUTPUT: 162 out $(cat "$OUT") 163 if [ $TRACE != $ERR ] 164 then 165 out 166 out "TRACE-ERROR OUTPUT:" 167 out $(cat "$TRACE") 168 fi 169 if [ -n "$NO_DETAILS" ]; then 170 details="Details written to $FULLDETAILS" 171 else 172 details=$(json_escape "$(cat ${FULLDETAILS})") 173 rm -rf "$TMP" 174 fi 175 status=error 176 title="'$(basename $2)' failed" 177 else 178 if [ -n "$NO_DETAILS" ]; then 179 details="Details written to $OUT" 180 else 181 details=$(json_escape "$(cat ${OUT})") 182 rm -rf "$TMP" 183 fi 184 status=ok 185 title="'$(basename $2)' finished successfully" 186 fi 187 188 189 sermonicli report $SERVICEID $status "$title" "$details" 190 191 EOF 192 193 chmod +x $INSTALL_DIR/sermonicli 194 chmod +x $INSTALL_DIR/sermonic