This allows one to simply run `./configure` and expect it to
produce sane defaults for an install.
Previously, without specifying `--prefix=...`, `make install`
would simply fail, recommending to set `--prefix` or `DESTDIR`,
but that recommendation was incomplete at best, since it didn't
set many of the subdirs needed for a good organization.
Setting `DESTDIR` was even worse, since that shouldn't even affect
an installation (it is required to be transparent to the
installation).
/usr/local is the historic Unix standard path to use for
installations from source made manually by the admin of the
system. Some package managers (Homebrew, I'm looking specifically
at you) have abused that path to install their things, but 1) it's
not our fault that someone else incorrectly abuses that path (and
they seem to be fixing it for newer archs; e.g., they started
using /opt/homebrew for Apple Silicon), 2) there's no better path
than /usr/local, 3) we still allow changing it for systems where
this might not be the desired path (MacOS Intel with hombrew), and
4) it's _the standard_.
See a related conversation with Ingo (OpenBSD maintainer):
On 7/27/22 16:16, Ingo Schwarze wrote:
> Hi Alejandro,
[...]
>
> Alejandro Colomar wrote on Sun, Jul 24, 2022 at 07:07:18PM +0200:
>> On 7/24/22 16:57, Ingo Schwarze wrote:
>>> Alejandro Colomar wrote on Sun, Jul 24, 2022 at 01:20:46PM +0200:
>
>>>> /usr/local is for sysadmins to build from source;
>
>>> Doing that is *very* strongly discouraged on OpenBSD.
>
>> I guess that's why the directory was reused in the BSDs to install ports
>> (probably ports were installed by the sysadmin there, and by extension,
>> ports are now always installed there, but that's just a guess).
>
> Maybe. In any case, the practice of using /usr/local for packages
> created from ports is significantly older than the recommendation
> to refrain from using upstream "make install" outside the ports
> framework.
>
> * The FreeBSD ports framework was started by Jordan Hubbard in 1993.
> * The ports framework was ported from FreeBSD to OpenBSD
> by Niklas Hallqvist in 1996.
> * NetBSD pkgsrc was forked from FreeBSD ports by Alistair G. Crooks
> and Hubert Feyrer in 1997.
>
> I failed to quickly find Jordan's original version, but rev. 1.1
> of /usr/ports/infrastructure/mk/bsd.port.mk in OpenBSD (dated Jun 3
> 22:47:10 1996 UTC) already said
>
> LOCALBASE ?= /usr/local
> PREFIX ?= ${LOCALBASE}
>
[...]
>> I had a discussion in NGINX Unit about it, and
>> the decission for now has been: "support prefix=/usr/local for default
>> manual installation through the Makefile, and let BSD users adjust to
>> their preferred path".
>
> That's an *excellent* solution for the task, thanks for doing it
> the right way. By setting PREFIX=/usr/local by default in the
> upstream Makefile, you are minimizing the work for *BSD porters.
>
> The BSD ports frameworks will typically run the upstreak "make install"
> with the variable DESTDIR set to a custom value, for example
>
> DESTDIR=/usr/ports/pobj/groff-1.23.0/fake-amd64
>
> so if the upstream Makefile sets PREFIX=/usr/local ,
> that's perfect, everything gets installed to the right place
> without an intervention by the person doing the porting.
>
> Of course, if the upstream Makefile would use some other PREFIX,
> that would not be a huge obstacle. All we have to do in that case
> is pass the option --prefix=/usr/local to the ./configure script,
> or something equivalent if the software isn't using GNU configure.
>
>> We were concerned that we might get collisions
>> with the BSD port also installing in /usr/local, but that's the least
>> evil (and considering BSD users don't typically run `make install`, it's
>> not so bad).
>
> It's not bad at all. It's perfect.
>
> Of course, if a user wants to install *without* the ports framework,
> they have to provide their own --prefix. But that's not an issue
> because it is easy to do, and installing without a port is discouraged
> anyway.
===
Directory variables should never contain a trailing slash (I've
learned that the hard way, where some things would break
unexpectedly). Especially, make(1) is likely to have problems
when things have double slashes or a trailing slash, since it
treats filenames as text strings. I've removed the trailing slash
from the prefix, and added it to the derivate variables just after
the prefix. pkg-config(1) also expects directory variables to have
no trailing slash.
===
I also removed the code that would set variables as depending on
the prefix if they didn't start with a slash, because that is a
rather non-obvious behavior, and things should not always depend
on prefix, but other dirs such as $(runstatedir), so if we keep
a similar behavior it would be very unreliable. Better keep
variables intact if set, or use the default if unset.
===
Print the real defaults for ./configure --help, rather than the actual
values.
===
I used a subdirectory under the standard /var/lib for NXT_STATE,
instead of a homemade "state" dir that does the same thing.
===
Modified the Makefile to create some dirs that weren't being
created, and also remove those that weren't being removed in
uninstall, probably because someone forgot to add them.
===
Add new options for setting the new variables, and rename some to be
consistent with the standard names. Keep the old ones at configuration
time for compatibility, but mark them as deprecated. Don't keep the old
ones at exec time.
===
A summary of the default config is:
Unit configuration summary:
bin directory: ............. "/usr/local/bin"
sbin directory: ............ "/usr/local/sbin"
lib directory: ............. "/usr/local/lib"
include directory: ......... "/usr/local/include"
man pages directory: ....... "/usr/local/share/man"
modules directory: ......... "/usr/local/lib/unit/modules"
state directory: ........... "/usr/local/var/lib/unit"
tmp directory: ............. "/tmp"
pid file: .................. "/usr/local/var/run/unit/unit.pid"
log file: .................. "/usr/local/var/log/unit/unit.log"
control API socket: ........ "unix:/usr/local/var/run/unit/control.unit.sock"
Link: <https://www.gnu.org/prep/standards/html_node/Directory-Variables.html>
Link: <https://refspecs.linuxfoundation.org/FHS_3.0/fhs/index.html>
Reviewed-by: Artem Konev <a.konev@f5.com>
Reviewed-by: Andrew Clayton <a.clayton@nginx.com>
Tested-by: Andrew Clayton <a.clayton@nginx.com>
Reviewed-by: Konstantin Pavlov <thresh@nginx.com>
Signed-off-by: Alejandro Colomar <alx@nginx.com>
1498 lines
35 KiB
Bash
Executable File
1498 lines
35 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
|
|
|
|
program_name="$0";
|
|
prog_name="$(basename $program_name)";
|
|
|
|
dry_run='no';
|
|
|
|
help_unit()
|
|
{
|
|
cat <<__EOF__ ;
|
|
SYNOPSIS
|
|
$program_name [-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 '$program_name 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
|
|
$program_name [-h] COMMAND [ARGS]
|
|
|
|
Subcommands
|
|
+-- cmd [-h]
|
|
+-- ctl [-h] [-s SOCK] SUBCOMMAND [ARGS]
|
|
| +-- 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]
|
|
+-- 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 '$program_name 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 "$prog_name: error: $*";
|
|
}
|
|
|
|
err()
|
|
{
|
|
>&2 echo "$prog_name: 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
|
|
$program_name 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
|
|
$program_name ctl [-h] [-s SOCK] SUBCOMMAND [ARGS]
|
|
|
|
Subcommands
|
|
+-- 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
|
|
subcommand.
|
|
|
|
SUBCOMMANDS
|
|
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 && 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
|
|
http)
|
|
shift;
|
|
unit_ctl_http ${remote:+ ---r $remote} ${sock:+ ---s $sock} $@;
|
|
;;
|
|
insert)
|
|
shift;
|
|
unit_ctl_insert ${remote:+ ---r $remote} ${sock:+ ---s $sock} $@;
|
|
;;
|
|
*)
|
|
err "ctl: $1: Unknown argument.";
|
|
;;
|
|
esac;
|
|
}
|
|
|
|
|
|
help_unit_ctl_http()
|
|
{
|
|
cat <<__EOF__ ;
|
|
SYNOPSIS
|
|
$program_name 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
|
|
$program_name 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";
|
|
|
|
elif ! test -v sock; then
|
|
local sock="$(unit_sock_find)";
|
|
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
|
|
$program_name 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
|
|
$program_name 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";
|
|
|
|
elif ! test -v sock; then
|
|
local sock="$(unit_sock_find)";
|
|
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
|
|
$program_name 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 '\--libstatedir' >/dev/null; then
|
|
echo "$cmd" \
|
|
| sed 's/ --/\n--/g' \
|
|
| grep '\--libstatedir' \
|
|
| cut -d' ' -f2;
|
|
else
|
|
$cmd --help \
|
|
| sed -n '/\--libstatedir/,+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. © 2022</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
|
|
$program_name 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
|
|
$program_name 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
|
|
$program_name 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
|
|
$program_name 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 ax \
|
|
| 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
|
|
$program_name 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
|
|
$ $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;
|
|
|
|
__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_sock()
|
|
{
|
|
cat <<__EOF__ ;
|
|
SYNOPSIS
|
|
$program_name sock [-h] SUBCOMMAND [ARGS]
|
|
|
|
Subcommands
|
|
+-- filter [-ch]
|
|
+-- find [-h]
|
|
|
|
DESCRIPTION
|
|
Print the control API socket address of running unitd(8)
|
|
instances.
|
|
|
|
Run '$program_name 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
|
|
$program_name 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
|
|
$program_name 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 $@;
|
|
;;
|
|
sock)
|
|
shift;
|
|
unit_sock $@;
|
|
;;
|
|
welcome)
|
|
shift;
|
|
unit_ctl_welcome $@;
|
|
;;
|
|
*)
|
|
err "$1: Unknown command.";
|
|
;;
|
|
esac;
|