sermoni

"Service monitor" / cronjob status service
Log | Files | Refs

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