summaryrefslogtreecommitdiffhomepage
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/README.md1
-rwxr-xr-xtools/setup-unit270
-rwxr-xr-xtools/unitc53
3 files changed, 284 insertions, 40 deletions
diff --git a/tools/README.md b/tools/README.md
index f534aa1f..1a631e10 100644
--- a/tools/README.md
+++ b/tools/README.md
@@ -35,6 +35,7 @@ web page with NGINX Unit.
|---------|-|
| filename … | Read configuration data consequently from the specified files instead of stdin.
| _HTTP method_ | It is usually not required to specify a HTTP method. `GET` is used to read the configuration. `PUT` is used when making configuration changes unless a specific method is provided.
+| `edit` | Opens **URI** in the default editor for interactive configuration. The [jq](https://stedolan.github.io/jq/) tool is required for this option.
| `INSERT` | A _virtual_ HTTP method that prepends data when the URI specifies an existing array. The [jq](https://stedolan.github.io/jq/) tool is required for this option.
| `-q` \| `--quiet` | No output to stdout.
diff --git a/tools/setup-unit b/tools/setup-unit
index de1d4f5f..38592fe3 100755
--- a/tools/setup-unit
+++ b/tools/setup-unit
@@ -30,16 +30,13 @@ test -v ZSH_VERSION \
export LC_ALL=C
-program_name="$0";
-prog_name="$(basename $program_name)";
-
dry_run='no';
help_unit()
{
cat <<__EOF__ ;
SYNOPSIS
- $program_name [-h] COMMAND [ARGS]
+ $0 [-h] COMMAND [ARGS]
Subcommands
├── repo-config [-hn] [PKG-MANAGER OS-NAME OS-VERSION]
@@ -49,7 +46,7 @@ DESCRIPTION
This script simplifies installing and configuring an NGINX Unit server
for first-time users.
- Run '$program_name COMMAND -h' for more information on a command.
+ Run '$0 COMMAND -h' for more information on a command.
COMMANDS
repo-config
@@ -75,11 +72,12 @@ help_more_unit()
{
cat <<__EOF__ ;
SYNOPSIS
- $program_name [-h] COMMAND [ARGS]
+ $0 [-h] COMMAND [ARGS]
Subcommands
├── cmd [-h]
├── ctl [-h] [-s SOCK] SUBCOMMAND [ARGS]
+ │   ├── edit [-h] PATH
│   ├── http [-h] [-c CURLOPT] METHOD PATH
│   └── insert [-h] PATH INDEX
├── freeport [-h]
@@ -87,6 +85,7 @@ SYNOPSIS
├── os-probe [-h]
├── ps [-h] [-t TYPE]
├── repo-config [-hn] [PKG-MANAGER OS-NAME OS-VERSION]
+ ├── restart [-hls]
├── sock [-h] SUBCOMMAND [ARGS]
│   ├── filter [-chs]
│   └── find [-h]
@@ -96,7 +95,7 @@ DESCRIPTION
This script simplifies installing and configuring
an NGINX Unit server for first-time users.
- Run '$program_name COMMAND -h' for more information on a command.
+ Run '$0 COMMAND -h' for more information on a command.
COMMANDS
cmd Print the invocation line of unitd(8).
@@ -137,12 +136,12 @@ __EOF__
warn()
{
- >&2 echo "$prog_name: error: $*";
+ >&2 echo "$(basename "$0"): error: $*";
}
err()
{
- >&2 echo "$prog_name: error: $*";
+ >&2 echo "$(basename "$0"): error: $*";
exit 1;
}
@@ -167,7 +166,7 @@ help_unit_cmd()
{
cat <<__EOF__ ;
SYNOPSIS
- $program_name cmd [-h]
+ $0 cmd [-h]
DESCRIPTION
Print the invocation line of running unitd(8) instances.
@@ -207,19 +206,22 @@ help_unit_ctl()
{
cat <<__EOF__ ;
SYNOPSIS
- $program_name ctl [-h] [-s SOCK] SUBCOMMAND [ARGS]
+ $0 ctl [-h] [-s SOCK] SUBCOMMAND [ARGS]
Subcommands
+ ├── edit [-h] PATH
├── http [-h] [-c CURLOPT] METHOD PATH
└── insert [-h] PATH INDEX
DESCRIPTION
Control a running unitd(8) instance through its control API socket.
- Run '$program_name ctl SUBCOMMAND -h' for more information on a
+ Run '$0 ctl SUBCOMMAND -h' for more information on a
subcommand.
SUBCOMMANDS
+ edit Edit the unitd(8) configuration with an editor.
+
http Send an HTTP request to the control API socket.
insert Insert an element at the specified index into an array in the
@@ -300,6 +302,10 @@ unit_ctl()
fi;
case $1 in
+ edit)
+ shift;
+ unit_ctl_edit ${remote:+ ---r $remote} ---s "$sock" $@;
+ ;;
http)
shift;
unit_ctl_http ${remote:+ ---r $remote} ---s "$sock" $@;
@@ -315,11 +321,115 @@ unit_ctl()
}
+help_unit_ctl_edit()
+{
+ cat <<__EOF__ ;
+SYNOPSIS
+ $0 ctl [CTL-OPTS] edit [-h] PATH
+
+DESCRIPTION
+ Edit the JSON configuration with an editor. The current configuration
+ is downloaded into a temporary file, open with the editor, and then
+ sent back to the control API socket.
+
+ The following editors are tried in this order of preference: \$VISUAL,
+ \$EDITOR, editor(1), vi(1), vim(1), ed(1).
+
+
+OPTIONS
+ -h, --help
+ Print this help.
+
+ENVIRONMENT
+ VISUAL
+ EDITOR
+ See environ(7).
+
+SEE ALSO
+ $0 ctl http -h;
+
+ update-alternatives(1)
+
+__EOF__
+}
+
+
+unit_ctl_edit()
+{
+ while test $# -ge 1; do
+ case "$1" in
+ -h | --help)
+ help_unit_ctl_edit;
+ exit 0;
+ ;;
+ ---r | ----remote)
+ local remote="$2";
+ shift;
+ ;;
+ ---s | ----sock)
+ local sock="$2";
+ shift;
+ ;;
+ -*)
+ err "ctl: edit: $1: Unknown option.";
+ ;;
+ *)
+ break;
+ ;;
+ esac;
+ shift;
+ done;
+
+ if ! test $# -ge 1; then
+ err 'ctl: insert: PATH: Missing argument.';
+ fi;
+ local req_path="$1";
+
+ if test -v remote; then
+ local remote_sock="$(echo "$sock" | unit_sock_filter -s)";
+ local local_sock="$(mktemp -u -p /var/run/unit/)";
+ local ssh_ctrl="$(mktemp -u -p /var/run/unit/)";
+
+ mkdir -p /var/run/unit/;
+
+ ssh -fMNnT -S "$ssh_ctrl" \
+ -o 'ExitOnForwardFailure yes' \
+ -L "$local_sock:$remote_sock" "$remote";
+
+ sock="unix:$local_sock";
+ fi;
+
+ local tmp="$(mktemp ||:)";
+
+ unit_ctl_http ---s "$sock" -c --no-progress-meter GET "$req_path" \
+ </dev/null >"$tmp" \
+ ||:;
+
+ $(
+ ((test -v VISUAL && test -n "$VISUAL") && printf '%s\n' "$VISUAL") \
+ || ((test -v EDITOR && test -n "$EDITOR") && printf '%s\n' "$EDITOR") \
+ || command -v editor \
+ || command -v vi \
+ || command -v vim \
+ || echo ed;
+ ) "$tmp" \
+ ||:;
+
+ unit_ctl_http ---s "$sock" PUT "$req_path" <"$tmp" \
+ ||:;
+
+ if test -v remote; then
+ ssh -S "$ssh_ctrl" -O exit "$remote" 2>/dev/null;
+ unlink "$local_sock";
+ fi;
+}
+
+
help_unit_ctl_http()
{
cat <<__EOF__ ;
SYNOPSIS
- $program_name ctl [CTL-OPTS] http [-h] [-c CURLOPT] METHOD PATH
+ $0 ctl [CTL-OPTS] http [-h] [-c CURLOPT] METHOD PATH
DESCRIPTION
Send an HTTP request to the unitd(8) control API socket.
@@ -341,7 +451,7 @@ ENVIRONMENT
Equivalent to the option -c (--curl).
EXAMPLES
- $program_name ctl http -c --no-progress-meter GET /config >tmp;
+ $0 ctl http -c --no-progress-meter GET /config >tmp;
SEE ALSO
<https://unit.nginx.org/controlapi/#api-manipulation>
@@ -424,7 +534,7 @@ help_unit_ctl_insert()
{
cat <<__EOF__ ;
SYNOPSIS
- $program_name ctl [CTL-OPTS] insert [-h] PATH INDEX
+ $0 ctl [CTL-OPTS] insert [-h] PATH INDEX
DESCRIPTION
Insert an element at the specified position (INDEX) into the JSON array
@@ -437,7 +547,7 @@ OPTIONS
Print this help.
SEE ALSO
- $program_name ctl http -h;
+ $0 ctl http -h;
__EOF__
}
@@ -514,7 +624,7 @@ help_unit_ctl_welcome()
{
cat <<__EOF__ ;
SYNOPSIS
- $program_name welcome [-hn]
+ $0 welcome [-hn]
DESCRIPTION
This script tests an NGINX Unit installation by creating an initial
@@ -676,7 +786,7 @@ unit_ctl_welcome()
<hr>
<p><a href="https://unit.nginx.org/?referer=welcome">NGINX Unit &mdash; the universal web app server</a><br>
- NGINX, Inc. &copy; 2022</p>
+ NGINX, Inc. &copy; 2023</p>
</body>
</html>
__EOF__';
@@ -720,7 +830,7 @@ help_unit_freeport()
{
cat <<__EOF__ ;
SYNOPSIS
- $program_name freeport [-h]
+ $0 freeport [-h]
DESCRIPTION
Print an available TCP port.
@@ -828,7 +938,7 @@ help_unit_json_ins()
{
cat <<__EOF__ ;
SYNOPSIS
- $program_name json-ins [-hn] JSON INDEX
+ $0 json-ins [-hn] JSON INDEX
ARGUMENTS
JSON Path to a JSON file containing a top-level array.
@@ -901,7 +1011,7 @@ help_unit_os_probe()
{
cat <<__EOF__ ;
SYNOPSIS
- $program_name os-probe [-h]
+ $0 os-probe [-h]
DESCRIPTION
This script probes the OS and prints three fields, delimited by ':';
@@ -978,7 +1088,7 @@ help_unit_ps()
{
cat <<__EOF__ ;
SYNOPSIS
- $program_name ps [-h] [-t TYPE]
+ $0 ps [-h] [-t TYPE]
DESCRIPTION
List unitd(8) processes.
@@ -1034,7 +1144,7 @@ unit_ps()
shift;
done;
- ps ax \
+ ps awwx \
| if test -v type; then
grep ${type_c:+-e 'unit: controller'} \
${type_m:+-e 'unit: main'} \
@@ -1051,7 +1161,7 @@ help_unit_repo_config()
{
cat <<__EOF__ ;
SYNOPSIS
- $program_name repo-config [-hn] [PKG-MANAGER OS-NAME OS-VERSION]
+ $0 repo-config [-hn] [PKG-MANAGER OS-NAME OS-VERSION]
DESCRIPTION
This script configures the NGINX Unit repository for the system
@@ -1082,11 +1192,11 @@ OPTIONS
what it does.
EXAMPLES
- $ $prog_name repo-config apt debian bullseye;
- $ $prog_name repo-config apt ubuntu jammy;
- $ $prog_name repo-config dnf fedora 36;
- $ $prog_name repo-config dnf rhel 9;
- $ $prog_name repo-config yum amzn2 2;
+ $ $(basename "$0") repo-config apt debian bullseye;
+ $ $(basename "$0") repo-config apt ubuntu jammy;
+ $ $(basename "$0") repo-config dnf fedora 36;
+ $ $(basename "$0") repo-config dnf rhel 9;
+ $ $(basename "$0") repo-config yum amzn2 2;
__EOF__
}
@@ -1222,11 +1332,101 @@ __EOF__";
}
+help_unit_restart()
+{
+ cat <<__EOF__ ;
+SYNOPSIS
+ $0 restart [-hls]
+
+DESCRIPTION
+ Restart all running unitd(8) instances.
+
+OPTIONS
+ -h, --help
+ Print this help.
+
+ -l, --log
+ Reset log file.
+
+ -s, --statedir
+ Reset \$statedir.
+
+CAVEATS
+ This command will ask for confirmation before removing
+ directories; please review those prompts with care, as unknown
+ bugs in the command may attempt to wipe your file system.
+
+__EOF__
+}
+
+
+unit_restart()
+{
+ while test $# -ge 1; do
+ case "$1" in
+ -h | --help)
+ help_unit_restart;
+ exit 0;
+ ;;
+ -l | --log)
+ local log_flag='yes';
+ ;;
+ -s | --statedir)
+ local state_flag='yes';
+ ;;
+ -*)
+ err "restart: $1: Unknown option.";
+ ;;
+ *)
+ err "restart: $1: Unknown argument.";
+ ;;
+ esac;
+ shift;
+ done;
+
+ local cmds="$(unit_cmd)";
+
+ pkill -e unitd;
+
+ printf '%s\n' "$cmds" \
+ | while read -r cmd; do
+ if test -v log_flag; then
+ (
+ echo "$cmd" \
+ | grep '\--log' \
+ | sed 's/.*--log \+\([^ ]\+\).*/\1/' \
+ || eval $cmd --help \
+ | grep -A1 '\--log FILE' \
+ | grep 'default:' \
+ | sed 's/.*"\(.*\)".*/\1/';
+ ) \
+ | xargs rm -f;
+ fi;
+
+ if test -v state_flag; then
+ (
+ echo "$cmd" \
+ | grep '\--statedir' \
+ | sed 's/.*--statedir \+\([^ ]\+\).*/\1/' \
+ || eval $cmd --help \
+ | grep -A1 '\--statedir DIR' \
+ | grep 'default:' \
+ | sed 's/.*"\(.*\)".*/\1/';
+ ) \
+ | xargs -I {} find {} -mindepth 1 -maxdepth 1 \
+ | xargs rm -rfi;
+ fi;
+
+ eval $cmd;
+ done;
+}
+
+
help_unit_sock()
{
cat <<__EOF__ ;
SYNOPSIS
- $program_name sock [-h] SUBCOMMAND [ARGS]
+ $0 sock [-h] SUBCOMMAND [ARGS]
Subcommands
├── filter [-ch]
@@ -1236,7 +1436,7 @@ DESCRIPTION
Print the control API socket address of running unitd(8)
instances.
- Run '$program_name sock SUBCOMMAND -h' for more information on a
+ Run '$0 sock SUBCOMMAND -h' for more information on a
subcommand.
SUBCOMMANDS
@@ -1297,7 +1497,7 @@ help_unit_sock_filter()
{
cat <<__EOF__ ;
SYNOPSIS
- $program_name sock filter [-chs]
+ $0 sock filter [-chs]
DESCRIPTION
Filter the output of the 'sock find' command and transform it to
@@ -1376,7 +1576,7 @@ help_unit_sock_find()
{
cat <<__EOF__ ;
SYNOPSIS
- $program_name sock find [-h]
+ $0 sock find [-h]
DESCRIPTION
Find and print the control API socket address of running
@@ -1481,6 +1681,10 @@ repo-config)
shift;
unit_repo_config $@;
;;
+restart)
+ shift;
+ unit_restart $@;
+ ;;
sock)
shift;
unit_sock $@;
diff --git a/tools/unitc b/tools/unitc
index 9973e62d..877e11d4 100755
--- a/tools/unitc
+++ b/tools/unitc
@@ -1,7 +1,7 @@
#!/bin/bash
# unitc - a curl wrapper for configuring NGINX Unit
# https://github.com/nginx/unit/tree/master/tools
-# NGINX, Inc. (c) 2022
+# NGINX, Inc. (c) 2023
# Defaults
#
@@ -32,7 +32,7 @@ while [ $# -gt 0 ]; do
shift
;;
- "GET" | "PUT" | "POST" | "DELETE" | "INSERT")
+ "GET" | "PUT" | "POST" | "DELETE" | "INSERT" | "EDIT")
METHOD=$OPTION
shift
;;
@@ -71,6 +71,7 @@ USAGE: ${0##*/} [options] URI
General options
filename … # Read configuration data from files instead of stdin
HTTP method # Default=GET, or PUT with config data (case-insensitive)
+ EDIT # Opens the URI contents in \$EDITOR
INSERT # Virtual HTTP method to prepend data to an existing array
-q | --quiet # No output to stdout
@@ -129,12 +130,23 @@ if [ $REMOTE -eq 0 ]; then
exit 1
fi
- # Get control address
+ # Obtain any optional startup parameters from the 'unitd: main' process
+ # so we can get the actual control address and error log location.
+ # Command line options and output of ps(1) is notoriously variable across
+ # different *nix/BSD platforms so multiple attempts might be needed.
#
- PARAMS=$(ps $PID | grep unitd | cut -f2- -dv | tr '[]' ' ' | cut -f3- -d ' ' | sed -e 's/ --/\n--/g')
+ PARAMS=$((ps -wwo args=COMMAND -p $PID || ps $PID) 2> /dev/null | grep unit | tr '[]' ^ | cut -f2 -d^ | sed -e 's/ --/\n--/g')
+ if [ "$PARAMS" = "" ]; then
+ echo "${0##*/}: WARNING: unable to identify unitd command line parameters for PID $PID, assuming unitd defaults from \$PATH"
+ PARAMS=unitd
+ fi
CTRL_ADDR=$(echo "$PARAMS" | grep '\--control' | cut -f2 -d' ')
if [ "$CTRL_ADDR" = "" ]; then
- CTRL_ADDR=$($(echo "$PARAMS" | grep unitd) --help | grep -A1 '\--control' | tail -1 | cut -f2 -d\")
+ CTRL_ADDR=$($(echo "$PARAMS") --help | grep -A1 '\--control' | tail -1 | cut -f2 -d\")
+ fi
+ if [ "$CTRL_ADDR" = "" ]; then
+ echo "${0##*/}: ERROR: cannot detect control socket. Did you start unitd with a relative path? Try starting unitd with --control option."
+ exit 2
fi
# Prepare for network or Unix socket addressing
@@ -156,7 +168,11 @@ if [ $REMOTE -eq 0 ]; then
#
ERROR_LOG=$(echo "$PARAMS" | grep '\--log' | cut -f2 -d' ')
if [ "$ERROR_LOG" = "" ]; then
- ERROR_LOG=$($(echo "$PARAMS" | grep unitd) --help | grep -A1 '\--log' | tail -1 | cut -f2 -d\")
+ ERROR_LOG=$($(echo "$PARAMS") --help | grep -A1 '\--log' | tail -1 | cut -f2 -d\")
+ fi
+ if [ "$ERROR_LOG" = "" ]; then
+ echo "${0##*/}: WARNING: cannot detect unit log file (will not be monitored). If you started unitd from a relative path then try using the --log option."
+ ERROR_LOG=/dev/null
fi
# Cache the discovery for this unit PID (and cleanup any old files)
@@ -190,6 +206,29 @@ fi
if [ -t 0 ] && [ ${#CONF_FILES[@]} -eq 0 ]; then
if [ "$METHOD" = "DELETE" ]; then
$SSH_CMD curl -X $METHOD $UNIT_CTRL$URI 2> /tmp/${0##*/}.$$ | $OUTPUT
+ elif [ "$METHOD" = "EDIT" ]; then
+ EDITOR=$(test "$EDITOR" && printf '%s' "$EDITOR" || command -v editor || command -v vim || echo vi)
+ EDIT_FILENAME=/tmp/${0##*/}.$$${URI//\//_}
+ $SSH_CMD curl -fsS $UNIT_CTRL$URI > $EDIT_FILENAME || exit 2
+ if [ "${URI:0:12}" = "/js_modules/" ]; then
+ if ! hash jq 2> /dev/null; then
+ echo "${0##*/}: ERROR: jq(1) is required to edit JavaScript modules; install at <https://stedolan.github.io/jq/>"
+ exit 1
+ fi
+ jq -r < $EDIT_FILENAME > $EDIT_FILENAME.js # Unescape linebreaks for a better editing experience
+ EDIT_FILE=$EDIT_FILENAME.js
+ $EDITOR $EDIT_FILENAME.js || exit 2
+ # Remove the references, delete old config, push new config+reference
+ $SSH_CMD curl -fsS $UNIT_CTRL/config/settings/js_module > /tmp/${0##*/}.$$_js_module && \
+ $SSH_CMD curl -X DELETE $UNIT_CTRL/config/settings/js_module && \
+ $SSH_CMD curl -fsSX DELETE $UNIT_CTRL$URI 2> /tmp/${0##*/}.$$ && \
+ printf "%s" "$(< $EDIT_FILENAME.js)" | $SSH_CMD curl -fX PUT --data-binary @- $UNIT_CTRL$URI 2> /tmp/${0##*/}.$$ && \
+ $SSH_CMD curl -X PUT --data-binary @/tmp/${0##*/}.$$_js_module $UNIT_CTRL/config/settings/js_module 2> /tmp/${0##*/}.$$
+ else
+ tr -d '\r' < $EDIT_FILENAME > $EDIT_FILENAME.json # Remove carriage-return from newlines
+ $EDITOR $EDIT_FILENAME.json || exit 2
+ $SSH_CMD curl -X PUT --data-binary @$EDIT_FILENAME.json $UNIT_CTRL$URI 2> /tmp/${0##*/}.$$ | $OUTPUT
+ fi
else
SHOW_LOG=$(echo $URI | grep -c ^/control/)
$SSH_CMD curl $UNIT_CTRL$URI 2> /tmp/${0##*/}.$$ | $OUTPUT
@@ -225,7 +264,7 @@ if [ $CURL_STATUS -ne 0 ]; then
fi
exit 4
fi
-rm -f /tmp/${0##*/}.$$ 2> /dev/null
+rm -f /tmp/${0##*/}.$$* 2> /dev/null
if [ $SHOW_LOG -gt 0 ] && [ $NOLOG -eq 0 ] && [ $QUIET -eq 0 ]; then
echo -n "${0##*/}: Waiting for log..."