From e9c1954dc2a677fe36615b5ace5d638bd0bfd133 Mon Sep 17 00:00:00 2001 From: Konstantin Pavlov Date: Tue, 22 Nov 2022 12:39:20 +0100 Subject: Tools: Added setup-unit. Downloaded from . Acked-by: Artem Konev Acked-by: Konstantin Pavlov Signed-off-by: Alejandro Colomar --- tools/setup-unit | 311 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 311 insertions(+) create mode 100755 tools/setup-unit (limited to 'tools') diff --git a/tools/setup-unit b/tools/setup-unit new file mode 100755 index 00000000..2e10e54d --- /dev/null +++ b/tools/setup-unit @@ -0,0 +1,311 @@ +#!/bin/sh + +##################################################################### +# +# Copyright (C) NGINX, Inc. +# +# Author: NGINX Unit Team, F5 Inc. +# Version: 0.0.1 +# Date: 2022-05-05 +# +# This script will configure the repositories for NGINX Unit on Ubuntu, +# Debian, RedHat, CentOS, Oracle Linux, Amazon Linux, Fedora. +# It must be run as root. +# +# Note: curl and awk are required by this script, so the script checks to make +# sure they are installed. +# +##################################################################### + +export LC_ALL=C + +checkOSPrereqs () { + + if ! command -v curl > /dev/null 2>&1 + then + echo "Error: curl not found in PATH. It must be installed to run this script." + exit 1 + fi + + if ! command -v awk > /dev/null 2>&1 + then + echo "Error: awk not found in PATH. It must be installed to run this script." + exit 1 + fi + + return 0 +} + +##################################################################### +# Function getOS +# +# Getting the OS is not the same on all distributions. First, we use +# uname to find out if we are running on Linux or FreeBSD. For all the +# supported versions of Debian and Ubuntu, we expect to find the +# /etc/os-release file which has multiple lines with name-value pairs +# from which we can get the OS name and version. For RedHat and its +# variants, the os-release file may or may not exist, depending on the +# version. If it doesn't, then we look for the release package and +# get the OS and version from the package name. For FreeBSD, we use the +# "uname -rs" command. +# +# A string is written to stdout with three values separated by ":": +# OS +# OS Name +# OS Version +# +# If none of these files was found, an empty string is written. +# +# Return: 0 for success, 1 for error +##################################################################### +getOS () { + + os="" + osName="" + osVersion="" + + LC_ALL=C + + os=$(uname | tr '[:upper:]' '[:lower:]') + + if [ "$os" != "linux" ] && [ "$os" != "freebsd" ]; then + echoErr "Error: Operating system is not Linux or FreeBSD, can't proceed" + echo "On macOS, try 'brew install nginx/unit/unit'" + echo + return 1 + fi + + if [ "$os" = "linux" ]; then + if [ -f "$osRelease" ]; then + # The value for the ID and VERSION_ID may or may not be in quotes + osName=$( grep "^ID=" "$osRelease" | sed s/\"//g | awk -F= '{ print $2 }') + osVersion=$(grep "^VERSION_ID=" "$osRelease" | sed s/\"//g | awk -F= '{ print $2 }') + else + # rhel or centos 6.* + if rpm -q redhat-release-server >/dev/null 2>&1; then + osName=rhel + osVersion=$(rpm -q redhat-release-server |sed 's/.*-//' | awk -F. '{print $1"."$2;}') + elif rpm -q centos-release >/dev/null 2>&1; then + osName=centos + osVersion=$(rpm -q centos-release | sed 's/centos-release-//' | sed 's/\..*//' | awk -F- '{print $1"."$2;}') + else + echoErr "Error: Unable to determine the operating system and version, or the OS is not supported" + echo + return 1 + fi + fi + else + osName=$os + osVersion=$(uname -rs | awk -F '[ -]' '{print $2}') + if [ -z "$osVersion" ]; then + echoErr "Unable to get the FreeBSD version" + echo + return 1 + fi + fi + + # Force osName to lowercase + osName=$(echo "$osName" | tr '[:upper:]' '[:lower:]') + echoDebug "getOS: os=$os osName=$osName osVersion=$osVersion" + echo "$os:$osName:$osVersion" + + return 0 +} + + +installDebian () { + + echoDebug "Install on Debian" + + curl --output /usr/share/keyrings/nginx-keyring.gpg https://unit.nginx.org/keys/nginx-keyring.gpg + + apt install -y apt-transport-https lsb-release ca-certificates + + printf "deb [signed-by=/usr/share/keyrings/nginx-keyring.gpg] https://packages.nginx.org/unit/debian/ %s unit\n" "$(lsb_release -cs)" | tee /etc/apt/sources.list.d/unit.list + printf "deb-src [signed-by=/usr/share/keyrings/nginx-keyring.gpg] https://packages.nginx.org/unit/debian/ %s unit\n" "$(lsb_release -cs)" | tee -a /etc/apt/sources.list.d/unit.list + + apt update + + return 0 +} + +installUbuntu () { + + echoDebug "Install on Ubuntu" + + curl --output /usr/share/keyrings/nginx-keyring.gpg https://unit.nginx.org/keys/nginx-keyring.gpg + + apt install -y apt-transport-https lsb-release ca-certificates + + printf "deb [signed-by=/usr/share/keyrings/nginx-keyring.gpg] https://packages.nginx.org/unit/ubuntu/ %s unit\n" "$(lsb_release -cs)" | tee /etc/apt/sources.list.d/unit.list + printf "deb-src [signed-by=/usr/share/keyrings/nginx-keyring.gpg] https://packages.nginx.org/unit/ubuntu/ %s unit\n" "$(lsb_release -cs)" | tee -a /etc/apt/sources.list.d/unit.list + + apt update + + return 0 +} + +installRedHat () { + + echoDebug "Install on RedHat/CentOS/Oracle" + + case "$osVersion" in + 6|6.*|7|7.*|8|8.*) + cat << __EOF__ > /etc/yum.repos.d/unit.repo +[unit] +name=unit repo +baseurl=https://packages.nginx.org/unit/rhel/\$releasever/\$basearch/ +gpgcheck=0 +enabled=1 +__EOF__ + ;; + *) + echo "Unsupported $osName version: $osVersion" + exit 1 + ;; + esac + + yum makecache + + return 0 +} + +installAmazon () { + + echoDebug "Install on Amazon" + + case "$osVersion" in + 2) + cat << __EOF__ > /etc/yum.repos.d/unit.repo +[unit] +name=unit repo +baseurl=https://packages.nginx.org/unit/amzn2/\$releasever/\$basearch/ +gpgcheck=0 +enabled=1 +__EOF__ + ;; + *) + cat << __EOF__ > /etc/yum.repos.d/unit.repo +[unit] +name=unit repo +baseurl=https://packages.nginx.org/unit/amzn/\$releasever/\$basearch/ +gpgcheck=0 +enabled=1 +__EOF__ + ;; + esac + + yum makecache + + return 0 +} + +installFedora () { + + echoDebug "Install on Fedora" + + cat << __EOF__ > /etc/yum.repos.d/unit.repo +[unit] +name=unit repo +baseurl=https://packages.nginx.org/unit/fedora/\$releasever/\$basearch/ +gpgcheck=0 +enabled=1 +__EOF__ + + dnf makecache + + return 0 +} + + +am_i_root() { + + USERID=$(id -u) + if [ 0 -ne "$USERID" ]; then + echoErr "This script requires root privileges to run; now exiting." + exit 1 + fi + + return 0 +} + +echoErr () { + + echo "$*" 1>&2; +} + +echoDebug () { + + if [ "$debug" -eq 1 ]; then + echo "$@" 1>&2; + fi +} + +main() { +debug=0 # If set to 1, debug message will be displayed + +checkOSPrereqs + +# The name and location of the files that will be used to get Linux +# release info +osRelease="/etc/os-release" + +os="" # Will be "linux" or "freebsd" +osName="" # Will be "ubuntu", "debian", "rhel", + # "centos", "suse", "amzn", or "freebsd" +osVersion="" + +am_i_root + +echo "This script will setup repositories for NGINX Unit" + +# Check the OS +osNameVersion=$(getOS) +if [ -z "$osNameVersion" ]; then + echoErr "Error getting the operating system information" + exit 1 +fi + +# Break out the OS, name, and version +os=$(echo "$osNameVersion" | awk -F: '{print $1}') +osName=$(echo "$osNameVersion" | awk -F: '{print $2}') +osVersion=$(echo "$osNameVersion" | awk -F: '{print $3}') + +# Call the appropriate installation function +case "$osName" in + debian) + installDebian + ;; + ubuntu) + installUbuntu + ;; + rhel) + installRedHat + ;; + centos) + installRedHat + ;; + ol) + installRedHat + ;; + amzn) + installAmazon + ;; + fedora) + installFedora + ;; + *) + echo "$osName is not supported" + exit 1 + ;; +esac + +echo +echo "All done - NGINX Unit repositories for "$osName" "$osVersion" are set up" +echo "Further steps: https://unit.nginx.org/installation/#official-packages" + +} + +main + +exit 0 -- cgit From dfededabdc47caa548c7d7bd62133e0d4df2f0fa Mon Sep 17 00:00:00 2001 From: Liam Crilly Date: Sat, 3 Dec 2022 18:11:14 +0000 Subject: Added tools/README.md. --- tools/README.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 tools/README.md (limited to 'tools') diff --git a/tools/README.md b/tools/README.md new file mode 100644 index 00000000..7dbf0781 --- /dev/null +++ b/tools/README.md @@ -0,0 +1,16 @@ +# Unit Tools + +This directory contains useful tools for installing, configuring, and +managing NGINX Unit. They may not be part of official packages and +should be considered experimental. + +--- + +## setup-unit + +### A script that simplifies installing and configuring an NGINX Unit server for first-time users + +* `setup-unit repo-config` configures your package manager with the NGINX +Unit repository for later installation. +* `setup-unit welcome` creates an initial configuration to serve a welcome +web page with NGINX Unit. -- cgit From 101b262f1feedb7119c8e2cee82657958a31e460 Mon Sep 17 00:00:00 2001 From: Liam Crilly Date: Wed, 14 Dec 2022 16:20:08 +0000 Subject: Tools: Added unitc. --- tools/README.md | 75 ++++++++++++++++++ tools/unitc | 235 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 310 insertions(+) create mode 100755 tools/unitc (limited to 'tools') diff --git a/tools/README.md b/tools/README.md index 7dbf0781..f534aa1f 100644 --- a/tools/README.md +++ b/tools/README.md @@ -4,6 +4,9 @@ This directory contains useful tools for installing, configuring, and managing NGINX Unit. They may not be part of official packages and should be considered experimental. +* [`setup-unit`](#setup-unit) +* [`unitc`](#unitc) + --- ## setup-unit @@ -14,3 +17,75 @@ should be considered experimental. Unit repository for later installation. * `setup-unit welcome` creates an initial configuration to serve a welcome web page with NGINX Unit. + +--- + +## unitc + +### A curl wrapper for managing NGINX Unit configuration + +```USAGE: unitc [options] URI``` + + * **URI** specifies the target in Unit's control API, e.g. `/config` . + * Configuration data is read from stdin. + * [jq](https://stedolan.github.io/jq/) is used to prettify JSON output, if + available. + +| Options | | +|---------|-| +| 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. +| `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. + +Options are case insensitive and can appear in any order. For example, a +redundant part of the configuration can be identified by its URI, and +followed by `delete` in a subsequent command. + +### Local Configuration +For local instances of Unit, the control socket is automatically detected. +The error log is monitored; when changes occur, new log entries are shown. + +| Options | | +|---------|-| +| `-l` \| `--nolog` | Do not monitor the error log after configuration changes. + +#### Examples +```shell +unitc /config +unitc /control/applications/my_app/restart +unitc /config < unitconf.json +echo '{"*:8080": {"pass": "routes"}}' | unitc /config/listeners +unitc /config/applications/my_app DELETE +unitc /certificates/bundle cert.pem key.pem +``` + +### Remote Configuration +For remote instances of NGINX Unit, the control socket on the remote host can +be set with the `$UNIT_CTRL` environment variable. The remote control socket +can be accessed over TCP or SSH, depending on the type of control socket: + + * `ssh://[user@]remote_host[:ssh_port]/path/to/control.socket` + * `http://remote_host:unit_control_port` + +> **Note:** SSH is recommended for remote confguration. Consider the +> [security implications](https://unit.nginx.org/howto/security/#secure-socket-and-state) +> of managing remote configuration over plaintext HTTP. + +| Options | | +|---------|-| +| `ssh://…` | Specify the remote Unix control socket on the command line. +| `http://…`*URI* | For remote TCP control sockets, the URI may include the protocol, hostname, and port. + +#### Examples +```shell +unitc http://192.168.0.1:8080/status +UNIT_CTRL=http://192.168.0.1:8080 unitc /status + +export UNIT_CTRL=ssh://root@unithost/var/run/control.unit.sock +unitc /config/routes +cat catchall_route.json | unitc POST /config/routes +echo '{"match":{"uri":"/wp-admin/*"},"action":{"return":403}}' | unitc INSERT /config/routes +``` + +--- diff --git a/tools/unitc b/tools/unitc new file mode 100755 index 00000000..838f7ebf --- /dev/null +++ b/tools/unitc @@ -0,0 +1,235 @@ +#!/bin/bash +# unitc - a curl wrapper for configuring NGINX Unit +# https://github.com/nginx/unit/tree/master/tools +# NGINX, Inc. (c) 2022 + +# Defaults +# +ERROR_LOG=/dev/null +REMOTE=0 +SHOW_LOG=1 +NOLOG=0 +QUIET=0 +URI="" +SSH_CMD="" +METHOD=PUT +CONF_FILES=() + +while [ $# -gt 0 ]; do + OPTION=$(echo $1 | tr '[a-z]' '[A-Z]') + case $OPTION in + "-H" | "--HELP") + shift + ;; + + "-L" | "--NOLOG" | "--NO-LOG") + NOLOG=1 + shift + ;; + + "-Q" | "--QUIET") + QUIET=1 + shift + ;; + + "GET" | "PUT" | "POST" | "DELETE" | "INSERT") + METHOD=$OPTION + shift + ;; + + "HEAD" | "PATCH" | "PURGE" | "OPTIONS") + echo "${0##*/}: ERROR: Invalid HTTP method ($OPTION)" + exit 1 + ;; + + *) + if [ -r $1 ]; then + CONF_FILES+=($1) + elif [ "${1:0:1}" = "/" ] || [ "${1:0:4}" = "http" ] && [ "$URI" = "" ]; then + URI=$1 + elif [ "${1:0:6}" = "ssh://" ]; then + UNIT_CTRL=$1 + else + echo "${0##*/}: ERROR: Invalid option ($1)" + exit 1 + fi + shift + ;; + esac +done + +if [ "$URI" = "" ]; then + cat << __EOF__ +${0##*/} - a curl wrapper for managing NGINX Unit configuration + +USAGE: ${0##*/} [options] URI + +• URI is for Unit's control API target, e.g. /config +• A local Unit control socket is detected unless a remote one is specified. +• Configuration data is read from stdin. + +General options + filename … # Read configuration data from files instead of stdin + HTTP method # Default=GET, or PUT with config data (case-insensitive) + INSERT # Virtual HTTP method to prepend data to an existing array + -q | --quiet # No output to stdout + +Local options + -l | --nolog # Do not monitor the error log after applying config changes + +Remote options + ssh://[user@]remote_host[:port]/path/to/control.socket # Remote Unix socket + http://remote_host:port/URI # Remote TCP socket + + A remote Unit control socket may also be defined with the \$UNIT_CTRL + environment variable as http://remote_host:port -OR- ssh://… (as above) + +__EOF__ + exit 1 +fi + +# Figure out if we're running on the Unit host, or remotely +# +if [ "$UNIT_CTRL" = "" ]; then + if [ "${URI:0:4}" = "http" ]; then + REMOTE=1 + UNIT_CTRL=$(echo "$URI" | cut -f1-3 -d/) + URI=/$(echo "$URI" | cut -f4- -d/) + fi +elif [ "${UNIT_CTRL:0:6}" = "ssh://" ]; then + REMOTE=1 + SSH_CMD="ssh $(echo $UNIT_CTRL | cut -f1-3 -d/)" + UNIT_CTRL="--unix-socket /$(echo $UNIT_CTRL | cut -f4- -d/) _" +elif [ "${URI:0:1}" = "/" ]; then + REMOTE=1 +fi + +if [ $REMOTE -eq 0 ]; then + # 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 (set \$UNIT_CTRL to configure a remote instance)" + 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 [ -r /tmp/${0##*/}.$PID.env ]; then + source /tmp/${0##*/}.$PID.env + else + # Check we have unitd in $PATH (and all the other tools we will need) + # + MISSING=$(hash unitd curl ps grep tr cut sed tail sleep 2>&1 | cut -f4 -d: | tr -d '\n') + if [ "$MISSING" != "" ]; then + echo "${0##*/}: ERROR: cannot find$MISSING: please install or add to \$PATH" + exit 1 + fi + + # Get control address + # + PARAMS=$(ps $PID | grep unitd | cut -f2- -dv | tr '[]' ' ' | cut -f4- -d ' ' | sed -e 's/ --/\n--/g') + 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 + SOCK_FILE=$(echo $CTRL_ADDR | cut -f2- -d:) + if [ -r $SOCK_FILE ]; then + UNIT_CTRL="--unix-socket $SOCK_FILE _" + else + echo "${0##*/}: ERROR: cannot read unitd control socket: $SOCK_FILE" + ls -l $SOCK_FILE + exit 2 + fi + else + UNIT_CTRL="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 UNIT_CTRL=\"${UNIT_CTRL}\" > /tmp/${0##*/}.$PID.env + echo ERROR_LOG=${ERROR_LOG} >> /tmp/${0##*/}.$PID.env + fi +fi + +# Choose presentation style +# +if [ $QUIET -eq 1 ]; then + OUTPUT="head -c 0" # Equivalent to >/dev/null +elif hash jq 2> /dev/null; then + OUTPUT="jq" +else + OUTPUT="cat" +fi + +# Get current length of error log before we make any changes +# +if [ -f $ERROR_LOG ] && [ -r $ERROR_LOG ]; then + LOG_LEN=$(wc -l < $ERROR_LOG) +else + NOLOG=1 +fi + +# Adjust HTTP method and curl params based on presence of stdin payload +# +if [ -t 0 ] && [ ${#CONF_FILES[@]} -eq 0 ]; then + if [ "$METHOD" = "DELETE" ]; then + $SSH_CMD curl -X $METHOD $UNIT_CTRL$URI 2> /tmp/${0##*/}.$$ | $OUTPUT + else + SHOW_LOG=$(echo $URI | grep -c ^/control/) + $SSH_CMD curl $UNIT_CTRL$URI 2> /tmp/${0##*/}.$$ | $OUTPUT + fi +else + if [ "$METHOD" = "INSERT" ]; then + if ! hash jq 2> /dev/null; then + echo "${0##*/}: ERROR: jq(1) is required to use the INSERT method; install at " + exit 1 + fi + NEW_ELEMENT=$(cat ${CONF_FILES[@]}) + echo $NEW_ELEMENT | jq > /dev/null || exit $? # Test the input is valid JSON before proceeding + OLD_ARRAY=$($SSH_CMD curl -s $UNIT_CTRL$URI) + if [ "$(echo $OLD_ARRAY | jq -r type)" = "array" ]; then + echo $OLD_ARRAY | jq ". |= [$NEW_ELEMENT] + ." | $SSH_CMD curl -X PUT --data-binary @- $UNIT_CTRL$URI 2> /tmp/${0##*/}.$$ | $OUTPUT + else + echo "${0##*/}: ERROR: the INSERT method expects an array" + exit 3 + fi + else + cat ${CONF_FILES[@]} | $SSH_CMD curl -X $METHOD --data-binary @- $UNIT_CTRL$URI 2> /tmp/${0##*/}.$$ | $OUTPUT + fi +fi + +CURL_STATUS=${PIPESTATUS[0]} +if [ $CURL_STATUS -ne 0 ]; then + echo "${0##*/}: ERROR: curl(1) exited with an error ($CURL_STATUS)" + if [ $CURL_STATUS -eq 7 ] && [ $REMOTE -eq 0 ]; then + echo "${0##*/}: Check that you have permission to access the Unit control socket, or try again with sudo(8)" + else + echo "${0##*/}: Trying to access $UNIT_CTRL$URI" + cat /tmp/${0##*/}.$$ && rm /tmp/${0##*/}.$$ + fi + exit 4 +fi +rm /tmp/${0##*/}.$$ 2> /dev/null + +if [ $SHOW_LOG -gt 0 ] && [ $NOLOG -eq 0 ] && [ $QUIET -eq 0 ]; then + echo -n "${0##*/}: Waiting for log..." + sleep $SHOW_LOG + echo "" + sed -n $((LOG_LEN+1)),\$p $ERROR_LOG +fi -- cgit From 3778877eb3be3904edadb9f85553f81cdf32ea43 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Mon, 21 Nov 2022 18:20:26 +0100 Subject: Tools: Added subcommands to setup-unit. This script combines the old setup-unit (as the repo-config command), with new functionality, to provide an easy welcome website for first-time users, and also some more commands that are useful for administrating a running unitd(8) instance. Suggested-by: Liam Crilly Cc: Konstantin Pavlov Cc: Artem Konev Cc: Timo Start Cc: Andrew Clayton Signed-off-by: Alejandro Colomar --- tools/setup-unit | 1611 +++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 1400 insertions(+), 211 deletions(-) (limited to 'tools') diff --git a/tools/setup-unit b/tools/setup-unit index 2e10e54d..286eef87 100755 --- a/tools/setup-unit +++ b/tools/setup-unit @@ -1,311 +1,1500 @@ -#!/bin/sh +#!/usr/bin/env bash ##################################################################### # # Copyright (C) NGINX, Inc. -# # Author: NGINX Unit Team, F5 Inc. -# Version: 0.0.1 -# Date: 2022-05-05 -# -# This script will configure the repositories for NGINX Unit on Ubuntu, -# Debian, RedHat, CentOS, Oracle Linux, Amazon Linux, Fedora. -# It must be run as root. -# -# Note: curl and awk are required by this script, so the script checks to make -# sure they are installed. # ##################################################################### + +if test -n ${BASH_VERSION} && test "${BASH_VERSINFO[0]}" -eq 3; then + >&2 echo 'Your version of bash(1) is not supported by this script.'; + >&2 echo "You're probably running on MacOS. We recommend that you either"; + >&2 echo 'install a newer version of bash(1), or you run this script with'; + >&2 echo 'another shell, like for example zsh(1):'; + >&2 echo " $ zsh ${SUDO_USER:+sudo }$0 ..."; + exit 1; +fi; + + +set -Eefuo pipefail; + +test -v BASH_VERSION \ +&& shopt -s lastpipe; + export LC_ALL=C -checkOSPrereqs () { +program_name="$0"; +prog_name="$(basename $program_name)"; - if ! command -v curl > /dev/null 2>&1 - then - echo "Error: curl not found in PATH. It must be installed to run this script." - exit 1 - fi +dry_run='no'; - if ! command -v awk > /dev/null 2>&1 - then - echo "Error: awk not found in PATH. It must be installed to run this script." - exit 1 - fi +help_unit() +{ + cat <<__EOF__ ; +SYNOPSIS + $program_name [-h] COMMAND [ARGS] + + Subcommands + +-- repo-config [-hn] [PKG-MANAGER OS-NAME OS-VERSION] + +-- welcome [-hn] - return 0 +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 + Creates an initial configuration to serve a welcome web page + for NGINX Unit. + +OPTIONS + -h, --help + Print this help. + + --help-more + Print help for more commands. They are experimental. This is + not recommended unless you know what you're doing. + +__EOF__ } -##################################################################### -# Function getOS -# -# Getting the OS is not the same on all distributions. First, we use -# uname to find out if we are running on Linux or FreeBSD. For all the -# supported versions of Debian and Ubuntu, we expect to find the -# /etc/os-release file which has multiple lines with name-value pairs -# from which we can get the OS name and version. For RedHat and its -# variants, the os-release file may or may not exist, depending on the -# version. If it doesn't, then we look for the release package and -# get the OS and version from the package name. For FreeBSD, we use the -# "uname -rs" command. -# -# A string is written to stdout with three values separated by ":": -# OS -# OS Name -# OS Version -# -# If none of these files was found, an empty string is written. -# -# Return: 0 for success, 1 for error -##################################################################### -getOS () { +help_more_unit() +{ + cat <<__EOF__ ; +SYNOPSIS + $program_name [-h] COMMAND [ARGS] - os="" - osName="" - osVersion="" + 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] - LC_ALL=C +DESCRIPTION + This script simplifies installing and configuring + an NGINX Unit server for first-time users. - os=$(uname | tr '[:upper:]' '[:lower:]') + Run '$program_name COMMAND -h' for more information on a command. - if [ "$os" != "linux" ] && [ "$os" != "freebsd" ]; then - echoErr "Error: Operating system is not Linux or FreeBSD, can't proceed" - echo "On macOS, try 'brew install nginx/unit/unit'" - echo - return 1 - fi +COMMANDS + cmd Print the invocation line of unitd(8). - if [ "$os" = "linux" ]; then - if [ -f "$osRelease" ]; then - # The value for the ID and VERSION_ID may or may not be in quotes - osName=$( grep "^ID=" "$osRelease" | sed s/\"//g | awk -F= '{ print $2 }') - osVersion=$(grep "^VERSION_ID=" "$osRelease" | sed s/\"//g | awk -F= '{ print $2 }') - else - # rhel or centos 6.* - if rpm -q redhat-release-server >/dev/null 2>&1; then - osName=rhel - osVersion=$(rpm -q redhat-release-server |sed 's/.*-//' | awk -F. '{print $1"."$2;}') - elif rpm -q centos-release >/dev/null 2>&1; then - osName=centos - osVersion=$(rpm -q centos-release | sed 's/centos-release-//' | sed 's/\..*//' | awk -F- '{print $1"."$2;}') - else - echoErr "Error: Unable to determine the operating system and version, or the OS is not supported" - echo - return 1 - fi - fi + ctl Control a running unitd(8) instance through its control 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 + This script probes the OS, and prints details about the + version. + + ps List unitd(8) processes. + + repo-config + Configure your package manager with the NGINX Unit + repository for later installation + + sock Print the address of the API control socket. + + welcome + Creates an initial configuration to serve a welcome web page + for NGINX Unit. + +OPTIONS + -h, --help + Print the 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 - osName=$os - osVersion=$(uname -rs | awk -F '[ -]' '{print $2}') - if [ -z "$osVersion" ]; then - echoErr "Unable to get the FreeBSD version" - echo - return 1 - fi - fi + eval "$*"; + fi; +} - # Force osName to lowercase - osName=$(echo "$osName" | tr '[:upper:]' '[:lower:]') - echoDebug "getOS: os=$os osName=$osName osVersion=$osVersion" - echo "$os:$osName:$osVersion" - return 0 +help_unit_cmd() +{ + cat <<__EOF__ ; +SYNOPSIS + $program_name cmd [-h] + +DESCRIPTION + Print the invocation line of running instances of unitd(8). + +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/'; } -installDebian () { +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 socket. + + Run '$program_name ctl SUBCOMMAND -h' for more information on a + subcommand. - echoDebug "Install on Debian" +SUBCOMMANDS + http Send an HTTP request to the control socket. - curl --output /usr/share/keyrings/nginx-keyring.gpg https://unit.nginx.org/keys/nginx-keyring.gpg + insert Insert an element into a specified index in an array in the + JSON configuration. - apt install -y apt-transport-https lsb-release ca-certificates +OPTIONS + -h, --help + Print this help. - printf "deb [signed-by=/usr/share/keyrings/nginx-keyring.gpg] https://packages.nginx.org/unit/debian/ %s unit\n" "$(lsb_release -cs)" | tee /etc/apt/sources.list.d/unit.list - printf "deb-src [signed-by=/usr/share/keyrings/nginx-keyring.gpg] https://packages.nginx.org/unit/debian/ %s unit\n" "$(lsb_release -cs)" | tee -a /etc/apt/sources.list.d/unit.list + -s, --sock SOCK + Use SOCK as the API control socket address. If not specified, + the script will try to find it. This will be used by + subcommands. - apt update + The socket can be a tcp(7) socket or a unix(7) socket, and in + the case of a unix(7) socket, it can be local, or it can be in + a remote machine, accessed through ssh(1). Accepted syntax + for SOCK: - return 0 + 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; you should + have a look at: + + +ENVIRONMENT + Options take precedence over their equivalent environment variables, + so if both are specified, the option will be used. + + UNIT_CTL_SOCK + Equivalent to the option -s (--sock). + +__EOF__ } -installUbuntu () { - echoDebug "Install on Ubuntu" +unit_ctl() +{ - curl --output /usr/share/keyrings/nginx-keyring.gpg https://unit.nginx.org/keys/nginx-keyring.gpg + if test -v UNIT_CTL_SOCK; then + local sock="$UNIT_CTL_SOCK"; + fi; - apt install -y apt-transport-https lsb-release ca-certificates + 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; +} - printf "deb [signed-by=/usr/share/keyrings/nginx-keyring.gpg] https://packages.nginx.org/unit/ubuntu/ %s unit\n" "$(lsb_release -cs)" | tee /etc/apt/sources.list.d/unit.list - printf "deb-src [signed-by=/usr/share/keyrings/nginx-keyring.gpg] https://packages.nginx.org/unit/ubuntu/ %s unit\n" "$(lsb_release -cs)" | tee -a /etc/apt/sources.list.d/unit.list - apt update +help_unit_ctl_http() +{ + cat <<__EOF__ ; +SYNOPSIS + $program_name ctl [CTL-OPTS] http [-h] [-c CURLOPT] METHOD PATH - return 0 +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. It can be used multiple times, which will be + appended (and also appended to the contents of + 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 + + +__EOF__ } -installRedHat () { - echoDebug "Install on RedHat/CentOS/Oracle" +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 into a specified position (INDEX) in the JSON array + in the unitd(8) configuration API at PATH. + + The new element is read from standard input. + +OPTIONS + -h, --help + Print this help. + +SEE ALSO + $program_name ctl http -h; - case "$osVersion" in - 6|6.*|7|7.*|8|8.*) - cat << __EOF__ > /etc/yum.repos.d/unit.repo -[unit] -name=unit repo -baseurl=https://packages.nginx.org/unit/rhel/\$releasever/\$basearch/ -gpgcheck=0 -enabled=1 __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."; ;; *) - echo "Unsupported $osName version: $osVersion" - exit 1 + break; ;; - esac + esac; + shift; + done; - yum makecache + if ! test $# -ge 1; then + err 'ctl: insert: PATH: Missing argument.'; + fi; + local req_path="$1"; - return 0 + 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" \ + "$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; } -installAmazon () { - echoDebug "Install on Amazon" +help_unit_ctl_welcome() +{ + cat <<__EOF__ ; +SYNOPSIS + $program_name welcome [-hn] + +DESCRIPTION + This script tests an NGINX Unit instalation 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 instea of actually + running them. Each command is preceded by a line explaining + what it does. - case "$osVersion" in - 2) - cat << __EOF__ > /etc/yum.repos.d/unit.repo -[unit] -name=unit repo -baseurl=https://packages.nginx.org/unit/amzn2/\$releasever/\$basearch/ -gpgcheck=0 -enabled=1 __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."; + ;; *) - cat << __EOF__ > /etc/yum.repos.d/unit.repo -[unit] -name=unit repo -baseurl=https://packages.nginx.org/unit/amzn/\$releasever/\$basearch/ -gpgcheck=0 -enabled=1 + err "welcome: $1: Unknown argument."; + ;; + esac; + shift; + done; + + id -u \ + | xargs test 0 -ne \ + && err 'welcome: This script requires root privileges to run.'; + + 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="$(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 starting NGINX Unit, see:'; + err " "; + 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 socket."; + + if ! test -v force; then + unit_cmd \ + | read -r cmd; + + # Check unitd is not configured already. + echo "$cmd" \ + | if grep '\--state' >/dev/null; then + echo "$cmd" \ + | sed 's/ --/\n--/g' \ + | grep '\--state' \ + | cut -d' ' -f2; + else + $cmd --help \ + | sed -n '/\--state/,+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 | grep -q '^{}.\?$'; # The '.\?' is for the possible carriage return. + then + warn 'welcome: NGINX Unit is already configured. If you are sure you want'; + err 'to overwrite its current configuration, run 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 "cat >'$www'"' <<__EOF__; + + + + Welcome to NGINX Unit + + + +

Welcome to NGINX Unit

+

Congratulations! NGINX Unit is installed and running.

+

Useful Links

+ + +

Next steps

+ +

Check Current Configuration

+
+

Unit'"'"'s control API is currently listening for configuration changes + on the '"$(unit_sock_find | grep -q '^unix:' && echo 'Unix socket' || echo 'socket')"' at + '"$(unit_sock_find)"'
+ To see the current configuration:

+
'"${SUDO_USER:+sudo }"'curl '"$curl_opt"'/config
+
+ +

Change Listener Port

+
+

This page is served over a random TCP high port. To choose the default HTTP port (80), + replace the "listeners" object:

+
echo '"'"'{"*:80": {"pass": "routes"}}'"'"' | '"${SUDO_USER:+sudo }"'curl -X PUT -d@- '"$curl_opt"'/config/listeners
+ Then remove the port number from the address bar and reload the page. +
+ +
+

NGINX Unit — the universal web app server
+ NGINX, Inc. © 2022

+ + +__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__ - ;; - esac +} - yum makecache - return 0 +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 + #include + #include + #include + #include + #include + + + 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; } -installFedora () { - echoDebug "Install on Fedora" +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 where to insert the element. + +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. - cat << __EOF__ > /etc/yum.repos.d/unit.repo -[unit] -name=unit repo -baseurl=https://packages.nginx.org/unit/fedora/\$releasever/\$basearch/ -gpgcheck=0 -enabled=1 __EOF__ +} - dnf makecache - return 0 +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 .;" } -am_i_root() { +help_unit_os_probe() +{ + cat <<__EOF__ ; +SYNOPSIS + $program_name os-probe [-h] + +DESCRIPTION + This script probes the OS, and prints details about the version. It + prints three fields, delimited by ':'; the first is the package manager, + the second is the OS name, and the third is the OS version. + +OPTIONS + -h, --help + Print this help. + +__EOF__ +} + - USERID=$(id -u) - if [ 0 -ne "$USERID" ]; then - echoErr "This script requires root privileges to run; now exiting." - exit 1 +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 - return 0 + 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" } -echoErr () { - echo "$*" 1>&2; +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__ } -echoDebug () { - if [ "$debug" -eq 1 ]; then - echo "$@" 1>&2; - fi +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 \ + ||: } -main() { -debug=0 # If set to 1, debug message will be displayed -checkOSPrereqs +help_unit_repo_config() +{ + cat <<__EOF__ ; +SYNOPSIS + $program_name repo-config [-hn] [PKG-MANAGER OS-NAME OS-VERSION] -# The name and location of the files that will be used to get Linux -# release info -osRelease="/etc/os-release" +DESCRIPTION + This script configures the NGINX Unit repository for the system + package manager. -os="" # Will be "linux" or "freebsd" -osName="" # Will be "ubuntu", "debian", "rhel", - # "centos", "suse", "amzn", or "freebsd" -osVersion="" + The script automatically detects your OS, and works accordingly. + However, in case the automatic selection fails, you may specify the + package manager and the OS name and version. -am_i_root +ARGUMENTS + PKG-MANAGER + Supported: 'apt', 'dnf', and 'yum'. -echo "This script will setup repositories for NGINX Unit" + OS-NAME + Supported: 'debian', 'ubuntu', 'fedora', 'rhel', and 'amzn2'. -# Check the OS -osNameVersion=$(getOS) -if [ -z "$osNameVersion" ]; then - echoErr "Error getting the operating system information" - exit 1 -fi + OS-VERSION + For most distributions this should be a numeric value, but for + debian derivatives, the codename should be used. -# Break out the OS, name, and version -os=$(echo "$osNameVersion" | awk -F: '{print $1}') -osName=$(echo "$osNameVersion" | awk -F: '{print $2}') -osVersion=$(echo "$osNameVersion" | awk -F: '{print $3}') +OPTIONS + -h, --help + Print this help. -# Call the appropriate installation function -case "$osName" in - debian) - installDebian - ;; - ubuntu) - installUbuntu - ;; - rhel) - installRedHat + -n, --dry-run + Dry run. Print the commands to be run instea 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.'; + + id -u \ + | xargs test 0 -ne \ + && err 'repo-config: This script requires root privileges to run.'; + + 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 ;; - centos) - installRedHat + 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; ;; - ol) - installRedHat + *) + err "repo-config: $pkg_mngr: The package manager isn't supported"; ;; - amzn) - installAmazon + 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: ' +} + + +help_unit_sock() +{ + cat <<__EOF__ ; +SYNOPSIS + $program_name sock [-h] SUBCOMMAND [ARGS] + + Subcommands + +-- filter [-ch] + +-- find [-h] + +DESCRIPTION + Print the address of the control API socket of running instances of + unitd(8). + + 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 to run other commands, such as curl(1) + or ssh(1). + + find Find and print the address of the control API socket of + running instances of unitd(8). + +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 $@; ;; - fedora) - installFedora + find) + shift; + unit_sock_find $@; ;; *) - echo "$osName is not supported" - exit 1 + err "sock: $1: Unknown subcommand."; ;; -esac + esac; +} + -echo -echo "All done - NGINX Unit repositories for "$osName" "$osVersion" are set up" -echo "Further steps: https://unit.nginx.org/installation/#official-packages" +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 to run 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; } -main -exit 0 +help_unit_sock_find() +{ + cat <<__EOF__ ; +SYNOPSIS + $program_name sock find [-h] + +DESCRIPTION + Find and print the address of the control API socket of running + instances of unitd(8). + +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; -- cgit From 789095b8a04fcf16110f436c271213af054411cf Mon Sep 17 00:00:00 2001 From: Artem Konev Date: Wed, 14 Dec 2022 21:17:01 +0000 Subject: Tools: Updated built-in 'setup-unit' help, README.md command lines. --- tools/setup-unit | 129 +++++++++++++++++++++++++++---------------------------- 1 file changed, 63 insertions(+), 66 deletions(-) (limited to 'tools') diff --git a/tools/setup-unit b/tools/setup-unit index 286eef87..79dab850 100755 --- a/tools/setup-unit +++ b/tools/setup-unit @@ -9,10 +9,10 @@ if test -n ${BASH_VERSION} && test "${BASH_VERSINFO[0]}" -eq 3; then - >&2 echo 'Your version of bash(1) is not supported by this script.'; - >&2 echo "You're probably running on MacOS. We recommend that you either"; - >&2 echo 'install a newer version of bash(1), or you run this script with'; - >&2 echo 'another shell, like for example zsh(1):'; + >&2 echo 'Your version of bash(1) isn't supported by this script.'; + >&2 echo "You're probably running on macOS. We recommend that you either"; + >&2 echo 'install a newer version of bash(1) or run this script with'; + >&2 echo 'another shell, such as zsh(1):'; >&2 echo " $ zsh ${SUDO_USER:+sudo }$0 ..."; exit 1; fi; @@ -52,16 +52,16 @@ COMMANDS for later installation. welcome - Creates an initial configuration to serve a welcome web page - for NGINX Unit. + 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. This is - not recommended unless you know what you're doing. + Print help for more commands. They are experimental. Using + these isn't recommended, unless you know what you're doing. __EOF__ } @@ -96,7 +96,7 @@ DESCRIPTION COMMANDS cmd Print the invocation line of unitd(8). - ctl Control a running unitd(8) instance through its control socket. + ctl Control a running unitd(8) instance via its control API socket. freeport Print an available TCP port. @@ -106,24 +106,23 @@ COMMANDS array read from a file at a given INDEX. os-probe - This script probes the OS, and prints details about the - version. + 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 + repository for later installation. - sock Print the address of the API control socket. + sock Print the control API socket address. welcome - Creates an initial configuration to serve a welcome web page - for NGINX Unit. + Create an initial configuration to serve a welcome web page + with NGINX Unit. OPTIONS -h, --help - Print the basic help (some commands are hidden). + Print basic help (some commands are hidden). --help-more Print the hidden help with more commands. @@ -166,7 +165,7 @@ SYNOPSIS $program_name cmd [-h] DESCRIPTION - Print the invocation line of running instances of unitd(8). + Print the invocation line of running unitd(8) instances. OPTIONS -h, --help @@ -210,15 +209,15 @@ SYNOPSIS +-- insert [-h] PATH INDEX DESCRIPTION - Control a running unitd(8) instance through its control socket. + 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 socket. + http Send an HTTP request to the control API socket. - insert Insert an element into a specified index in an array in the + insert Insert an element at the specified index into an array in the JSON configuration. OPTIONS @@ -226,12 +225,11 @@ OPTIONS Print this help. -s, --sock SOCK - Use SOCK as the API control socket address. If not specified, - the script will try to find it. This will be used by - subcommands. + 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, and in - the case of a unix(7) socket, it can be local, or it can be in + 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: @@ -239,13 +237,12 @@ OPTIONS ssh://[user@]host[:port]/path/to/control.sock [http[s]://]host[:port] - The last form is less secure than the first two; you should - have a look at: + The last form is less secure than the first two; have a look: ENVIRONMENT - Options take precedence over their equivalent environment variables, - so if both are specified, the option will be used. + 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). @@ -324,9 +321,8 @@ 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. It can be used multiple times, which will be - appended (and also appended to the contents of - UNIT_CTL_HTTP_CURLOPTS). + behavior. The option can be cumulatively used multiple times + (the result is also appended to UNIT_CTL_HTTP_CURLOPTS). -h, --help Print this help. @@ -425,8 +421,8 @@ SYNOPSIS $program_name ctl [CTL-OPTS] insert [-h] PATH INDEX DESCRIPTION - Insert an element into a specified position (INDEX) in the JSON array - in the unitd(8) configuration API at PATH. + 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. @@ -518,7 +514,7 @@ SYNOPSIS $program_name welcome [-hn] DESCRIPTION - This script tests an NGINX Unit instalation by creating an initial + This script tests an NGINX Unit installation by creating an initial configuration and serving a welcome web page. Recommended for first-time users. @@ -527,7 +523,7 @@ OPTIONS Print this help. -n, --dry-run - Dry run. Print the commands to be run instea of actually + Dry run. Print the commands to be run instead of actually running them. Each command is preceded by a line explaining what it does. @@ -580,7 +576,7 @@ unit_ctl_welcome() if test 0 -eq "$nprocs"; then warn "welcome: NGINX Unit isn't running."; - warn 'For help starting NGINX Unit, see:'; + warn 'For help with starting NGINX Unit, see:'; err " "; elif test 1 -ne "$nprocs"; then err 'welcome: Only one NGINX Unit instance should be running.'; @@ -590,7 +586,7 @@ unit_ctl_welcome() local curl_opt="$(unit_sock_find | unit_sock_filter -c)"; curl $curl_opt/ >/dev/null 2>&1 \ - || err "welcome: Can't reach the control socket."; + || err "welcome: Can't reach the control API socket."; if ! test -v force; then unit_cmd \ @@ -616,8 +612,8 @@ unit_ctl_welcome() if test -e $conffile; then if ! unit_ctl_http ---s "$sock" 'GET' '/config' /dev/null | grep -q '^{}.\?$'; # The '.\?' is for the possible carriage return. then - warn 'welcome: NGINX Unit is already configured. If you are sure you want'; - err 'to overwrite its current configuration, run again with --force.'; + warn 'welcome: NGINX Unit is already configured. To overwrite'; + err 'its current configuration, run the script again with --force.'; fi; fi; fi; @@ -835,7 +831,7 @@ SYNOPSIS ARGUMENTS JSON Path to a JSON file containing a top-level array. - INDEX Position in the array where to insert the element. + INDEX Position in the array to insert the element at. DESCRIPTION Insert a JSON element read from standard input into a JSON array read @@ -906,9 +902,9 @@ SYNOPSIS $program_name os-probe [-h] DESCRIPTION - This script probes the OS, and prints details about the version. It - prints three fields, delimited by ':'; the first is the package manager, - the second is the OS name, and the third is the OS version. + 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 @@ -939,7 +935,7 @@ unit_os_probe() 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." + err "os-probe: The OS isn't Linux or FreeBSD; can't proceed." fi if [ "$os" = 'linux' ]; then @@ -960,14 +956,14 @@ unit_os_probe() 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" + 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' + err 'os-probe: Unable to get the FreeBSD version.' fi fi @@ -1059,8 +1055,8 @@ DESCRIPTION This script configures the NGINX Unit repository for the system package manager. - The script automatically detects your OS, and works accordingly. - However, in case the automatic selection fails, you may specify the + 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 @@ -1071,15 +1067,15 @@ ARGUMENTS Supported: 'debian', 'ubuntu', 'fedora', 'rhel', and 'amzn2'. OS-VERSION - For most distributions this should be a numeric value, but for - debian derivatives, the codename should be used. + 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 instea of actually + Dry run. Print the commands to be run instead of actually running them. Each command is preceded by a line explaining what it does. @@ -1202,7 +1198,7 @@ __EOF__"; installAPT "$pkg_mngr" "$os_name" ${3:+$os_version}; ;; *) - err "repo-config: $os_name: The OS isn't supported"; + err "repo-config: $os_name: The OS isn't supported."; ;; esac ;; @@ -1212,12 +1208,12 @@ __EOF__"; installYumDnf "$pkg_mngr" "$os_name" "$os_version" ${3:+ovr}; ;; *) - err "repo-config: $os_name: The OS isn't supported"; + err "repo-config: $os_name: The OS isn't supported."; ;; esac; ;; *) - err "repo-config: $pkg_mngr: The package manager isn't supported"; + err "repo-config: $pkg_mngr: The package manager isn't supported."; ;; esac; @@ -1239,19 +1235,19 @@ SYNOPSIS +-- find [-h] DESCRIPTION - Print the address of the control API socket of running instances of - unitd(8). + 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 to run other commands, such as curl(1) - or ssh(1). + 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 address of the control API socket of - running instances of unitd(8). + find Find and print the control API socket address of running + unitd(8) instances. OPTIONS -h, --help @@ -1306,8 +1302,9 @@ SYNOPSIS $program_name sock filter [-chs] DESCRIPTION - Filter the output of the 'sock find' command, and transform it to - something suitable to run other commands, such as curl(1) or ssh(1). + 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 @@ -1384,8 +1381,8 @@ SYNOPSIS $program_name sock find [-h] DESCRIPTION - Find and print the address of the control API socket of running - instances of unitd(8). + Find and print the control API socket address of running + unitd(8) instances. OPTIONS -h, --help -- cgit