543d478e12
Almost equivalent to b42f6b1d
("Tools: unitc edit mode for interactive
configuration."), implemented by Liam in tools/unitc.
I chose to give preference to vi(1) over vim(1) because Debian has vi(1)
as part of update-alternatives(1), so that sysadmins can configure it to
be a symlink to their favourite vi(1) implementation or variant.
We're ignoring the errors of the commands due to having the SSH tunnel
open. I should fix the script to use traps to close the tunnel on any
error, so we don't leak tunnels. Then, we'll be able to not ignore
curl(1) or editor errors. That will also probably allow moving the
tunneling code to the ctl command, thus deduplicating code.
Cc: Liam Crilly <liam@nginx.com>
Cc: Andrew Clayton <a.clayton@nginx.com>
Signed-off-by: Alejandro Colomar <alx@nginx.com>
1699 lines
40 KiB
Bash
Executable file
1699 lines
40 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
|
|
#####################################################################
|
|
#
|
|
# Copyright (C) NGINX, Inc.
|
|
# Author: NGINX Unit Team, F5 Inc.
|
|
#
|
|
#####################################################################
|
|
|
|
|
|
if test -n ${BASH_VERSION} && test "${BASH_VERSINFO[0]}" -eq 3; then
|
|
>&2 cat <<__EOF__ ;
|
|
Your version of bash(1) isn't supported by this script. You're probably
|
|
running on macOS. We recommend that you either install a newer version
|
|
of bash(1) or run this script with another shell, such as zsh(1):
|
|
|
|
$ ${SUDO_USER:+sudo }zsh $0 ...
|
|
__EOF__
|
|
exit 1;
|
|
fi;
|
|
|
|
|
|
set -Eefuo pipefail;
|
|
|
|
test -v BASH_VERSION \
|
|
&& shopt -s lastpipe;
|
|
|
|
test -v ZSH_VERSION \
|
|
&& setopt sh_word_split;
|
|
|
|
export LC_ALL=C
|
|
|
|
dry_run='no';
|
|
|
|
help_unit()
|
|
{
|
|
cat <<__EOF__ ;
|
|
SYNOPSIS
|
|
$0 [-h] COMMAND [ARGS]
|
|
|
|
Subcommands
|
|
├── repo-config [-hn] [PKG-MANAGER OS-NAME OS-VERSION]
|
|
└── welcome [-hn]
|
|
|
|
DESCRIPTION
|
|
This script simplifies installing and configuring an NGINX Unit server
|
|
for first-time users.
|
|
|
|
Run '$0 COMMAND -h' for more information on a command.
|
|
|
|
COMMANDS
|
|
repo-config
|
|
Configure your package manager with the NGINX Unit repository
|
|
for later installation.
|
|
|
|
welcome
|
|
Create an initial configuration to serve a welcome web page
|
|
with NGINX Unit.
|
|
|
|
OPTIONS
|
|
-h, --help
|
|
Print this help.
|
|
|
|
--help-more
|
|
Print help for more commands. They are experimental. Using
|
|
these isn't recommended, unless you know what you're doing.
|
|
|
|
__EOF__
|
|
}
|
|
|
|
help_more_unit()
|
|
{
|
|
cat <<__EOF__ ;
|
|
SYNOPSIS
|
|
$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]
|
|
├── json-ins [-hn] JSON INDEX
|
|
├── 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]
|
|
└── welcome [-hn]
|
|
|
|
DESCRIPTION
|
|
This script simplifies installing and configuring
|
|
an NGINX Unit server for first-time users.
|
|
|
|
Run '$0 COMMAND -h' for more information on a command.
|
|
|
|
COMMANDS
|
|
cmd Print the invocation line of unitd(8).
|
|
|
|
ctl Control a running unitd(8) instance via its control API socket.
|
|
|
|
freeport
|
|
Print an available TCP port.
|
|
|
|
json-ins
|
|
Insert a JSON element read from standard input into a JSON
|
|
array read from a file at a given INDEX.
|
|
|
|
os-probe
|
|
Probe the OS and print details about its version.
|
|
|
|
ps List unitd(8) processes.
|
|
|
|
repo-config
|
|
Configure your package manager with the NGINX Unit
|
|
repository for later installation.
|
|
|
|
sock Print the control API socket address.
|
|
|
|
welcome
|
|
Create an initial configuration to serve a welcome web page
|
|
with NGINX Unit.
|
|
|
|
OPTIONS
|
|
-h, --help
|
|
Print basic help (some commands are hidden).
|
|
|
|
--help-more
|
|
Print the hidden help with more commands.
|
|
|
|
__EOF__
|
|
}
|
|
|
|
warn()
|
|
{
|
|
>&2 echo "$(basename "$0"): error: $*";
|
|
}
|
|
|
|
err()
|
|
{
|
|
>&2 echo "$(basename "$0"): error: $*";
|
|
exit 1;
|
|
}
|
|
|
|
dry_run_echo()
|
|
{
|
|
if test "$dry_run" = "yes"; then
|
|
echo "$*";
|
|
fi;
|
|
}
|
|
|
|
dry_run_eval()
|
|
{
|
|
if test "$dry_run" = "yes"; then
|
|
echo " $*";
|
|
else
|
|
eval "$*";
|
|
fi;
|
|
}
|
|
|
|
|
|
help_unit_cmd()
|
|
{
|
|
cat <<__EOF__ ;
|
|
SYNOPSIS
|
|
$0 cmd [-h]
|
|
|
|
DESCRIPTION
|
|
Print the invocation line of running unitd(8) instances.
|
|
|
|
OPTIONS
|
|
-h, --help
|
|
Print this help.
|
|
|
|
__EOF__
|
|
}
|
|
|
|
|
|
unit_cmd()
|
|
{
|
|
while test $# -ge 1; do
|
|
case "$1" in
|
|
-h | --help)
|
|
help_unit_cmd;
|
|
exit 0;
|
|
;;
|
|
-*)
|
|
err "cmd: $1: Unknown option.";
|
|
;;
|
|
*)
|
|
err "cmd: $1: Unknown argument.";
|
|
;;
|
|
esac;
|
|
shift;
|
|
done;
|
|
|
|
unit_ps -t m \
|
|
| sed 's/.*\[\(.*\)].*/\1/';
|
|
}
|
|
|
|
|
|
help_unit_ctl()
|
|
{
|
|
cat <<__EOF__ ;
|
|
SYNOPSIS
|
|
$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 '$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
|
|
JSON configuration.
|
|
|
|
OPTIONS
|
|
-h, --help
|
|
Print this help.
|
|
|
|
-s, --sock SOCK
|
|
Use SOCK as the control API socket address. If not specified,
|
|
the script tries to find it. This value is used by subcommands.
|
|
|
|
The socket can be a tcp(7) socket or a unix(7) socket; in
|
|
the case of a unix(7) socket, it can exist locally or on
|
|
a remote machine, accessed through ssh(1). Accepted syntax
|
|
for SOCK:
|
|
|
|
unix:/path/to/control.sock
|
|
ssh://[user@]host[:port]/path/to/control.sock
|
|
[http[s]://]host[:port]
|
|
|
|
The last form is less secure than the first two; have a look:
|
|
<https://unit.nginx.org/howto/security/#secure-socket-and-stat>
|
|
|
|
ENVIRONMENT
|
|
Options take precedence over their equivalent environment variables;
|
|
if both are specified, the command-line option is used.
|
|
|
|
UNIT_CTL_SOCK
|
|
Equivalent to the option -s (--sock).
|
|
|
|
__EOF__
|
|
}
|
|
|
|
|
|
unit_ctl()
|
|
{
|
|
|
|
if test -v UNIT_CTL_SOCK; then
|
|
local sock="$UNIT_CTL_SOCK";
|
|
fi;
|
|
|
|
while test $# -ge 1; do
|
|
case "$1" in
|
|
-h | --help)
|
|
help_unit_ctl;
|
|
exit 0;
|
|
;;
|
|
-s | --sock)
|
|
if ! test $# -ge 2; then
|
|
err "ctl: $1: Missing argument.";
|
|
fi;
|
|
local sock="$2";
|
|
shift;
|
|
;;
|
|
-*)
|
|
err "ctl: $1: Unknown option.";
|
|
;;
|
|
*)
|
|
break;
|
|
;;
|
|
esac;
|
|
shift;
|
|
done;
|
|
|
|
if test ! $# -ge 1; then
|
|
err 'ctl: Missing subcommand.';
|
|
fi;
|
|
|
|
if ! test -v sock; then
|
|
local sock="$(unit_sock_find)";
|
|
fi;
|
|
|
|
if echo $sock | grep '^ssh://' >/dev/null; then
|
|
local remote="$(echo $sock | sed 's,\(ssh://[^/]*\).*,\1,')";
|
|
local sock="$(echo $sock | sed 's,ssh://[^/]*\(.*\),unix:\1,')";
|
|
fi;
|
|
|
|
case $1 in
|
|
edit)
|
|
shift;
|
|
unit_ctl_edit ${remote:+ ---r $remote} ---s "$sock" $@;
|
|
;;
|
|
http)
|
|
shift;
|
|
unit_ctl_http ${remote:+ ---r $remote} ---s "$sock" $@;
|
|
;;
|
|
insert)
|
|
shift;
|
|
unit_ctl_insert ${remote:+ ---r $remote} ---s "$sock" $@;
|
|
;;
|
|
*)
|
|
err "ctl: $1: Unknown argument.";
|
|
;;
|
|
esac;
|
|
}
|
|
|
|
|
|
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
|
|
$0 ctl [CTL-OPTS] http [-h] [-c CURLOPT] METHOD PATH
|
|
|
|
DESCRIPTION
|
|
Send an HTTP request to the unitd(8) control API socket.
|
|
|
|
The payload is read from standard input.
|
|
|
|
OPTIONS
|
|
-c, --curl CURLOPT
|
|
Pass CURLOPT as an option to curl. This script is implemented
|
|
in terms of curl(1), so it's useful to be able to tweak its
|
|
behavior. The option can be cumulatively used multiple times
|
|
(the result is also appended to UNIT_CTL_HTTP_CURLOPTS).
|
|
|
|
-h, --help
|
|
Print this help.
|
|
|
|
ENVIRONMENT
|
|
UNIT_CTL_HTTP_CURLOPTS
|
|
Equivalent to the option -c (--curl).
|
|
|
|
EXAMPLES
|
|
$0 ctl http -c --no-progress-meter GET /config >tmp;
|
|
|
|
SEE ALSO
|
|
<https://unit.nginx.org/controlapi/#api-manipulation>
|
|
|
|
__EOF__
|
|
}
|
|
|
|
|
|
unit_ctl_http()
|
|
{
|
|
local curl_options="${UNIT_CTL_HTTP_CURLOPTS:-}";
|
|
|
|
while test $# -ge 1; do
|
|
case "$1" in
|
|
-c | --curl)
|
|
if ! test $# -ge 2; then
|
|
err "ctl: http: $1: Missing argument.";
|
|
fi;
|
|
curl_options="$curl_options $2";
|
|
shift;
|
|
;;
|
|
-h | --help)
|
|
help_unit_ctl_http;
|
|
exit 0;
|
|
;;
|
|
---r | ----remote)
|
|
local remote="$2";
|
|
shift;
|
|
;;
|
|
---s | ----sock)
|
|
local sock="$2";
|
|
shift;
|
|
;;
|
|
-*)
|
|
err "ctl: http: $1: Unknown option.";
|
|
;;
|
|
*)
|
|
break;
|
|
;;
|
|
esac;
|
|
shift;
|
|
done;
|
|
|
|
if ! test $# -ge 1; then
|
|
err 'ctl: http: METHOD: Missing argument.';
|
|
fi;
|
|
local method="$1";
|
|
|
|
if ! test $# -ge 2; then
|
|
err 'ctl: http: PATH: Missing argument.';
|
|
fi;
|
|
local req_path="$2";
|
|
|
|
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;
|
|
|
|
curl $curl_options -X $method -d@- \
|
|
$(echo "$sock" | unit_sock_filter -c)${req_path} \
|
|
||:;
|
|
|
|
if test -v remote; then
|
|
ssh -S "$ssh_ctrl" -O exit "$remote" 2>/dev/null;
|
|
unlink "$local_sock";
|
|
fi;
|
|
}
|
|
|
|
|
|
help_unit_ctl_insert()
|
|
{
|
|
cat <<__EOF__ ;
|
|
SYNOPSIS
|
|
$0 ctl [CTL-OPTS] insert [-h] PATH INDEX
|
|
|
|
DESCRIPTION
|
|
Insert an element at the specified position (INDEX) into the JSON array
|
|
located at PATH in unitd(8) control API.
|
|
|
|
The new element is read from standard input.
|
|
|
|
OPTIONS
|
|
-h, --help
|
|
Print this help.
|
|
|
|
SEE ALSO
|
|
$0 ctl http -h;
|
|
|
|
__EOF__
|
|
}
|
|
|
|
|
|
unit_ctl_insert()
|
|
{
|
|
while test $# -ge 1; do
|
|
case "$1" in
|
|
-h | --help)
|
|
help_unit_ctl_insert;
|
|
exit 0;
|
|
;;
|
|
---r | ----remote)
|
|
local remote="$2";
|
|
shift;
|
|
;;
|
|
---s | ----sock)
|
|
local sock="$2";
|
|
shift;
|
|
;;
|
|
-*)
|
|
err "ctl: insert: $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 $# -ge 2; then
|
|
err 'ctl: insert: INDEX: Missing argument.';
|
|
fi;
|
|
local idx="$2";
|
|
|
|
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 old="$(mktemp ||:)";
|
|
|
|
unit_ctl_http ---s "$sock" -c --no-progress-meter GET "$req_path" \
|
|
</dev/null >"$old" \
|
|
||:;
|
|
|
|
unit_json_ins "$old" "$idx" \
|
|
| unit_ctl_http ---s "$sock" PUT "$req_path" \
|
|
||:;
|
|
|
|
if test -v remote; then
|
|
ssh -S "$ssh_ctrl" -O exit "$remote" 2>/dev/null;
|
|
unlink "$local_sock";
|
|
fi;
|
|
}
|
|
|
|
|
|
help_unit_ctl_welcome()
|
|
{
|
|
cat <<__EOF__ ;
|
|
SYNOPSIS
|
|
$0 welcome [-hn]
|
|
|
|
DESCRIPTION
|
|
This script tests an NGINX Unit installation by creating an initial
|
|
configuration and serving a welcome web page. Recommended for
|
|
first-time users.
|
|
|
|
OPTIONS
|
|
-h, --help
|
|
Print this help.
|
|
|
|
-n, --dry-run
|
|
Dry run. Print the commands to be run instead of actually
|
|
running them. Each command is preceded by a line explaining
|
|
what it does.
|
|
|
|
__EOF__
|
|
}
|
|
|
|
|
|
unit_ctl_welcome()
|
|
{
|
|
while test $# -ge 1; do
|
|
case "$1" in
|
|
-f | --force)
|
|
local force='yes';
|
|
;;
|
|
-h | --help)
|
|
help_unit_ctl_welcome;
|
|
exit 0;
|
|
;;
|
|
-n | --dry-run)
|
|
dry_run='yes';
|
|
;;
|
|
-*)
|
|
err "welcome: $1: Unknown option.";
|
|
;;
|
|
*)
|
|
err "welcome: $1: Unknown argument.";
|
|
;;
|
|
esac;
|
|
shift;
|
|
done;
|
|
|
|
command -v curl >/dev/null \
|
|
|| err 'welcome: curl(1) not found in PATH. It must be installed to run this script.';
|
|
|
|
www='/srv/www/unit/index.html';
|
|
if test -e "$www" && ! test -v force || ! test -w /srv; then
|
|
www="$HOME/srv/www/unit/index.html";
|
|
fi;
|
|
if test -e "$www" && ! test -v force; then
|
|
www="$(mktemp)";
|
|
mv "$www" "$www.html";
|
|
www="$www.html"
|
|
fi;
|
|
|
|
unit_ps -t m \
|
|
| wc -l \
|
|
| read -r nprocs \
|
|
||:
|
|
|
|
if test 0 -eq "$nprocs"; then
|
|
warn "welcome: NGINX Unit isn't running.";
|
|
warn 'For help with starting NGINX Unit, see:';
|
|
err " <https://unit.nginx.org/installation/#startup-and-shutdown>";
|
|
elif test 1 -ne "$nprocs"; then
|
|
err 'welcome: Only one NGINX Unit instance should be running.';
|
|
fi;
|
|
|
|
local sock="$(unit_sock_find)";
|
|
local curl_opt="$(unit_sock_find | unit_sock_filter -c)";
|
|
|
|
curl $curl_opt/ >/dev/null 2>&1 \
|
|
|| err "welcome: Can't reach the control API socket.";
|
|
|
|
if ! test -v force; then
|
|
unit_cmd \
|
|
| read -r cmd;
|
|
|
|
# Check unitd is not configured already.
|
|
echo "$cmd" \
|
|
| if grep '\--statedir' >/dev/null; then
|
|
echo "$cmd" \
|
|
| sed 's/ --/\n--/g' \
|
|
| grep '\--statedir' \
|
|
| cut -d' ' -f2;
|
|
else
|
|
$cmd --help \
|
|
| sed -n '/\--statedir/,+1p' \
|
|
| grep 'default:' \
|
|
| sed 's/ *default: "\(.*\)"/\1/';
|
|
fi \
|
|
| sed 's,$,/conf.json,' \
|
|
| read -r conffile \
|
|
||:;
|
|
|
|
if test -e $conffile; then
|
|
if ! unit_ctl_http ---s "$sock" 'GET' '/config' </dev/null 2>/dev/null | grep -q '^{}.\?$'; # The '.\?' is for the possible carriage return.
|
|
then
|
|
warn 'welcome: NGINX Unit is already configured. To overwrite';
|
|
err 'its current configuration, run the script again with --force.';
|
|
fi;
|
|
fi;
|
|
fi;
|
|
|
|
(
|
|
unit_freeport \
|
|
|| err "welcome: Can't find an available port.";
|
|
) \
|
|
| read -r port;
|
|
|
|
dry_run_echo 'Create a file to serve:';
|
|
dry_run_eval "mkdir -p $(dirname $www);";
|
|
dry_run_eval "tee '$www' >/dev/null"' <<__EOF__;
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<title>Welcome to NGINX Unit</title>
|
|
<style type="text/css">
|
|
body { background: white; color: black; font-family: sans-serif; margin: 2em; line-height: 1.5; }
|
|
h1,h2 { color: #00974d; }
|
|
li { margin-bottom: 0.5em; }
|
|
pre { background-color: beige; padding: 0.4em; }
|
|
hr { margin-top: 2em; border: 1px solid #00974d; }
|
|
.indent { margin-left: 1.5em; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<h1>Welcome to NGINX Unit</h1>
|
|
<p>Congratulations! NGINX Unit is installed and running.</p>
|
|
<h3>Useful Links</h3>
|
|
<ul>
|
|
<li><b><a href="https://unit.nginx.org/configuration/?referer=welcome">https://unit.nginx.org/configuration/</a></b><br>
|
|
To get started with Unit, see the <em>Configuration</em> docs, starting with
|
|
the <em>Quick Start</em> guide.</li>
|
|
<li><b><a href="https://github.com/nginx/unit">https://github.com/nginx/unit</a></b><br>
|
|
See our GitHub repo to browse the code, contribute, or seek help from the
|
|
<a href="https://github.com/nginx/unit#community">community</a>.</li>
|
|
</ul>
|
|
|
|
<h2>Next steps</h2>
|
|
|
|
<h3>Check Current Configuration</h3>
|
|
<div class="indent">
|
|
<p>Unit'"'"'s control API is currently listening for configuration changes
|
|
on the '"$(unit_sock_find | grep -q '^unix:' && echo '<a href="https://en.wikipedia.org/wiki/Unix_domain_socket">Unix socket</a>' || echo 'socket')"' at
|
|
<b>'"$(unit_sock_find)"'</b><br>
|
|
To see the current configuration:</p>
|
|
<pre>'"${SUDO_USER:+sudo }"'curl '"$curl_opt"'/config</pre>
|
|
</div>
|
|
|
|
<h3>Change Listener Port</h3>
|
|
<div class="indent">
|
|
<p>This page is served over a random TCP high port. To choose the default HTTP port (80),
|
|
replace the <b>"listeners"</b> object:</p>
|
|
<pre>echo '"'"'{"*:80": {"pass": "routes"}}'"'"' | '"${SUDO_USER:+sudo }"'curl -X PUT -d@- '"$curl_opt"'/config/listeners</pre>
|
|
Then remove the port number from the address bar and reload the page.
|
|
</div>
|
|
|
|
<hr>
|
|
<p><a href="https://unit.nginx.org/?referer=welcome">NGINX Unit — the universal web app server</a><br>
|
|
NGINX, Inc. © 2023</p>
|
|
</body>
|
|
</html>
|
|
__EOF__';
|
|
dry_run_echo;
|
|
dry_run_echo 'Give it appropriate permissions:';
|
|
dry_run_eval "chmod 644 '$www';";
|
|
dry_run_echo;
|
|
|
|
dry_run_echo 'Configure unitd:'
|
|
dry_run_eval "cat <<__EOF__ \\
|
|
| sed 's/8080/$port/' \\
|
|
| curl -X PUT -d@- $curl_opt/config;
|
|
{
|
|
\"listeners\": {
|
|
\"*:8080\": {
|
|
\"pass\": \"routes\"
|
|
}
|
|
},
|
|
\"routes\": [{
|
|
\"action\": {
|
|
\"share\": \"$www\"
|
|
}
|
|
}]
|
|
}
|
|
__EOF__";
|
|
|
|
dry_run_echo;
|
|
|
|
echo;
|
|
echo 'You may want to try the following commands now:';
|
|
echo;
|
|
echo 'Check out current unitd configuration:';
|
|
echo " ${SUDO_USER:+sudo} curl $curl_opt/config";
|
|
echo;
|
|
echo 'Browse the welcome page:';
|
|
echo " curl http://localhost:$port/";
|
|
}
|
|
|
|
|
|
help_unit_freeport()
|
|
{
|
|
cat <<__EOF__ ;
|
|
SYNOPSIS
|
|
$0 freeport [-h]
|
|
|
|
DESCRIPTION
|
|
Print an available TCP port.
|
|
|
|
OPTIONS
|
|
-h, --help
|
|
Print this help.
|
|
|
|
__EOF__
|
|
}
|
|
|
|
|
|
unit_freeport()
|
|
{
|
|
while test $# -ge 1; do
|
|
case "$1" in
|
|
-h | --help)
|
|
help_unit_freeport;
|
|
exit 0;
|
|
;;
|
|
-*)
|
|
err "freeport: $1: Unknown option.";
|
|
;;
|
|
*)
|
|
err "freeport: $1: Unknown argument.";
|
|
;;
|
|
esac;
|
|
shift;
|
|
done;
|
|
|
|
freeport="$(mktemp -t freeport-XXXXXX)";
|
|
|
|
cat <<__EOF__ \
|
|
| cc -x c -o $freeport -;
|
|
#include <netinet/in.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <strings.h>
|
|
#include <sys/socket.h>
|
|
#include <unistd.h>
|
|
|
|
|
|
int32_t get_free_port(void);
|
|
|
|
|
|
int
|
|
main(void)
|
|
{
|
|
int32_t port;
|
|
|
|
port = get_free_port();
|
|
if (port == -1)
|
|
exit(EXIT_FAILURE);
|
|
|
|
printf("%d\n", port);
|
|
exit(EXIT_SUCCESS);
|
|
}
|
|
|
|
|
|
int32_t
|
|
get_free_port(void)
|
|
{
|
|
int sfd;
|
|
int32_t port;
|
|
socklen_t len;
|
|
struct sockaddr_in addr;
|
|
|
|
port = -1;
|
|
|
|
sfd = socket(PF_INET, SOCK_STREAM, 0);
|
|
if (sfd == -1) {
|
|
perror("socket()");
|
|
return -1;
|
|
}
|
|
|
|
bzero(&addr, sizeof(addr));
|
|
addr.sin_family = AF_INET;
|
|
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
|
addr.sin_port = htons(0); // random port
|
|
|
|
len = sizeof(addr);
|
|
if (bind(sfd, (struct sockaddr *) &addr, len)) {
|
|
perror("bind()");
|
|
goto fail;
|
|
}
|
|
|
|
if (getsockname(sfd, (struct sockaddr *) &addr, &len)) {
|
|
perror("getsockname()");
|
|
goto fail;
|
|
}
|
|
|
|
port = ntohs(addr.sin_port);
|
|
|
|
fail:
|
|
close(sfd);
|
|
return port;
|
|
}
|
|
__EOF__
|
|
|
|
$freeport;
|
|
}
|
|
|
|
|
|
help_unit_json_ins()
|
|
{
|
|
cat <<__EOF__ ;
|
|
SYNOPSIS
|
|
$0 json-ins [-hn] JSON INDEX
|
|
|
|
ARGUMENTS
|
|
JSON Path to a JSON file containing a top-level array.
|
|
|
|
INDEX Position in the array to insert the element at.
|
|
|
|
DESCRIPTION
|
|
Insert a JSON element read from standard input into a JSON array read
|
|
from a file at a given INDEX.
|
|
|
|
The resulting array is printed to standard output.
|
|
|
|
OPTIONS
|
|
-h, --help
|
|
Print this help.
|
|
|
|
-n, --dry-run
|
|
Dry run. Print the command to be run instead of actually
|
|
running it.
|
|
|
|
__EOF__
|
|
}
|
|
|
|
|
|
unit_json_ins()
|
|
{
|
|
while test $# -ge 1; do
|
|
case "$1" in
|
|
-h | --help)
|
|
help_unit_json_ins;
|
|
exit 0;
|
|
;;
|
|
-n | --dry-run)
|
|
dry_run='yes';
|
|
;;
|
|
-*)
|
|
err "json-ins: $1: Unknown option.";
|
|
;;
|
|
*)
|
|
break;
|
|
;;
|
|
esac;
|
|
shift;
|
|
done;
|
|
|
|
if ! test $# -ge 1; then
|
|
err 'json-ins: JSON: Missing argument.';
|
|
fi;
|
|
local arr=$1;
|
|
|
|
if ! test $# -ge 2; then
|
|
err 'json-ins: INDEX: Missing argument.';
|
|
fi;
|
|
local idx=$2;
|
|
|
|
dry_run_eval "(
|
|
jq '.[0:$idx]' <'$arr';
|
|
echo '[';
|
|
jq .;
|
|
echo ']';
|
|
jq '.[$idx:]' <'$arr';
|
|
) \\
|
|
| sed '/^\[]$/d' \\
|
|
| sed '/^]$/{N;s/^]\n\[$/,/}' \\
|
|
| jq .;"
|
|
}
|
|
|
|
|
|
help_unit_os_probe()
|
|
{
|
|
cat <<__EOF__ ;
|
|
SYNOPSIS
|
|
$0 os-probe [-h]
|
|
|
|
DESCRIPTION
|
|
This script probes the OS and prints three fields, delimited by ':';
|
|
the first is the package manager, the second is the OS name, the third
|
|
is the OS version.
|
|
|
|
OPTIONS
|
|
-h, --help
|
|
Print this help.
|
|
|
|
__EOF__
|
|
}
|
|
|
|
|
|
unit_os_probe()
|
|
{
|
|
while test $# -ge 1; do
|
|
case "$1" in
|
|
-h | --help)
|
|
help_unit_os_probe;
|
|
exit 0;
|
|
;;
|
|
-*)
|
|
err "os-probe: $1: Unknown option.";
|
|
;;
|
|
*)
|
|
err "os-probe: $1: Unknown argument.";
|
|
;;
|
|
esac;
|
|
shift;
|
|
done;
|
|
|
|
local os=$(uname | tr '[:upper:]' '[:lower:]')
|
|
|
|
if [ "$os" != 'linux' ] && [ "$os" != 'freebsd' ]; then
|
|
err "os-probe: The OS isn't Linux or FreeBSD; can't proceed."
|
|
fi
|
|
|
|
if [ "$os" = 'linux' ]; then
|
|
if command -v apt-get >/dev/null; then
|
|
local pkgMngr='apt';
|
|
elif command -v dnf >/dev/null; then
|
|
local pkgMngr='dnf';
|
|
elif command -v yum >/dev/null; then
|
|
local pkgMngr='yum';
|
|
else
|
|
local pkgMngr='';
|
|
fi;
|
|
|
|
local osRelease='/etc/os-release';
|
|
|
|
if [ -f "$osRelease" ]; then
|
|
# The value for the ID and VERSION_ID may or may not be in quotes
|
|
local osName=$(grep "^ID=" "$osRelease" | sed s/\"//g | awk -F= '{ print $2 }' ||:)
|
|
local osVersion=$(grep '^VERSION_ID=' "$osRelease" | sed s/\"//g | awk -F= '{ print $2 }' || lsb_release -cs)
|
|
else
|
|
err "os-probe: Unable to determine OS and version, or the OS isn't supported."
|
|
fi
|
|
else
|
|
local pkgMngr='pkg';
|
|
local osName=$os
|
|
local osVersion=$(uname -rs | awk -F '[ -]' '{print $2}' ||:)
|
|
if [ -z "$osVersion" ]; then
|
|
err 'os-probe: Unable to get the FreeBSD version.'
|
|
fi
|
|
fi
|
|
|
|
osName=$(echo "$osName" | tr '[:upper:]' '[:lower:]')
|
|
echo "$pkgMngr:$osName:$osVersion"
|
|
}
|
|
|
|
|
|
help_unit_ps()
|
|
{
|
|
cat <<__EOF__ ;
|
|
SYNOPSIS
|
|
$0 ps [-h] [-t TYPE]
|
|
|
|
DESCRIPTION
|
|
List unitd(8) processes.
|
|
|
|
OPTIONS
|
|
-h, --help
|
|
Print this help.
|
|
|
|
-t, --type TYPE
|
|
List only processes of type TYPE. The available types are:
|
|
|
|
- controller (c)
|
|
- main (m)
|
|
- router (r)
|
|
|
|
__EOF__
|
|
}
|
|
|
|
|
|
unit_ps()
|
|
{
|
|
while test $# -ge 1; do
|
|
case "$1" in
|
|
-h | --help)
|
|
help_unit_ps;
|
|
exit 0;
|
|
;;
|
|
-t | --type)
|
|
if ! test $# -ge 2; then
|
|
err "ps: $1: Missing argument.";
|
|
fi;
|
|
local type=;
|
|
case "$2" in
|
|
c | controller)
|
|
local type_c='c';
|
|
;;
|
|
m | main)
|
|
local type_m='m';
|
|
;;
|
|
r | router)
|
|
local type_r='r';
|
|
;;
|
|
esac;
|
|
shift;
|
|
;;
|
|
-*)
|
|
err "ps: $1: Unknown option.";
|
|
;;
|
|
*)
|
|
err "ps: $1: Unknown argument.";
|
|
;;
|
|
esac;
|
|
shift;
|
|
done;
|
|
|
|
ps awwx \
|
|
| if test -v type; then
|
|
grep ${type_c:+-e 'unit: controller'} \
|
|
${type_m:+-e 'unit: main'} \
|
|
${type_r:+-e 'unit: router'};
|
|
else
|
|
grep 'unit: ';
|
|
fi \
|
|
| grep -v grep \
|
|
||:
|
|
}
|
|
|
|
|
|
help_unit_repo_config()
|
|
{
|
|
cat <<__EOF__ ;
|
|
SYNOPSIS
|
|
$0 repo-config [-hn] [PKG-MANAGER OS-NAME OS-VERSION]
|
|
|
|
DESCRIPTION
|
|
This script configures the NGINX Unit repository for the system
|
|
package manager.
|
|
|
|
The script automatically detects the OS and proceeds accordingly.
|
|
However, if this automatic selection fails, you may specify the
|
|
package manager and the OS name and version.
|
|
|
|
ARGUMENTS
|
|
PKG-MANAGER
|
|
Supported: 'apt', 'dnf', and 'yum'.
|
|
|
|
OS-NAME
|
|
Supported: 'debian', 'ubuntu', 'fedora', 'rhel', and 'amzn2'.
|
|
|
|
OS-VERSION
|
|
For most distributions, this should be a numeric value; for
|
|
Debian derivatives, use the codename instead.
|
|
|
|
OPTIONS
|
|
-h, --help
|
|
Print this help.
|
|
|
|
-n, --dry-run
|
|
Dry run. Print the commands to be run instead of actually
|
|
running them. Each command is preceded by a line explaining
|
|
what it does.
|
|
|
|
EXAMPLES
|
|
$ $(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__
|
|
}
|
|
|
|
|
|
unit_repo_config()
|
|
{
|
|
installAPT ()
|
|
{
|
|
local os_name="$2";
|
|
|
|
dry_run_echo "Install on $os_name";
|
|
dry_run_echo;
|
|
dry_run_eval 'curl --output /usr/share/keyrings/nginx-keyring.gpg https://unit.nginx.org/keys/nginx-keyring.gpg;';
|
|
dry_run_echo;
|
|
dry_run_eval 'apt-get install -y apt-transport-https lsb-release ca-certificates;';
|
|
|
|
if test $# -ge 3; then
|
|
local os_version="$3";
|
|
else
|
|
local os_version='$(lsb_release -cs)';
|
|
fi;
|
|
|
|
dry_run_echo;
|
|
dry_run_eval "printf 'deb [signed-by=/usr/share/keyrings/nginx-keyring.gpg] https://packages.nginx.org/unit/$os_name/ %s unit\n' \"$os_version\" | tee /etc/apt/sources.list.d/unit.list;";
|
|
dry_run_eval "printf 'deb-src [signed-by=/usr/share/keyrings/nginx-keyring.gpg] https://packages.nginx.org/unit/$os_name/ %s unit\n' \"$os_version\" | tee -a /etc/apt/sources.list.d/unit.list;";
|
|
dry_run_echo;
|
|
dry_run_eval 'apt-get update;';
|
|
}
|
|
|
|
installYumDnf ()
|
|
{
|
|
local pkg_mngr="$1";
|
|
local os_name="$2";
|
|
|
|
if test $# -ge 3; then
|
|
local os_version="$3";
|
|
else
|
|
local os_version='\$releasever';
|
|
fi;
|
|
|
|
dry_run_echo "Install on $os_name";
|
|
dry_run_echo;
|
|
|
|
dry_run_eval "cat >/etc/yum.repos.d/unit.repo <<__EOF__
|
|
[unit]
|
|
name=unit repo
|
|
baseurl=https://packages.nginx.org/unit/$os_name/$os_version/\\\$basearch/
|
|
gpgcheck=0
|
|
enabled=1
|
|
__EOF__";
|
|
|
|
dry_run_echo;
|
|
dry_run_eval "$pkg_mngr makecache;";
|
|
}
|
|
|
|
while test $# -ge 1; do
|
|
case "$1" in
|
|
-h | --help)
|
|
help_unit_repo_config;
|
|
exit 0;
|
|
;;
|
|
-n | --dry-run)
|
|
dry_run='yes';
|
|
;;
|
|
-*)
|
|
err "repo-config: $1: Unknown option.";
|
|
;;
|
|
*)
|
|
break;
|
|
;;
|
|
esac;
|
|
shift;
|
|
done;
|
|
|
|
if test $# -ge 1; then
|
|
local pkg_mngr="$1";
|
|
|
|
if ! test $# -ge 2; then
|
|
err "repo-config: OS-NAME: Missing argument.";
|
|
fi;
|
|
local os_name="$2";
|
|
|
|
if ! test $# -ge 3; then
|
|
err "repo-config: OS-VERSION: Missing argument.";
|
|
fi;
|
|
local os_version="$3";
|
|
fi;
|
|
|
|
command -v curl >/dev/null \
|
|
|| err 'repo-config: curl(1) not found in PATH. It must be installed to run this script.';
|
|
|
|
echo 'This script sets up the NGINX Unit repository';
|
|
|
|
if ! test $# -ge 3; then
|
|
local os_pkg_name_version=$(unit_os_probe || warn "On macOS, try 'brew install nginx/unit/unit'.")
|
|
local pkg_mngr=$(echo "$os_pkg_name_version" | awk -F: '{print $1}')
|
|
local os_name=$(echo "$os_pkg_name_version" | awk -F: '{print $2}')
|
|
local os_version=$(echo "$os_pkg_name_version" | awk -F: '{print $3}')
|
|
fi;
|
|
|
|
# Call the appropriate installation function
|
|
case "$pkg_mngr" in
|
|
apt)
|
|
case "$os_name" in
|
|
debian | ubuntu)
|
|
installAPT "$pkg_mngr" "$os_name" ${3:+$os_version};
|
|
;;
|
|
*)
|
|
err "repo-config: $os_name: The OS isn't supported.";
|
|
;;
|
|
esac
|
|
;;
|
|
yum | dnf)
|
|
case "$os_name" in
|
|
rhel | amzn | fedora)
|
|
installYumDnf "$pkg_mngr" "$os_name" "$os_version" ${3:+ovr};
|
|
;;
|
|
*)
|
|
err "repo-config: $os_name: The OS isn't supported.";
|
|
;;
|
|
esac;
|
|
;;
|
|
*)
|
|
err "repo-config: $pkg_mngr: The package manager isn't supported.";
|
|
;;
|
|
esac;
|
|
|
|
echo
|
|
echo 'All done; the NGINX Unit repository is set up.';
|
|
echo "Configured with '$pkg_mngr' on '$os_name' '$os_version'.";
|
|
echo 'Further steps: <https://unit.nginx.org/installation/#official-packages>'
|
|
}
|
|
|
|
|
|
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
|
|
$0 sock [-h] SUBCOMMAND [ARGS]
|
|
|
|
Subcommands
|
|
├── filter [-ch]
|
|
└── find [-h]
|
|
|
|
DESCRIPTION
|
|
Print the control API socket address of running unitd(8)
|
|
instances.
|
|
|
|
Run '$0 sock SUBCOMMAND -h' for more information on a
|
|
subcommand.
|
|
|
|
SUBCOMMANDS
|
|
filter Filter the output of the 'find' subcommand and transform it
|
|
to something suitable for running other commands, such as
|
|
curl(1) or ssh(1).
|
|
|
|
find Find and print the control API socket address of running
|
|
unitd(8) instances.
|
|
|
|
OPTIONS
|
|
-h, --help
|
|
Print this help.
|
|
|
|
__EOF__
|
|
}
|
|
|
|
|
|
unit_sock()
|
|
{
|
|
while test $# -ge 1; do
|
|
case "$1" in
|
|
-h | --help)
|
|
help_unit_sock;
|
|
exit 0;
|
|
;;
|
|
-*)
|
|
err "sock: $1: Unknown option.";
|
|
;;
|
|
*)
|
|
break;
|
|
;;
|
|
esac;
|
|
shift;
|
|
done;
|
|
|
|
if ! test $# -ge 1; then
|
|
err 'sock: Missing subcommand.';
|
|
fi;
|
|
|
|
case $1 in
|
|
filter)
|
|
shift;
|
|
unit_sock_filter $@;
|
|
;;
|
|
find)
|
|
shift;
|
|
unit_sock_find $@;
|
|
;;
|
|
*)
|
|
err "sock: $1: Unknown subcommand.";
|
|
;;
|
|
esac;
|
|
}
|
|
|
|
|
|
help_unit_sock_filter()
|
|
{
|
|
cat <<__EOF__ ;
|
|
SYNOPSIS
|
|
$0 sock filter [-chs]
|
|
|
|
DESCRIPTION
|
|
Filter the output of the 'sock find' command and transform it to
|
|
something suitable for running other commands, such as
|
|
curl(1) or ssh(1).
|
|
|
|
OPTIONS
|
|
-c, --curl
|
|
Print an argument suitable for curl(1).
|
|
|
|
-h, --help
|
|
Print this help.
|
|
|
|
-s, --ssh
|
|
Print a socket address suitable for use in an ssh(1) tunnel.
|
|
|
|
__EOF__
|
|
}
|
|
|
|
|
|
unit_sock_filter()
|
|
{
|
|
while test $# -ge 1; do
|
|
case "$1" in
|
|
-c | --curl)
|
|
if test -v ssh_flag; then
|
|
err "sock: filter: $1: Missing argument.";
|
|
fi;
|
|
local curl_flag='yes';
|
|
;;
|
|
-h | --help)
|
|
help_unit_sock_filter;
|
|
exit 0;
|
|
;;
|
|
-s | --ssh)
|
|
if test -v curl_flag; then
|
|
err "sock: filter: $1: Missing argument.";
|
|
fi;
|
|
local ssh_flag='yes';
|
|
;;
|
|
-*)
|
|
err "sock: filter: $1: Unknown option.";
|
|
;;
|
|
*)
|
|
err "sock: filter: $1: Unknown argument.";
|
|
;;
|
|
esac;
|
|
shift;
|
|
done;
|
|
|
|
while read -r control; do
|
|
|
|
if test -v curl_flag; then
|
|
if echo "$control" | grep '^unix:' >/dev/null; then
|
|
unix_socket="$(echo "$control" | sed 's/unix:/--unix-socket /')";
|
|
host='http://localhost';
|
|
else
|
|
unix_socket='';
|
|
host="$control";
|
|
fi;
|
|
|
|
echo "$unix_socket $host";
|
|
|
|
elif test -v ssh_flag; then
|
|
echo "$control" \
|
|
| sed -E 's,^(unix:|http://|https://),,';
|
|
|
|
else
|
|
echo "$control";
|
|
fi;
|
|
done;
|
|
}
|
|
|
|
|
|
help_unit_sock_find()
|
|
{
|
|
cat <<__EOF__ ;
|
|
SYNOPSIS
|
|
$0 sock find [-h]
|
|
|
|
DESCRIPTION
|
|
Find and print the control API socket address of running
|
|
unitd(8) instances.
|
|
|
|
OPTIONS
|
|
-h, --help
|
|
Print this help.
|
|
|
|
__EOF__
|
|
}
|
|
|
|
|
|
unit_sock_find()
|
|
{
|
|
while test $# -ge 1; do
|
|
case "$1" in
|
|
-h | --help)
|
|
help_unit_sock_find;
|
|
exit 0;
|
|
;;
|
|
-*)
|
|
err "sock: find: $1: Unknown option.";
|
|
;;
|
|
*)
|
|
err "sock: find: $1: Unknown argument.";
|
|
;;
|
|
esac;
|
|
shift;
|
|
done;
|
|
|
|
unit_cmd \
|
|
| while read -r cmd; do
|
|
if echo "$cmd" | grep '\--control' >/dev/null; then
|
|
echo "$cmd" \
|
|
| sed 's/ --/\n--/g' \
|
|
| grep '\--control' \
|
|
| cut -d' ' -f2;
|
|
else
|
|
if ! command -v $cmd >/dev/null; then
|
|
local cmd='unitd';
|
|
fi;
|
|
$cmd --help \
|
|
| sed -n '/\--control/,+1p' \
|
|
| grep 'default:' \
|
|
| sed 's/ *default: "\(.*\)"/\1/';
|
|
fi;
|
|
done;
|
|
}
|
|
|
|
|
|
while test $# -ge 1; do
|
|
case "$1" in
|
|
-h | --help)
|
|
help_unit;
|
|
exit 0;
|
|
;;
|
|
--help-more)
|
|
help_more_unit;
|
|
exit 0;
|
|
;;
|
|
-*)
|
|
err "$1: Unknown option.";
|
|
;;
|
|
*)
|
|
break;
|
|
;;
|
|
esac;
|
|
shift;
|
|
done;
|
|
|
|
if ! test $# -ge 1; then
|
|
err "Missing command.";
|
|
fi;
|
|
|
|
case $1 in
|
|
cmd)
|
|
shift;
|
|
unit_cmd $@;
|
|
;;
|
|
ctl)
|
|
shift;
|
|
unit_ctl $@;
|
|
;;
|
|
freeport)
|
|
shift;
|
|
unit_freeport $@;
|
|
;;
|
|
json-ins)
|
|
shift;
|
|
unit_json_ins $@;
|
|
;;
|
|
os-probe)
|
|
shift;
|
|
unit_os_probe $@;
|
|
;;
|
|
ps)
|
|
shift;
|
|
unit_ps $@;
|
|
;;
|
|
repo-config)
|
|
shift;
|
|
unit_repo_config $@;
|
|
;;
|
|
restart)
|
|
shift;
|
|
unit_restart $@;
|
|
;;
|
|
sock)
|
|
shift;
|
|
unit_sock $@;
|
|
;;
|
|
welcome)
|
|
shift;
|
|
unit_ctl_welcome $@;
|
|
;;
|
|
*)
|
|
err "$1: Unknown command.";
|
|
;;
|
|
esac;
|