|
#!/bin/bash |
|
# unitc - a curl wrapper for configuring NGINX Unit |
|
# [v1.3 30-Jul-2022] Liam Crilly <[email protected]> |
|
# |
|
# CHANGELOG |
|
# v1.3 Bug fixes and improved error handling |
|
# v1.2 Accepts lower-case HTTP methods, simpler/portable cache format |
|
# v1.1 Uses jq(1) if available for prettified output, added --help |
|
# v1.0 Initial version with socket detection and log monitoring |
|
# |
|
# TODO |
|
# - Iteratively scan for new log entries |
|
# - Optionally provide JSON config as filename on command line |
|
|
|
# Defaults |
|
# |
|
QUIET=0 |
|
METHOD=PUT |
|
SHOW_LOG=1 |
|
|
|
while [ $# -gt 1 ]; do |
|
OPTION=`echo $1 | tr '[a-z]' '[A-Z]'` |
|
case $OPTION in |
|
"-H" | "--HELP") |
|
shift |
|
;; |
|
|
|
"-Q" | "--QUIET") |
|
QUIET=1 |
|
shift |
|
;; |
|
|
|
"GET" | "PUT" | "POST" | "DELETE") |
|
METHOD=$OPTION |
|
shift |
|
;; |
|
|
|
"HEAD" | "PATCH" | "PURGE" | "OPTIONS") |
|
echo "${0##*/}: ERROR: Invalid HTTP method ($OPTION)" |
|
exit 1 |
|
;; |
|
|
|
*) |
|
echo "${0##*/}: ERROR: Invalid option ($1)" |
|
exit 1 |
|
;; |
|
esac |
|
done |
|
|
|
if [ $# -lt 1 ] || [ "${1:0:1}" = "-" ]; then |
|
echo "USAGE: ${0##*/} [HTTP method] [--quiet] URI" |
|
echo " - Configuration JSON is read from stdin" |
|
echo " - Default method is PUT with stdin, else GET" |
|
echo " - The control socket is automatically detected" |
|
exit 1 |
|
fi |
|
|
|
if [ "${1:0:1}" != "/" ]; then |
|
echo "${0##*/}: ERROR: Invalid configuration URI" |
|
exit 1 |
|
fi |
|
|
|
# Check if Unit is running, find the main process |
|
# |
|
PID=(`ps ax | grep unit:\ main | grep -v \ grep | awk '{print $1}'`) |
|
if [ ${#PID[@]} -eq 0 ]; then |
|
echo "${0##*/}: ERROR: unitd not running" |
|
exit 1 |
|
elif [ ${#PID[@]} -gt 1 ]; then |
|
echo "${0##*/}: ERROR: multiple unitd processes detected (${PID[@]})" |
|
exit 1 |
|
fi |
|
|
|
# Read the significant unitd conifuration from cache file (or create it) |
|
# |
|
if [[ -f /tmp/${0##*/}.$PID ]]; then |
|
source /tmp/${0##*/}.$PID |
|
else |
|
PARAMS=`ps -p $PID | grep unitd | cut -f2- -dv | tr '[]' ' ' | cut -f4- -d ' ' | sed -e 's/ --/\n--/g'` |
|
|
|
# Get control address |
|
# |
|
CTRL_ADDR=`echo "$PARAMS" | grep '\--control' | cut -f2 -d' '` |
|
if [ "$CTRL_ADDR" = "" ]; then |
|
CTRL_ADDR=`unitd --help | grep -A1 '\--control' | tail -1 | cut -f2 -d\"` |
|
fi |
|
|
|
# Prepare for network or Unix socket addressing |
|
# |
|
if [ `echo $CTRL_ADDR | grep -c ^unix:` -eq 1 ]; then |
|
CURL_ADDR="--unix-socket `echo $CTRL_ADDR | cut -f2- -d:` _" |
|
else |
|
CURL_ADDR="http://$CTRL_ADDR" |
|
fi |
|
|
|
# Get error log filename |
|
# |
|
ERROR_LOG=`echo "$PARAMS" | grep '\--log' | cut -f2 -d' '` |
|
if [ "$ERROR_LOG" = "" ]; then |
|
ERROR_LOG=`unitd --help | grep -A1 '\--log' | tail -1 | cut -f2 -d\"` |
|
fi |
|
|
|
# Cache the discovery for this unit PID (and cleanup any old files) |
|
# |
|
rm /tmp/${0##*/}.* 2> /dev/null |
|
echo CURL_ADDR=\"${CURL_ADDR}\" > /tmp/${0##*/}.$PID |
|
echo ERROR_LOG=${ERROR_LOG} >> /tmp/${0##*/}.$PID |
|
fi |
|
|
|
# Test for jq |
|
# |
|
if hash jq 2> /dev/null; then |
|
PRETTY="jq" |
|
else |
|
PRETTY="cat" |
|
fi |
|
|
|
# Get current length of error log before we make any changes |
|
# |
|
if [ -f $ERROR_LOG ]; then |
|
LOG_LEN=`wc -l < $ERROR_LOG` |
|
else |
|
QUIET=1 |
|
fi |
|
|
|
# Adjust HTTP method and curl params based on presence of stdin payload |
|
# |
|
if [ -t 0 ]; then |
|
if [ "$METHOD" = "DELETE" ]; then |
|
curl -s -X $METHOD $CURL_ADDR$1 | $PRETTY |
|
else |
|
SHOW_LOG=0 |
|
curl -s $CURL_ADDR$1 | $PRETTY |
|
fi |
|
else |
|
echo "$(cat)" | curl -s -X $METHOD --data-binary @- $CURL_ADDR$1 | $PRETTY |
|
fi |
|
if [ ${PIPESTATUS[0]} -ne 0 ]; then |
|
echo "${0##*/}: ERROR: curl exited with an error" |
|
fi |
|
|
|
if [[ $SHOW_LOG -gt 0 && $QUIET -eq 0 ]]; then |
|
echo -n "${0##*/}: Waiting for log..." |
|
sleep $SHOW_LOG |
|
echo "" |
|
sed -n $((LOG_LEN+1)),\$p $ERROR_LOG |
|
fi |
|
|
|
# vim: syntax=bash |